@classmethod和python中的方法之间的区别

时间:2013-07-31 08:27:53

标签: python

@classmethod和python中的'经典'方法有什么区别,

我应该何时使用@classmethod,何时应该在python中使用'经典'方法。 classmethod必须是一个被引用给类的方法(我的意思是它只是一个处理类的方法)?

我知道@staticmethod和经典方法之间有什么区别 THX

3 个答案:

答案 0 :(得分:5)

如果在类中定义一个方法,它将以一种特殊的方式处理:对它的访问将其包装在一个特殊的对象中,该对象修改调用参数以包含self,这是对引用对象的引用:

class A(object):
    def f(self):
        pass

a = A()
a.f()

a.f的来电实际上会f(通过descriptor protocol)要求对象真正返回。然后在不带参数的情况下调用此对象,并将调用转移到真实f,并在前面添加a

那么a.f()真正做的是调用原始的f函数并将(a)作为参数。

为了防止这种情况,我们可以包装函数

  1. 使用@staticmethod装饰器,
  2. 使用@classmethod装饰器,
  3. 与其他一个类似的工作,自制的装饰师。
  4. @staticmethod将它变成一个对象,当被问到时,它会改变参数传递行为,使其与调用原始f的意图相符:

    class A(object):
        def method(self):
            pass
        @staticmethod
        def stmethod():
            pass
        @classmethod
        def clmethod(cls):
            pass
    
    a = A()
    a.method() # the "function inside" gets told about a
    A.method() # doesn't work because there is no reference to the needed object
    a.clmethod() # the "function inside" gets told about a's class, A
    A.clmethod() # works as well, because we only need the classgets told about a's class, A
    a.stmethod() # the "function inside" gets told nothing about anything
    A.stmethod() # works as well
    

    所以@classmethod@staticmethod有一个共同点,就是他们“不关心”他们被召唤的具体对象;区别在于@staticmethod根本不想知道任何事情,而@classmethod想知道它的类。

    因此后者获取类对象所使用的对象是其实例。在这种情况下,只需将self替换为cls

    现在,何时使用什么?

    嗯,这很容易处理:

    • 如果您有权访问self,则显然需要实例方法。
    • 如果您不访问self,但想要了解其类,请使用@classmethod。例如,这可以是工厂方法的情况。 datetime.datetime.now()就是这样一个例子:您可以通过其类或实例调用它,但它会创建一个具有完全不同数据的新实例。我甚至使用它们一次来自动生成给定类的子类。
    • 如果您既不需要self也不需要cls,则可以使用@staticmethod。如果他们不需要关心子类化,这也可以用于工厂方法。

答案 1 :(得分:4)

假设您有一个类Car,它代表系统中的Car实体。

classmethod是一种适用于Car类的方法,不适用于任何Car个实例之一。因此,用@classmethod修饰的函数的第一个参数(通常称为cls)就是类本身。例如:

class Car(object):    
    colour = 'red'

    @classmethod
    def blue_cars(cls):
        # cls is the Car class
        # return all blue cars by looping over cls instances

函数作用于类的特定实例;通常称为self的第一个参数是实例本身:

def get_colour(self):
    return self.colour

总结一下:

  1. 使用classmethod来实现适用于整个类的方法(而不是特定的类实例):

    Car.blue_cars()
    
  2. 使用实例方法实现适用于特定实例的方法:

    my_car = Car(colour='red')
    my_car.get_colour() # should return 'red'
    

答案 2 :(得分:2)

@classmethod将类作为第一个参数,而function接受类

的实例
>>> class Test(object):
...     def func(self):
...         print self
...     @classmethod
...     def meth(self):
...         print self

>>> t = Test()
>>> t.func()
<__main__.Test object at 0x00000000027238D0>
>>> t.meth()
<class '__main__.Test'>

我故意在self中使用meth参数,因此它与func的语法非常接近。但通常你最好使用cls作为参数:

...     @classmethod
...     def meth(cls):
...         print cls