Python的类股的基本属性?

Python base classes share attributes?

本问题已经有最佳答案,请猛点这里访问。

test.py中的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Base(object):
    def __init__(self, l=[]):
        self.l = l

    def add(self, num):
        self.l.append(num)

    def remove(self, num):
        self.l.remove(num)

class Derived(Base):
    def __init__(self, l=[]):
        super(Derived, self).__init__(l)

python shell会话:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Python 2.6.5 (r265:79063, Apr  1 2010, 05:22:20)
[GCC 4.4.3 20100316 (prerelease)] on linux2
Type"help","copyright","credits" or"license" for more information.
>>> import test
>>> a = test.Derived()
>>> b = test.Derived()
>>> a.l
[]
>>> b.l
[]
>>> a.add(1)
>>> a.l
[1]
>>> b.l
[1]
>>> c = test.Derived()
>>> c.l
[1]

我期待的是"C++类"行为,其中每个派生对象包含它自己的基类实例。还是这样吗?为什么每个对象看起来共享同一个列表实例?


你犯了一个常见的python新手错误。

请看我的答案:我应该如何在python中声明实例变量的默认值?

简单解释一下,python只解释一次类定义。这意味着在__init__()方法中声明的所有内容只创建一次。或者,换句话说,您的EDOCX1[1]列表默认参数只进行一次。

然后,每次创建一个新类时,self.l = l都会为同一个实例分配一个引用,因此这是您不期望的行为。

Python的方式是这样的(部分代码):

1
2
3
4
def __init__(self, arg=None):
    if arg is None:
        arg = []
    self.arg = arg

另外,您应该考虑使用比l更好的命名约定,这很难理解,可能会被误认为是1|


这被称为可变的默认参数bug,通常由对Python不熟悉的人制造。当您将可变参数作为默认参数提供时,当需要使用默认参数时,相同的对象会在实例之间使用。"获得更好的理解"检查http://docs.python.org/tutorial/controlflow.html默认参数值中的重要警告部分

在代码中,实例A在其in it调用中使用了可变的默认参数(空列表对象),当您创建b的实例时,该实例又调用了base的in it方法,再次使用了与a在其in it中使用的对象完全相同的对象。在简单的单词a.l和b.l中,指向同一列表对象。

一个非常相似的讨论——"最小惊讶"和可变的默认参数