В чем разница между @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)
Для комбинации classmethod и имущества, это может быть сделано путем возвращать пользовательский объект. 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. Что Метод класса() вызов сделать с помощью метода он декорирует для достижения этой цели?
Реализация может быть сделано с помощью 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.Почему результат не может быть вызван?
Поскольку реализация ClassMethodDescriptor
не определяет функцию __call__
. После использования @property
он вернет ClassMethodDescriptor, который не может быть вызван.
Вы написали, что classmethods не нужен экземпляр. Что вызывает вызов classmethod() с методом, который он украшает для достижения этого? Почему результат не может быть вызван? – VPfB
Я обновил свой ответ. Надеюсь, это будет полезно для вас. –
Спасибо, теперь понятно. '@ classmethod' преобразует функцию в дескриптор. Вызов этих дескрипторов возвращает вызываемую функцию. Последний недостающий элемент - это то, почему он был разработан таким образом. Я могу только догадываться, что главная причина заключается в том, что «детали вызова зависят от того, является ли obj объектом или классом.» (Source: Descriptor HowTo Guide на docs.python.org). Это позволяет различать эти два случая и, таким образом, предоставлять в качестве первого аргумента правые 'cls'. Как я уже сказал, просто гадать. – VPfB