Python: Do something for any method of a class?

纵饮孤独 提交于 2019-12-21 07:18:20

问题


Say I have a class with a bunch of methods:

class Human():

  def eat():
    print("eating")

  def sleep():
    print("sleeping")

  def throne():
    print("on the throne")

Then I run all the methods with

John=Human()
John.eat()
John.sleep()
John.throne()

I want to run print("I am") for each method being called. So I should get something like

I am:
eating
I am:
sleeping
I am:
on the throne

Is there a way to do this without having to reformat each method?


回答1:


If you can't change how you call your methods you can use the __getattribute__ magic method (methods are attributes too remember!) you just have to be careful to check the type of attributes so you don't print "I am:" every time you want to access any string or int attributes you may have:

class Human(object):
    def __getattribute__(self, attr):
        method = object.__getattribute__(self, attr)
        if not method:
            raise Exception("Method %s not implemented" % attr)
        if callable(method):
             print "I am:"
        return method

    def eat(self):
        print "eating"

    def sleep(self):
       print "sleeping"

    def throne(self):
        print "on the throne"

John = Human()
John.eat()
John.sleep()
John.throne()

Outputs:

I am:
eating
I am:
sleeping
I am:
on the throne



回答2:


You can do this if you don't mind adding an __init__ and __call__ method to your class and self to your method's arguments.

class Human():
    def __init__(self):
        return None
    def __call__(self, act):
        print "I am:"
        method = getattr(self, act)
        if not method:
            raise Exception("Method %s not implemented" % method_name)
        method()

    def eat(self):
        print "eating"

    def sleep(self):
        print "sleeping"

    def throne(self):
        print "on the throne"

John = Human()
John("eat")
John("sleep")
John("throne")

EDIT: see my other answer for a better solution




回答3:


If you want to have arguments as well, you can try using metaprogramming to alter the class methods themselves to run a pre/post operation, like the answer to How to run a method before/after all class function calls with arguments passed?



来源:https://stackoverflow.com/questions/26037533/python-do-something-for-any-method-of-a-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!