What does classmethod do except changing self to cls?
有一个关于
我还是不明白问题的原因,请帮忙。
我对
那么,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 |
what is the difference between @classmethod and @cm from the code below?
在类创建期间,在创建实例之前,decorator正在调用。
在您的例子中,@cm返回
另一方面,@classmethod可以在创建实例之前使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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和属性的组合,可以通过返回自定义对象来完成。参考文献
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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?
可以通过使用描述符来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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?
因为
区别在于ClassMethod不可调用,而CM方法可调用。这意味着,当属性(类)调用输入的func(它应该这样做)时,它的工作方式与除了cm以外的其他方式相同,但对classmethod无效,因为classmethod没有实现调用。
类方法不知道任何有关实例的信息,也不需要它。实例方法知道它的实例和类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
另外,正如您所看到的,您不需要实例来调用ClassMethod。