【发布时间】:2018-11-23 15:12:14
【问题描述】:
我有一个名为Special 的装饰器,它将一个函数转换为它自己的两个版本:一个可以直接调用并在结果前面加上'regular ',另一个可以用.special 调用并在结果前面加上前缀'special ':
class Special:
def __init__(self, func):
self.func = func
def __get__(self, instance, owner=None):
if instance is None:
return self
return Special(self.func.__get__(instance, owner))
def special(self, *args, **kwargs):
return 'special ' + self.func(*args, **kwargs)
def __call__(self, *args, **kwargs):
return 'regular ' + self.func(*args, **kwargs)
它适用于常规方法和静态方法 - 但 .special 不适用于类方法:
class Foo:
@Special
def bar(self):
return 'bar'
@staticmethod
@Special
def baz():
return 'baz'
@classmethod
@Special
def qux(cls):
return 'qux'
assert Foo().bar() == 'regular bar'
assert Foo().bar.special() == 'special bar'
assert Foo.baz() == 'regular baz'
assert Foo.baz.special() == 'special baz'
assert Foo.qux() == 'regular qux'
assert Foo.qux.special() == 'special qux' # TypeError: qux() missing 1 required positional argument: 'cls'
Foo().bar正在调用__get__,它绑定底层函数并将绑定的方法传递给Special的新实例 - 这就是Foo().bar()和Foo().bar.special()都工作的原因。Foo.baz只是返回原始的Special实例 - 其中常规和特殊调用都很简单。-
Foo.qux绑定而不调用我的__get__。- 新绑定对象知道在直接调用时将类作为第一个参数传递 - 所以
Foo.qux()有效。 -
Foo.qux.special只是调用底层函数的.special(classmethod不知道如何绑定它) - 所以Foo.qux.special()正在调用一个未绑定的函数,因此是TypeError。
- 新绑定对象知道在直接调用时将类作为第一个参数传递 - 所以
有没有办法让Foo.qux.special 知道它是从classmethod 调用的?或者其他解决这个问题的方法?
【问题讨论】:
标签: python python-decorators class-method