【问题标题】:Why is the list in the class attribute still a class attribute after instantiation, not an instance attribute?为什么类属性中的列表实例化后还是类属性,而不是实例属性?
【发布时间】:2021-10-19 11:00:57
【问题描述】:

我找到了原因。 Python变量,list, dict, set是可变对象,str, tuple string int float bool是不可变对象,所以当class属性的list、dict、set被修改时,不会生成对应的。实例属性的实例属性只有在实例属性的list、dict、set被重新赋值时才会生成。给实例属性str和tuple string int float bool赋值会将类属性中的属性名复制到实例属性中,然后重新赋值。

如果我想让类属性和实例属性的列表不同,可以同时初始化类属性和实例属性:

class MyClass:
     property = []

     def __init__(self):
         self.property = []
         pass

     def add(self, value):
         self.property.add(value)


a = MyClass()

print(id(a.property))
print(id(a.__class__.property))

2352192165696
2352189676480

以下是我原来的问题:

我有一个带有属性的类和一个带有空值的列表。当生成了a和b的两个实例并向属性添加元素时,发现属性没有实例化。使用 id 查看 a.property 和 b.property。内存地址是一样的。为什么?

property attribute 如何变成instance attribute

我的代码示例如下:

class MyClass:
    property = []

    def __init__(self):
        pass

    def append(self, value):
        self.property.append(value)


a = MyClass()
b = MyClass()
a.append(1)
print(a.property)
b.append(1)

print(a.property)
print(b.property)

print(id(a.property))
print(id(b.property))

结果是:

[1]
[1, 1]
[1, 1]
1866383694784
1866383694784

我尊重的结果:

[1]
[1]
[1]

【问题讨论】:

  • 用你自己的话说,当你写def __init__(self):时,你认为这是为了什么?另外,你自己对research这个问题做了什么尝试?例如,您是否尝试输入python instance attribute into a search engine? Stack Overflow 不是教程中心。
  • 你不需要类方法来改变类变量的值
  • 不要编辑你的问题来提出一个全新的问题。但同样,您可以通过在这里进行预期的研究来轻松回答这个问题。
  • @KarlKnechtel 我也知道可以在def __init__(self)中定义。我的类属性和实例属性有不同的用途,def __init__(self) 中省略了其他赋值。来starkoverflow是带着问题来提问的。感觉我问的不是新问题,而是对我之前的问题的一个不准确的描述。
  • @KarlKnechtel 这样我先把问题改回原来的状态,然后再问。

标签: python class instance


【解决方案1】:

在您的情况下,property = [] 是一个类变量,它与您的类的所有实例共享。我假设您不想与其他类共享property = [] 的值。这意味着您需要一个实例变量,可以如下定义。

class MyClass:
    def __init__(self):
        self.property = []

    def append(self, value):
        self.property.append(value)

这应该会给你预期的输出,纯粹的!

【讨论】:

  • 除了在def __init__ (self)中定义之外没有别的办法吗?
  • @jaried 不,所有实例变量都必须在 __init__ 函数中。这是一个问题还是你为什么要问?
  • 但是有些属性是在类中定义的,而不是在def __init__(self)中定义的。实例相当于复制类的属性,而不是使用类的属性。为什么?
  • @jaried 正如我所说,class variablesinstance variables 之间存在差异。类变量在__init__ 函数之外声明,并由所有类实例共享。实例变量在__init__ 函数内,不被类实例共享。这意味着对实例变量的更改只会更改实例本身。
  • 我修改了我的问题。
【解决方案2】:

发生这种情况是因为您没有在 __init__ 函数中声明 property
每次创建对象的新实例时都会调用__init__,所以我猜这就是您的身份正在寻找。
尝试将以下更改应用于您的课程:

class MyClass:
    def __init__(self):
        self.property = []

    def append(self, value):
        self.property.append(value)

【讨论】:

  • 我修改了我的问题。
  • 我想我可能知道答案。列表就像一个数组,如果你体验过 C/CPP 这样的低级编程语言,你应该知道,数组在计算机内存中的值实际上是它所保存的第一个值的内存地址。另一方面,数字的值(例如其他语言中的int)直接存储在计算机给出的地址中。关键是,我认为因为您之前使用了列表,内存地址保持不变,但现在因为您将数字作为值分配,它们各自获得不同的内存地址。
  • 我希望我能把一切都说清楚,我只是用完了字符......-
  • 哦,我看到你已经把问题改回原来的样子了……我还是把这个评论留在这里,以防万一
  • 我找到了原因。谢谢你的回答。
猜你喜欢
  • 2014-12-07
  • 2011-08-22
  • 2018-08-04
  • 2016-10-26
  • 1970-01-01
  • 2020-07-26
  • 2020-09-01
  • 2021-12-26
相关资源
最近更新 更多