Python对象初始化错误,还是我误解了对象的工作方式?

0 投票
5 回答
685 浏览
提问于 2025-04-15 14:53
  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 的对象引用,onetwo 这两个对象都会显示这个引用。我原以为 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

这样一来,一切都会好很多。这是关于默认参数处理的一个细节,特别是当这些参数是可变的情况下。如果你想了解更多,可以去这个页面的讨论部分看看。

撰写回答