【问题标题】:Python. Strange class attributes behaviorPython。奇怪的类属性行为
【发布时间】:2010-04-25 07:13:29
【问题描述】:
>>> class Abcd:

...     a = ''
...     menu = ['a', 'b', 'c']
... 
>>> a = Abcd()
>>> b = Abcd()
>>> a.a = 'a'
>>> b.a = 'b'
>>> a.a
'a'
>>> b.a
'b'

都是正确的,每个对象都有自己的'a',但是...

>>> a.menu.pop()
'c'
>>> a.menu
['a', 'b']
>>> b.menu
['a', 'b']

怎么会这样? 以及如何使用列表作为类属性?

【问题讨论】:

  • 您绝对不是第一个遇到这种情况的人。我记得第一次遇到这个问题:我花了好几天才弄清楚问题是什么。一旦你学会它就有意义,但我个人认为它真的很不直观。
  • @musicfreak:我真的不明白为什么人们会对此感到困惑。通过查看任何教程中的任何 OO 示例,您将了解这一点。为什么有人宁愿浪费“几天”而不是花几个小时来阅读教程,我无法理解。
  • -1:这个有很多重复项。
  • 听起来你不想要一个类属性,而是一个实例属性。官方教程docs.python.org/tuttinyurl.com/thinkcspy2e 等书籍中介绍了如何做到这一点
  • 我来自 php 和 java,对我来说这个概念(作为“和或”功能和私有/受保护策略)很奇怪

标签: python class attributes


【解决方案1】:

这是因为您初始化 menu 属性的方式是将所有实例设置为指向同一个列表,而不是具有相同值的不同列表。

相反,使用类的__init__ 成员函数来初始化值,从而创建一个新列表并将该列表分配给该类的特定实例的属性:

class Abcd:
    def __init__(self):
        self.a = ''
        self.menu = ['a', 'b', 'c']

【讨论】:

  • 但是,简单字符串属性和列表属性有什么区别?为什么?
  • 因为它是引用和值之间的区别。如果你做了a.menu = ['a','b'],那么b.menu 将保持不变 - 但你不是,你正在更改a.menu指向 的列表。
【解决方案2】:

参见教程中的class-objects,注意self的使用。

使用实例属性,而不是类属性(以及新样式类):

>>> class Abcd(object):
...     def __init__(self):
...         self.a = ''
...         self.menu = ['a','b','c']
...         
>>> a=Abcd()
>>> b=Abcd()
>>> a.a='a'
>>> b.a='b'
>>> a.a
'a'
>>> b.a
'b'
>>> a.menu.pop()
'c'
>>> a.menu
['a', 'b']
>>> b.menu
['a', 'b', 'c']
>>> 

【讨论】:

  • 您可能需要注意,所有类都自动成为 Python 3.0+ 行中的新型类。
【解决方案3】:

因为 Python 中的变量只是“标签”

Abcd.menu 和 a.menu 都引用同一个列表对象。

在您的情况下,您应该将标签分配给新对象,

不要就地修改对象。

你可以跑

a.menu = a.menu[:-1]

而不是

a.menu.pop()

感受不同

【讨论】:

    猜你喜欢
    • 2017-04-10
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    相关资源
    最近更新 更多