class方法可以改变一个class的状态,什么意思?

classmethod can change the state of a class, what does this mean?

编辑:我不是在问什么是 classmethod 和 staticmethod 或者它们之间的区别。只是问这个问题来澄清 class 的状态是什么意思。

我刚开始 python。在浏览 @classmethod@staticmethod 上的教程时,我在多个网站上发现了类似于下面的声明。

geekforgeeks

中提到

A class method can access or modify class state while a static method can’t access or modify it.

Tutorialspoint

Class method can access and modify the class state. Static Method cannot access or modify the class state.


class状态是什么意思?这是否意味着有一种方法可以通过使用 class 方法修改所有对象的值,因为当 class 状态更改时它应该影响从该 class 创建的所有对象?我只能找到使用 @class 方法创建的工厂方法,我认为这不是某种 class 状态变化。

我是一名高级 C++ 程序员。如果可能的话,一些相关的解释会很好。

编辑:将此标记为重复的问题没有提到 class 状态。在问这个问题之前,我阅读了那个问题及其副本。

我试过的一个例子:

class MyClass:
 myvar = 100
 def __init__(self,age):
  self.myvar = age
 def instMethod(self):
  print("Inst method")

 @classmethod
 def classMethod(cls,age):
  cls.myvar = age

obj1 = MyClass(10)
obj2 = MyClass(20)
obj3 = MyClass(30)

print(obj1.myvar)
print(obj2.myvar)
print(obj3.myvar)

print("after class method")
MyClass.classMethod(45)

print(obj1.myvar)
print(obj2.myvar)
print(obj3.myvar)

输出:

10

20

30

after class method

10

20

30

但我的预期是

10

20

30

after class method

45

45

45

Class 状态将包括 class 属性:

class A:
    x = 3

    @classmethod
    def change_x(cls, new_x):
       cls.x = new_x

然后

>>> A.x
3
>>> A.change_x(9)
>>> A.x
9

class方法和静态方法的区别在于class方法是自动提供class方法的一个实例] 调用它,作为它的第一个参数;静态方法不是。

在 C++ 术语中,静态方法不受对象或对象实例的约束。静态方法将无法访问实例绑定或对象/class 绑定变量。

class 方法与静态方法非常相似,从某种意义上说,您可以像调用静态方法一样调用 class 方法:通过 class 而不是 class.

的实例

主要区别在于,class方法被对象/class绑定,因此可以访问class状态变量。

您引用的两种解释都是错误的。静态方法很有可能修改 class 的状态:

class A:
    x = 1

    @staticmethod
    def change_static():
        A.x = 2

    @classmethod
    def change_class(cls):
        cls.x = 3

证明:

>>> A.x
1
>>> A.change_static()
>>> A.x
2
>>> A.change_class()
>>> A.x
3

正确的 语句是 class 方法为调用它的 class 取一个参数,在此命名为 cls例子。这允许 class 方法访问它被调用的 class (通常可能是 A 的子 class),就像实例方法接受参数一样通常命名为 self 以访问调用它的实例。

静态方法没有这样的参数,但仍然可以通过名称访问 class。


对于问题的后半部分,您需要了解如何访问实例上的属性:

  • 如果实例有自己的同名属性,那么您将获得实例自己的属性的值。
  • 否则,如果实例的 class 具有其自己的该名称的属性,那么您将获得该值。
  • 否则,您将获得属于具有该名称之一的最近的超级class的属性。
  • 否则,将引发 AttributeError

请注意,这仅适用于获取属性值;如果您设置 a.x = 23 那么您将 总是 设置属于 a 本身的属性,即使它之前没有这样的属性。例如:

>>> a = A()
>>> a.x
3              # a has no x attribute, so this gets the value from the class
>>> A.x = 4
>>> a.x
4              # gets the updated value from the class
>>> a.x = 5
>>> A.x = 6
>>> a.x
5              # a has its own x attribute now, so this doesn't go to the class

在您的代码中,__init__ 方法设置了 self.myvar 属性,因此每个实例都有此属性。因此,像 obj1.myvar 这样的查找永远不会回退到 class 的属性。

这是一个示例,其中调用 class 方法会更改 class 属性,因此对于 class 的新实例来说它是不同的:

class Foo:
    i = 1

    @classmethod
    def increase(cls):
        cls.i += 1


instance1 = Foo()
print(instance1.i)
>>> 1

instance1.increase()
instance2 = Foo()
print(instance2.i)
>>> 2