的Python:任何不妥动态分配的实例方法的实例属性
问题描述:
我使用需要实例本身作为一个参数一个装饰想出了下面的代码来装饰实例方法:的Python:任何不妥动态分配的实例方法的实例属性
from functools import wraps
def logging_decorator(tricky_instance):
def wrapper(fn):
@wraps(fn)
def wrapped(*a, **kw):
if tricky_instance.log:
print("Calling %s.." % fn.__name__)
return fn(*a, **kw)
return wrapped
return wrapper
class Tricky(object):
def __init__(self, log):
self.log = log
self.say_hi = logging_decorator(self)(self.say_hi)
def say_hi(self):
print("Hello, world!")
i1 = Tricky(log=True)
i2 = Tricky(log=False)
i1.say_hi()
i2.say_hi()
这似乎工作的伟大,但我担心我可能忽略了这个技巧的一些无意的副作用。我是要在脚下自杀吗?还是安全?
请注意,我实际上并不想将其用于日志记录,这只是我能想到的最短有意义的示例。
答
我认为我试图变得不必要的聪明。似乎有一个令人尴尬的更简单的解决方案:
from functools import wraps
def logging_decorator(fn):
@wraps(fn)
def wrapped(self, *a, **kw):
if self.log:
print("Calling %s.." % fn.__name__)
return fn(self, *a, **kw)
return wrapped
class Tricky(object):
def __init__(self, log):
self.log = log
@logging_decorator
def say_hi(self):
print("Hello, world!")
i1 = Tricky(log=True)
i2 = Tricky(log=False)
i1.say_hi()
i2.say_hi()
答
我不清楚为什么你会想要这样做。如果要设定新的方法类型动态地使用types
:
import types
class Tricky(object):
def __init__(self):
def method(self):
print('Hello')
self.method = types.MethodType(method, self)
如果你想要做的事情况下,做到这一点的方法__init__
。如果你只是想装饰内部访问方法的情况下,你可以使用im_self
属性:
def decorator(tricky_instance):
def wrapper(meth):
print(meth.im_self == tricky_instance)
return meth
return wrapper
就个人而言,我认为这是于水火到也许-I-Shouldn't-USE-装饰的土地。
看起来合法。恕我直言。 – Evpok