Python对象初始化错误,还是我误解了对象的工作方式?
1 import sys
2
3 class dummy(object):
4 def __init__(self, val):
5 self.val = val
6
7 class myobj(object):
8 def __init__(self, resources):
9 self._resources = resources
10
11 class ext(myobj):
12 def __init__(self, resources=[]):
13 #myobj.__init__(self, resources)
14 self._resources = resources
15
16 one = ext()
17 one._resources.append(1)
18 two = ext()
19
20 print one._resources
21 print two._resources
22
23 sys.exit(0)
这段代码会打印出分配给 one._resources
的对象引用,one
和 two
这两个对象都会显示这个引用。我原以为 two
会是一个空数组,因为在创建对象时,如果没有定义它,就会明确地把它设置成空的。取消注释 myobj.__init__(self, resources)
也会产生同样的效果。使用 super(ext, self).__init__(resources)
也会有同样的结果。
我能让它正常工作的唯一方法是使用以下代码:
two = ext(dummy(2))
我不应该在创建对象时手动设置默认值来让这个工作。或者也许我确实需要这样做。你们有什么想法吗?
我在使用 Python 2.5 和 2.6 时尝试过这个。
5 个回答
2
请阅读 这个回答,了解如何通过 __init__()
来设置一个类。你遇到了Python中的一个常见问题:你正在尝试设置一个可变对象,而这个可变对象在 __init__()
被编译时只会被计算一次。解决这个问题的标准方法是:
class ext(myobj):
def __init__(self, resources=None):
if resources is None:
resources = []
#myobj.__init__(self, resources)
self._resources = resources
6
你的问题在于,默认值是在函数定义的时候就被计算出来了。这意味着同一个列表对象会在不同的实例之间共享。想了解更多,可以查看这个问题的回答。
9
你应该把
def __init__(self, resources=[]):
self._resources = resources
改成
def __init__(self, resources=None):
if resources is None:
resources = []
self._resources = resources
这样一来,一切都会好很多。这是关于默认参数处理的一个细节,特别是当这些参数是可变的情况下。如果你想了解更多,可以去这个页面的讨论部分看看。