@classmethod和@cm从下面的代码有什么区别?
装饰器在创建实例之前的类创建时调用。
对于您的情况,由于@cm返回func(self.__class__, *args, **kwargs)
,依赖于self
,因此应将其用作实例方法。
另一方面,@classmethod可以在创建实例之前使用。
def cm(func):
def decorated(self, *args, **kwargs):
return func(self.__class__, *args, **kwargs)
return decorated
class C:
@classmethod
def inc1(cls):
(blablabla)
@cm
def inc3(cls):
(blablabla)
C().inc1() # works as a instance method
C.inc1() # works as a classmethod
C().inc3() # works as a instance method
C.inc3() # TypeError: unbound method decorated() must be called with C instance as first argument (got nothing instead)
对于类方法和属性的组合,它可以通过返回一个自定义对象来完成。 Reference
class ClassPropertyDescriptor(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, klass=None):
if klass is None:
klass = type(obj)
return self.f.__get__(obj, klass)()
def classproperty(func):
if not isinstance(func, (classmethod, staticmethod)):
func = classmethod(func)
return ClassPropertyDescriptor(func)
class C:
@classproperty
def inc1(cls):
(blablabla)
C.inc1 # works as a classmethod property
[编辑]
问:什么是类方法()调用做的方法是装饰来实现呢?
实现可以通过使用descriptor
class ClassMethodDescriptor(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, klass=None):
if klass is None:
klass = type(obj)
def newfunc(*args):
return self.f(klass, *args)
return newfunc
def myclassmethod(func):
return ClassMethodDescriptor(func)
class C:
@myclassmethod
def inc1(cls):
(blablabla)
C.inc1() # works as a classmethod
问:为什么结果不调用来完成?
因为执行ClassMethodDescriptor
没有定义__call__
函数。一旦使用@property
,它将返回不可调用的ClassMethodDescriptor。
你写过那个classmethods不需要一个实例。 classmethod()调用使用它所实现的方法进行修饰的方法是什么?为什么结果不可调用? – VPfB
我更新了我的答案。希望这会对你有所帮助。 –
谢谢,现在更清楚了。 '@ classmethod'将函数转换为描述符。调用这个描述符返回一个可调用的函数。最后缺失的部分是为什么它是这样设计的。我只能猜测主要原因是“_调用的细节取决于obj是一个对象还是一个class._”(来源:docs.python.org上的Descriptor HowTo指南)。这使得区分这两种情况成为可能,因此提供了正确的“cls”作为第一个参数。正如我所说,只是猜测。 – VPfB