是否有一种简单的方法可以在课程中的每个函数的开头和结尾处执行某些操作?我调查了__getattribute__
,但我认为在这种情况下我不能使用它吗?
以下是我正在尝试做的简化版本:
class Thing():
def __init__(self):
self.busy = False
def func_1(self):
if self.busy:
return None
self.busy = True
...
self.busy = False
def func_2(self):
if self.busy:
return None
self.busy = True
...
self.busy = False
...
答案 0 :(得分:11)
您可以使用装饰器(如果您不了解它们,可以参考PEP-318):
def decorator(method):
def decorated_method(self, *args, **kwargs):
# before the method call
if self.busy:
return None
self.busy = True
# the actual method call
result = method(self, *args, **kwargs)
# after the method call
self.busy = False
return result
return decorated_method
class Thing():
def __init__(self):
self.busy = False
@decorator
def func_1(self):
...
@decorator
def func_2(self):
...
如果您希望装饰的方法看起来像"您可能希望使用functools.wraps
。原始方法。 @decorator
只是语法糖,你也可以明确地应用装饰器:
class Thing():
def __init__(self):
self.busy = False
def func_1(self):
...
func_1 = decorator(func_1) # replace "func_1" with the decorated "func_1"
如果您真的想将它应用于所有方法,您还可以使用类装饰器:
def decorate_all_methods(cls):
for name, method in cls.__dict__.items():
if name.startswith('_'): # don't decorate private functions
continue
setattr(cls, name, decorator(method))
return cls
@decorate_all_methods
class Thing():
def __init__(self):
self.busy = False
def func_1(self):
...
def func_2(self):
...
答案 1 :(得分:1)
作为已接受答案的替代方法,如果您希望此装饰仅适用于实例方法,则可以使用__getattribute__
。
class Thing(object):
def __init__(self):
self.busy = False
def __getattribute__(self, name):
attr = object.__getattribute__(self, name)
if callable(attr) and not name.startswith('_') and attr.__self__ == self:
attr = decorator(attr)
return attr
def func_1(self):
# instance method will be wrapped by `decorator`
...
@classmethod
def class_func(cls):
# class method will not be wrapped by `decorator`
# when called using `self.`, `cls.` or `Thing.`.
...
@staticmethod
def static_func():
# static method will not be wrapped by `decorator`
# when called using `Thing.`.
...
object
,并且不适用于Python 2中的旧式类。callable
已在Python 3.0中删除,但在3.2中返回。或者,可以使用isinstance(obj, collections.Callable)
。如果您想以不同方式包装类方法和静态方法,可以从自定义type
metaclass
继承:
class Meta(type):
def __getattribute__(*args):
print("staticmethod or classmethod invoked")
return type.__getattribute__(*args)
class Thing(object, metaclass=Meta):
...
def __getattribute__(self, name):
attr = object.__getattribute__(self, name)
if callable(attr) and not name.startswith('_'):
if attr.__self__ == self:
attr = decorator(attr)
else:
attr = Meta.__getattribute__(Thing, name)
return attr
以上metaclass=Meta
是Python 3语法。在Python 2中,它必须定义为:
class Thing(object):
__metaclass__ = Meta