classmethod除了把self改成cls还有什么作用?
What does classmethod do except changing self to cls?
关于 classmethod
和 property
组合在一起的问题已回答:Using property() on classmethods
问题的原因还是不太明白,求助
我对classmethod
的理解是,它只是简单地将self
替换为cls
。考虑到这一点,我在过去的几年里写了几个类方法,现在我发现我一直都错了。
那么从下面的代码来看,@classmethod
和 @cm
有什么区别呢?
def cm(func):
def decorated(self, *args, **kwargs):
return func(self.__class__, *args, **kwargs)
return decorated
class C:
V = 0
@property
@classmethod
def inc1(cls):
cls.V += 1
print("V1 =", cls.V)
@property
@cm
def inc3(cls):
cls.V += 3
print("V3 =", cls.V)
c = C()
#c.inc1 # fails with: TypeError: 'classmethod' object is not callable
c.inc3 # works
inc3
与 cm
有效,但 inc1
与 classmethod
无效。
class 方法对实例一无所知,也不需要它。
实例方法知道它的实例并且它是 class.
class Foo:
some = 'some'
class Bar(Foo):
def __init__(self):
self.some = 'not some'
@classmethod
def cls_some(cls):
print(cls.some)
def instance_some(self):
print(self.some)
Bar.cls_some()
>>>some
Bar().instance_some()
>>>not some
另外如您所见,您不需要实例来调用 class 方法。
区别是class方法是不可调用的,而cm方法是可调用的。这意味着当 属性(class) 调用输入的 func(它应该这样做)时,它会像你一样工作,除了 cm,但不适用于 classmethod 因为 classmethod 没有实现 call。
what is the difference between @classmethod and @cm from the code below?
装饰器在创建实例之前的 class 创建时间内调用。
在你的例子中,由于依赖于self
的@cm returns func(self.__class__, *args, **kwargs)
,它应该被用作实例方法。
另一方面,@class方法可以在创建实例之前使用。
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)
对于class方法和属性的组合,可以通过return自定义对象来完成。 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
[编辑]
Q. What does the classmethod() call do with the method it decorates to achieve that?
可以使用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
Q. Why is the result not callable?
因为ClassMethodDescriptor
的实现没有定义__call__
函数。一旦使用 @property
,它将 return 不可调用的 ClassMethodDescriptor。
关于 classmethod
和 property
组合在一起的问题已回答:Using property() on classmethods
问题的原因还是不太明白,求助
我对classmethod
的理解是,它只是简单地将self
替换为cls
。考虑到这一点,我在过去的几年里写了几个类方法,现在我发现我一直都错了。
那么从下面的代码来看,@classmethod
和 @cm
有什么区别呢?
def cm(func):
def decorated(self, *args, **kwargs):
return func(self.__class__, *args, **kwargs)
return decorated
class C:
V = 0
@property
@classmethod
def inc1(cls):
cls.V += 1
print("V1 =", cls.V)
@property
@cm
def inc3(cls):
cls.V += 3
print("V3 =", cls.V)
c = C()
#c.inc1 # fails with: TypeError: 'classmethod' object is not callable
c.inc3 # works
inc3
与 cm
有效,但 inc1
与 classmethod
无效。
class 方法对实例一无所知,也不需要它。 实例方法知道它的实例并且它是 class.
class Foo:
some = 'some'
class Bar(Foo):
def __init__(self):
self.some = 'not some'
@classmethod
def cls_some(cls):
print(cls.some)
def instance_some(self):
print(self.some)
Bar.cls_some()
>>>some
Bar().instance_some()
>>>not some
另外如您所见,您不需要实例来调用 class 方法。
区别是class方法是不可调用的,而cm方法是可调用的。这意味着当 属性(class) 调用输入的 func(它应该这样做)时,它会像你一样工作,除了 cm,但不适用于 classmethod 因为 classmethod 没有实现 call。
what is the difference between @classmethod and @cm from the code below?
装饰器在创建实例之前的 class 创建时间内调用。
在你的例子中,由于依赖于self
的@cm returns func(self.__class__, *args, **kwargs)
,它应该被用作实例方法。
另一方面,@class方法可以在创建实例之前使用。
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)
对于class方法和属性的组合,可以通过return自定义对象来完成。 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
[编辑]
Q. What does the classmethod() call do with the method it decorates to achieve that?
可以使用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
Q. Why is the result not callable?
因为ClassMethodDescriptor
的实现没有定义__call__
函数。一旦使用 @property
,它将 return 不可调用的 ClassMethodDescriptor。