我在这里询问了有关stackoverflow的上一个问题:函数调用中的Python不可变类型
其中明确表示,只对不可变对象的引用传递给函数,因此传递一个元组的功能并不会导致该对象的完整内存拷贝.
但是,根据:http://www.testingreflections.com/node/view/5126
"某些对象,如字符串,元组和数字,是不可变的. 在函数/方法中更改它们将创建一个新实例,并且函数/方法之外的原始实例不会更改."
我写了一些测试代码,其中一个不可变对象被传递给一个函数.正如所料,我可以通过作为函数头部分定义的parameter-name/reference修改对象,并且所有更改仅在被调用函数中保留,使原始对象不受影响.
所以我的问题是:
是否仅在尝试更改/修改传入的对象时才创建新实例?我猜测如果对象没有改变,只需要引用它就可以了.更重要的是,如果它确实在尝试修改时创建了一个副本,python如何管理内存?使用零拷贝/写时复制,或者它是否只在被调用的函数内创建一个完整的复制对象(整个对象的大小保留在内存中)?
如果您认为它们不是包含值的框,而是附加到对象的名称,您会更清楚地思考Python中的变量.任何对象都可以附加任意数量的名称; 某些名称是函数的局部名称,并在函数返回时自动从对象中取出.
所以当你做这样的事情时:
name = "Slartibartfast"
person = name
Run Code Online (Sandbox Code Playgroud)
有一个字符串对象,其中包含文本"Slartibartfast",并且有两个名称可供其引用:name和person.在这两种情况下你得到相同的对象; 您可以使用该id()功能验证这一点.
哪个是字符串的"真实"名称,name或者person?这是一个棘手的问题.该字符串本身并不具有名称; 它只是一个字符串.name不是包含 "Slartibartfast" 的框,它只是引用该对象的标识符.person在Python中具有完全相同的立场; name不是因为首先被分配而"更重要".
注意:某些对象(如函数和类)具有一个
__name__属性,该属性包含用于在deforclass语句中声明它的名称.这是对象的"真实姓名",如果它可以说有一个.但是,您仍然可以通过任意数量的指定名称来引用它.
现在,假设您"修改"字符串以使其更具荷兰风味:
person = person.replace("art", "aart")
Run Code Online (Sandbox Code Playgroud)
"修改"在引号中,因为您无法修改字符串.由于字符串是不可变的,每个字符串操作都会创建一个新字符串.它什么时候发生?立即.在这种情况下,将创建新字符串"Slaartibaartfast"并person调整名称以引用该字符串.但是,名称name仍然引用原始字符串,因为您没有告诉它引用其他任何内容.只要至少有一个名称引用它,Python将保持良好的旧"Slartibartfast".
处理函数时没有什么不同:
def dutchnametag(name):
name = name.replace("art", "aart")
print "HELLO! My Dutch name is", name
person = "Slartibartfast"
dutchnametag(person)
Run Code Online (Sandbox Code Playgroud)
在这里,我们将字符串"Slartibartfast"分配给全局名称person.然后我们将该字符串传递给我们的函数,在那里它接收额外的本地名称name.replace()然后通过name标识符调用字符串的方法,创建一个新字符串.name然后重新分配标识符以指向新字符串.在函数外部,全局标识符person仍然引用原始字符串,因为没有任何内容将其更改为指向其他任何内容.
| 归档时间: |
|
| 查看次数: |
2531 次 |
| 最近记录: |