【问题标题】:What is the purpose of @classmethod in Python? [duplicate]Python中@classmethod的目的是什么? [复制]
【发布时间】:2021-02-06 07:18:30
【问题描述】:

我目前正在学习 Python。在 OOP 中,@classmethod 装饰器的目的是什么?通过@classmethod 访问类变量和通过普通方法访问它有什么区别?就像我可以这样做一样:

class A():
   _variable = A

   def getVariable(self):
      return self._variable 
 

class A():
   _variable = A

   @classmethod
   def getVariable(cls):
      return cls._variable 
 

这两种方法有什么区别?为什么我需要使用什么时候使用classmethod,什么时候不需要?如果我不这样做会怎样?

【问题讨论】:

标签: python class class-variables


【解决方案1】:

使用类和实例变量/方法时,您关心的是可见性!

类变量/方法由类的所有实例共享,而实例变量/方法仅对您现在拥有的实例可用!

一般来说,实例变量用于每个实例唯一的数据,类变量用于类的所有实例共享的属性和方法:python tutorial

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind                  # shared by all dogs
'canine'
>>> e.kind                  # shared by all dogs
'canine'
>>> d.name                  # unique to d
'Fido'
>>> e.name                  # unique to e
'Buddy'

这个例子没有告诉你的是,使用类方法,你可以在不通过实例的情况下调用类上的方法!

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

    @classmethod
    def isGoodBoy(cls):
        return True  # all dogs are good boys!

现在isGoodBoy 方法不需要访问狗的名字,所以它可以是一个类方法,这反映在所有实例上;毕竟所有的狗都是好男孩(和女孩!)。

但这告诉你更多! 狗是个好孩子吗?我们是否要求任何特定的狗成为好孩子?

>> Dog.isGoodBoy() # here we call the method on the class
True # debate settled!

现在还有四个问题;当您处理类而不是对象时,最好使用类方法。您如何知道记录器实例在创建之前是否需要网络?这就是类方法和类变量的用途,以及该类的所有对象的共同状态和行为。

现在,由于这是在所有类之间共享的,因此您现在遇到了其他问题,该类的每个实例都可能修改类变量!这也意味着你可以在没有对象的情况下查询变量值!

假设你想在运行时从方法 A 切换到方法 B。


class Foo:
    upgrade = False
    def a(self):
        ...
    def b(self):
        ...
    def run(self):
        self.a() if self.upgrade else self.b()

现在Foo.upgrade = True 将为每个人切换内容!或者通过运行Dog.kind = 'feline' 将狗变成猫更好

【讨论】:

    【解决方案2】:

    @classmethod 定义下面的方法是静态的,属于类而不是对象。

    所以带有@classmethod 的方法不能访问对象的任何值,但可以在不初始化该类的对象的情况下调用它。

    一个用例是:

    class Test:
        @classmethod
        def foo(cls, a, b):
            # do smth
    
    Test.foo(1, "abc")
    

    【讨论】:

      猜你喜欢
      • 2010-12-29
      • 2021-08-13
      • 2013-04-16
      • 2010-10-06
      • 1970-01-01
      • 2019-06-13
      • 2014-11-12
      • 1970-01-01
      相关资源
      最近更新 更多