我正在尝试编写装饰器,根据它来做不同的工作,无论是装饰方法还是功能。
我试过这样的事情:
def dec(f):
def wrapper(*v, **kv):
if '__class__' in dir(f):
text = "Its a method"
else:
text = "Its a function"
print(text)
return f(*v, **kv)
return wrapper
class A:
@dec
def f(self):
pass
@dec
def f():
pass
a = A()
a.f()
f()
它返回:
Its a method
Its a method
但这不起作用,因为所有函数也都有__class__
属性:)我也尝试在Af上做inspect.ismethod
但Af就像函数一样被处理但在A命名空间中它返回当然是假的。如果我们已经完成了inspect.ismethod(a.f),其中a
是A
的实例,那么它将返回True,但我迫不及待想要实例。
答案 0 :(得分:1)
正如Martijn在他的评论中已经解释过的那样,在一个类语句中定义的函数不会使函数成为一个方法 - 方法对象是在查找时创建的,正如here所解释的那样 - 所以你要装饰的是并将永远(几乎在下面cf)成为一个功能。 FWIW,Python的“方法”只是围绕函数,类和(最终)实例的瘦包装。
除了函数之外你唯一可能得到的东西是classmethods和staticmethods(在这种情况下你会得到一个classmethod
或staticmethod
对象),即使这样,它依赖于关于装饰者的命令。
如果你想在装饰器中获取方法的当前实例(或类),你知道它将永远是第一个位置参数 - 但这可能不是很有帮助...总而言之,你必须明确地告诉装饰者它是否应该将函数视为普通函数或方法,或者用自定义描述符装饰它,在这种情况下你会知道函数是否已经被查找为方法。 ..天真的实现看起来像这样:
class MyDecorator(object):
def __init__(self, func, instance=None):
self.func = func
self.instance = instance
def __call__(self, *args, **kw):
if self.instance:
print "is method - instance : %s" % self.instance
args = (self.instance,) + args
else:
print "is_function"
return self.func(*args, **kw)
def __get__(self, instance, cls):
return type(self)(self.func, instance)