我已经阅读了许多关于 Python 中的变量引用的问题,但是当我使用我不期望的代码并且它变得非常令人沮丧时,事情仍然在发生。拿这段代码:
class MyClass(object) :
class_var = "original message" # same for all objects
def __init__(self, instance_var) :
self.instance_var = instance_var #particular to the object
my_object = MyClass("my instance variable")
untouched_object = MyClass("another instance_var")
# Values of class_var and instance_var as expected
MyClass.class_var = "changed message"
# attribute class_var has changed for both objects
# This changes attribute class_var for my_object only
my_object.class_var = "I am my_object"
# THIS ONLY CHANGES ATTRIBUTE CLASS_VAR FOR UNTOUCHED_OBJECT ONLY!
MyClass.class_var = "Last message"
print MyClass.class_var #prints Last Message
print my_object.class_var #prints I am my_object ???
print untouched_object.class_var #prints Last Message
这是怎么回事?当我使用类变量创建某个类的对象时,似乎 object.class_attribute
最初包含指向 Class.class_var
的指针,我可以更改所有对象的属性通过分配给 Class.class_var
。但是,如果我明确地将 object.class
属性分配给其他一些值,指针就会消失并且更改 Class.class_var
不再对该特定对象的更改产生影响,只有所有其他实例。这是怎么回事?此外,为什么我们能够以这种方式访问和更改类属性并可能无法访问 Python 文档声称所有实例都知道的值?
最佳答案
当你这样做的时候
my_object.class_var = "I am my_object"
您创建了一个实例 属性my_object.class_var
,它隐藏了类属性MyClass.class_var
,因此看来随后对MyClass.class_var
对 my_object
没有影响。
尝试根据其他语言的概念(例如引用和指针)来理解 Python 的数据模型可能会产生误导。尝试根据名称以及对象与名称的绑定(bind)来思考。
因此在您的示例中,MyClass.class_var
和 my_object.class_var
最初都是绑定(bind)到类属性的名称,但赋值将新的字符串对象绑定(bind)到名称我的对象.class_var
。
我发现将 (name, object) 对视为字典中的 (key, value) 对会有所帮助。在某些情况下,这实际上是“幕后”发生的事情(例如,使用您自己创建的普通类),但在其他情况下(例如 Python 的内置类型),出于效率的原因,事情的实现略有不同。
您可能会发现这篇文章很有帮助:Facts and myths about Python names and values ,由 SO 资深人士 Ned Batchelder 撰写。
关于类和实例变量的 Python 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35952278/