8

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

我什么时候应该使用@classmethod,什么时候应该在 python 中使用“经典”方法。classmethod 是否必须是引用类的方法(我的意思是它只是处理类的方法)?

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

4

3 回答 3

7

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

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

a = A()
a.f()

这个调用a.f实际上要求f(通过描述符 协议)一个对象真正返回。然后这个对象在没有参数的情况下被调用,并将调用转移到 real f,添加a在前面。

所以真正做的是用作为参数a.f()调用原始函数。f(a)

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

  1. @staticmethod装饰师,
  2. @classmethod装饰师,
  3. 与其他类似工作的自制装饰师之一。

@staticmethod把它变成一个对象,当被问到时,它会改变参数传递行为,以便它与调用 original 的意图相匹配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. 这也可以用于工厂方法,如果它们不需要关心子类化。
于 2013-07-31T08:33:31.637 回答
7

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

Aclassmethod是一种适用于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'
    
于 2013-07-31T08:36:11.803 回答
3

@classmethod将类作为第一个参数,而函数采用类的实例

>>> 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
于 2013-07-31T08:36:07.153 回答