问题
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