dav*_*lab 10 python language-design object instantiation
也许是一个简单的问题,但我不能完全按照我的Google查询来查找答案.当我将对象传递给对象构造函数时,我习惯于复制对象,如下所示:
...
def __init__(self, name):
self._name = name[:]
...
Run Code Online (Sandbox Code Playgroud)
但是,当我运行以下测试代码时,似乎没有必要,Python在对象实例化时正在制作对象值的深层副本:
>>> class Candy(object):
... def __init__(self, flavor):
... self.flavor = flavor
...
>>> flav = "cherry"
>>> a = Candy(flav)
>>> a
<__main__.Candy object at 0x00CA4670>
>>> a.flavor
'cherry'
>>> flav += ' and grape'
>>> flav
'cherry and grape'
>>> a.flavor
'cherry'
Run Code Online (Sandbox Code Playgroud)
那么,这里的真实故事是什么?谢谢!
编辑:
感谢@Olivier的出色回答.以下代码记录了Python通过引用复制的更好示例:
>>> flav = ['a','b']
>>> a = Candy(flav)
>>> a.flavor
['a', 'b']
>>> flav[1] = 'c'
>>> flav
['a', 'c']
>>> a.flavor
['a', 'c']
Run Code Online (Sandbox Code Playgroud)
Oli*_*ier 13
这是因为字符串是不可变的.
如果对象是不可变的,那么操作符+=实际上会引起混淆,实际上会重新分配它所应用的变量:
s = 'a'
ids = id(s)
s += 'b'
ids == id(s) # False, because s was reassigned to a new object
Run Code Online (Sandbox Code Playgroud)
所以,你的情况,在开始的时候,双方flav并a.flavor指向同一个字符串对象:
flav --------\
'cherry'
a.flavor ----/
Run Code Online (Sandbox Code Playgroud)
但是当您编写flav += 'and grape'变量flav时,会将其重新分配给新的字符串对象:
flav --------> 'cherry and grape'
a.flavor ----> 'cherry' # <-- that string object never changes
Run Code Online (Sandbox Code Playgroud)
这很令人困惑,因为通常,当您在变量上调用运算符时,它不会更改变量.但只是在不可变对象的情况下,它会重新分配变量.
所以对你的问题的最终答案是,是的,在实例化时复制对象是有意义的,特别是如果你期望一个可变对象(通常是这种情况).对象是不可变的,无论如何复制它都不会有害.