@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