函数内的Python不可变对象

2024-05-12 00:45:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我在这里问了一个关于stackoverflow的问题:Python immutable types in function calls

这清楚地表明,只有对不可变对象的引用才传递给函数,因此将元组传递给函数不会导致该对象的完整内存副本。在

但是,根据:http://www.testingreflections.com/node/view/5126

"Some objects, like strings, tuples, and numbers, are immutable. Altering them inside a function/method will create a new instance and the original instance outside the function/method is not changed."

我写了一些测试代码,其中一个不可变的对象被传递给一个函数。正如预期的那样,我可以通过定义为函数头一部分的参数名/引用来修改对象,并且所有的更改只在被调用的函数中保持不变,而不影响函数外部的原始对象。在

所以我的问题是:

新实例是否仅在试图更改/修改传入的对象时创建?我猜如果对象没有改变,只需要引用它。更重要的是,如果python确实在尝试修改时创建了一个副本,那么python如何管理内存?如果写入时拷贝/拷贝为零,还是创建了一个完整的复制对象(整个对象的大小保留在内存中)只在被调用函数中可见?


Tags: andthe对象instance函数内存in副本
3条回答

在Python中,如果不把变量看作包含值的框,而是将其作为附加到对象上的名称,那么您将更加清楚地思考Python中的变量。任何对象都可以附加任意数量的名称;有些名称是函数的局部名称,当函数返回时,这些名称将自动从对象中删除。在

所以当你这样做的时候:

name = "Slartibartfast"
person = name

有一个字符串对象,它包含文本“Slartibartfast”,有两个名称可以用来引用它:name和{}。在这两种情况下都可以得到相同的对象;可以使用id()函数来验证这一点。在

哪个是字符串的“真实”名称,name还是person?这是个诡计问题。字符串本身没有名称;它只是一个字符串。name不是一个包含“Slartibartfast”的框,它只是一个引用对象的标识符。person在Python中具有完全相同的地位;name不是“更重要的”,仅仅因为它是先赋值的。在

NOTE: Some objects, such as functions and classes, have a __name__ attribute that holds the name that was used to declare it in the def or class statement. This is the object's "real name" if it can be said to have one. However, you can still reference it through any number of assigned names.

现在,假设您“修改”字符串,使其更具荷兰风味:

^{2}$

“Modify”用引号括起来,因为您不能修改字符串。由于字符串是不可变的,每个字符串操作都会创建一个新字符串。什么时候发生的?马上。在本例中,将创建新字符串“slaartfast”,并调整名称person以引用该字符串。但是,名称name仍然引用原始字符串,因为您没有告诉它引用其他任何内容。只要至少有一个名字提到它,Python就会保留好的旧的“Slartibartfast”。在

在处理函数时,这没有什么不同:

def dutchnametag(name):
    name = name.replace("art", "aart")
    print "HELLO! My Dutch name is", name

person = "Slartibartfast"
dutchnametag(person)

这里我们将字符串“Slartibartfast”指定给全局名称person。然后将该字符串传递给函数,在那里它接收附加的本地名称name。然后通过name标识符调用字符串的replace()方法,创建一个新的字符串。然后重新分配标识符name,以指向新字符串。在函数之外,全局标识符person仍然引用原始字符串,因为没有任何改变,它指向任何其他字符串。在

如果一个对象是不可变的,就没有办法改变它。您可以将一个新对象分配给以前与参数对象关联的名称。为此,您首先需要创建一个新对象。所以是的,你会为一个全新的对象分配空间。在

我不是说python本身。但通常,在不可变的数据结构中,您使用的每个需要更改状态的方法都将返回一个新对象(具有修改后的状态)。旧的将保持不变。在

例如,Java可变列表可以具有:

void addItem(Object item) { ... }

对应的不可变列表将有一个

^{2}$

所以,不可变数据结构一般没有什么特别之处。在任何语言中,您都可以创建不可变的数据结构。一些可变的语言(或者说不可能创建可变的数据结构)。在

有些语言可能提供伪不变的数据结构。它们使一些特殊的数据结构看起来像是不可变的,而实际上它们不是

相关问题 更多 >