除了将自己改为cls之外,classmethod做了什么?

时间:2016-11-14 16:15:10

标签: python class-method

关于view1.setVisibility(View.GONE) view2.setVisibility(View.VISIBLE)classmethod合并在一起的问题已得到解答:Using property() on classmethods

我仍然不了解问题的原因,请帮助。

我对property的理解是,它只是将classmethod替换为self。考虑到这一点,我在过去的几年中写了几个类方法,现在我发现自己错了。

那么下面的代码中cls@classmethod之间有什么区别?

@cm
<{1}} 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有效。{/ p>

3 个答案:

答案 0 :(得分:2)

  

下面的代码中@classmethod和@cm有什么区别?

decorator在创建实例之前的类创建时调用。

在您的情况下,由于@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和property的组合,可以通过返回自定义对象来完成。 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值。 classmethod()调用它所装饰的方法做什么呢?

可以使用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。

答案 1 :(得分:0)

不同之处在于classmethod不可调用,cm方法可调用。这意味着当属性(类)调用输入的func(它应该这样做)时,除了cm之外,它会像你一样工作,但是因为classmethod没有,所以不适用于classmethod致电已实施。

答案 2 :(得分:-1)

类方法对实例一无所知,也不需要它。 instance方法知道它的实例和它的类。

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。