【问题标题】:behavior of classmethods and static variables in pythonepython中类方法和静态变量的行为
【发布时间】:2020-03-12 07:02:13
【问题描述】:

假设我有以下课程

class Parent: 
    message = "Hello World"
    @classmethod
    def print_message(cls):
        print(cls.message)
    @classmethod 
    def change_message(cls, new_message):
            cls.message =  new_message

class Child_one(Parent):
    @classmethod 
    def print_messsage(cls):
        print (cls.message)
    @classmethod 
    def change_message(cls, new_message):
        cls.message = new_message

class Child_two(Parent):
    @classmethod
    def print_message(cls):
        print(cls.message)

我想我的问题是子类的cls 指的是什么,因为如果我更改父类中的静态变量message,它会正确更改两个子类中message 的值

Parent.change_message("This is new message")
Child_one.print_message() # This is new message 
Child_two.print_message() # This is new message

这是我的预期行为,cls.message 均指父类的消息。但是这样做

Child_one.change_message("I am child one") 

导致

等行为
Parent.print_message() # This is new message 
Child_one.print_message() # I am child one 
Child_two.print_message() # This is new message 

所以 Child_one 的cls.message 变量不再指向父类的消息。

在其他语言中,例如c++c#,静态更改父类或子类的静态变量会导致所有父类和派生类发生更改。有没有办法在python 中复制这种行为,如果没有,为什么不呢?

【问题讨论】:

    标签: python inheritance class-method static-variables


    【解决方案1】:

    写入时

    只要您将某个东西分配给类或对象的成员,而该成员的名称不存在,它就会被创建。

    成员的名字出现在基类中这一事实并没有改变任何东西。它是在类本身中创建的。

    阅读后

    然后进行名称解析:首先尝试在类本身中查找成员,然后在其基类中查找。

    【讨论】:

    • 我明白这一点,但是我不明白为什么 python 在我设置它时会为Child_one 创建一个新成员。 Child_one 不存在它,但由于它是派生类,它不应该检查它的父类是否有一个名为 message 的成员,然后才决定创建它吗?写入时不忽略父类违反 is a 关系
    【解决方案2】:

    Frank-Rene 的回答是绝对正确的,通过观察类变量的内存地址可以看出这种行为:

    print(Parent.message, Child_one.message) #identical memory addresses
    Child_one.change_message("something")
    print(Parent.message, Child_one.message) #now they are different
    

    这是因为 Python 中的每个类都将其属性保存在一个 dunder 字典 (__dict__) 中,如果它们没有被覆盖,它们将引用父类直到被修改。

    对于您的用例,您可能对 Python 的 borg 设计模式感兴趣:https://github.com/faif/python-patterns/blob/master/patterns/creational/borg.py

    【讨论】:

      猜你喜欢
      • 2013-09-08
      • 2014-02-12
      • 2012-06-24
      • 1970-01-01
      • 2018-07-04
      • 2011-02-13
      • 2011-12-08
      • 1970-01-01
      相关资源
      最近更新 更多