似乎没有显式初始化,同一类的不同实例的列表和哈希将获得相同的内存地址。它是否正确?
#!/usr/bin/env python3
class DataManager:
def __init__(self, name=[], value={}):
self.parm_name = name
self.parm_value = value
pass
def add_param(self, name, value):
self.parm_name.append(name)
self.parm_value[name] = float(value)
if __name__ == "__main__":
dm1 = DataManager()
dm2 = DataManager()
print("Address of dm1: %s" % hex(id(dm1)))
print("Address of dm2: %s" % hex(id(dm2)))
print("Address of dm1.parm_name: %s" % hex(id(dm1.parm_name)))
print("Address of dm2.parm_name: %s" % hex(id(dm2.parm_name)))
dm1.parm_name.append("a")
dm2.parm_name.append("b")
print("dm1.parm_name: " + str(dm1.parm_name))
print("dm2.parm_name: " + str(dm2.parm_name))
下面是执行结果:
Address of dm1: 0x7f20d9167f28
Address of dm2: 0x7f20d9167f98
Address of dm1.parm_name: 0x7f20d914bb08
Address of dm2.parm_name: 0x7f20d914bb08
dm1.parm_name: ['a', 'b']
dm2.parm_name: ['a', 'b']
dm1.parm_name的地址与dm2的地址对我来说真的很奇怪。并追加实际添加到同一列表。
如果我如下更改dm1和dm2定义,它将按预期工作:
dm1 = DataManager([], {})
dm2 = DataManager([], {})
很奇怪,不是吗? 谁能告诉我为什么?非常感谢〜
我也在Python2中尝试过,结果相同。以下版本:
$ python3 --version
Python 3.5.0
$ python2 --version
Python 2.7.5
答案 0 :(得分:2)
代码中的默认参数
def __init__(self, name=[], value={})
是 mutable object
默认参数用于启用用于调用函数的可选参数,如果未将任何参数传递给__init__
,则使用默认值,在这种情况下,将分配给class fields
>
如果默认值是mutable objects
,则不会在每次调用时刷新它们, python一次又一次地使用相同的dict
和list
对象作为默认参数,并且不会为每次对dict
的调用创建新的list
或__init__
对象。最好将non mutable
对象用作默认参数。
答案 1 :(得分:1)
查看代码的简化版本
class DataManager:
def __init__(self, name=[]):
self.parm_name = name
def add_param(self, name):
self.parm_name.append(name)
if __name__ == "__main__":
dm1 = DataManager()
dm2 = DataManager()
dm1.add_param('a')
dm2.add_param('b')
print(dm1.parm_name)
print(dm2.parm_name)
相对于稍作修改的版本:
class DataManager:
def __init__(self, name=None):
self.parm_name = [] if name is None else name
def add_param(self, name):
self.parm_name.append(name)
if __name__ == "__main__":
dm1 = DataManager()
dm2 = DataManager()
dm1.add_param('a')
dm2.add_param('b')
print(dm1.parm_name)
print(dm2.parm_name)
在以前的版本中,dm1.parm_name is dm2.parm_name
返回True。