如何解决函数内的Python不可变对象
| 我在这里问了关于stackoverflow的上一个问题:函数调用中的Python不可变类型 这清楚地表明,只有对不可变对象的引用才传递给函数,因此将元组传递给函数不会导致该对象的完整内存副本。 但是,根据:http://www.testingreflections.com/node/view/5126 \“某些对象,例如字符串,元组, 和数字是不可变的。改变 它们在函数/方法中将 创建一个新实例和原始实例 函数/方法之外的实例 不会改变。\“ 我编写了一些测试代码,其中将不可变对象传递给函数。不出所料,我可以通过在函数头中定义的参数名称/引用来修改对象,并且所有更改仅保留在调用的函数内,而原始对象不在函数外部。 所以我的问题是: 仅在尝试更改/修改传入的对象时才创建新实例吗?我猜想,如果不更改对象,则只需对其进行引用。更重要的是,如果它确实在尝试修改时创建了副本,那么python如何管理内存?使用零复制/写时复制,还是仅在被调用的函数中创建一个完整的复制对象(整个对象的大小保留在内存中)?解决方法
如果您不将Python变量视为包含值的框,而是将其附加到对象的框,则将更加清楚地考虑它们。任何对象都可以附加任意数量的名称。一些名称是函数的本地名称,当函数返回时,它们会自动从对象上删除。
因此,当您执行以下操作时:
name = \"Slartibartfast\"
person = name
有一个字符串对象,其中包含文本“ Slartibartfast \”,并且可以使用两个名称来引用它:name
和person
。在两种情况下,您都会得到相同的对象;您可以使用id()
功能进行验证。
字符串的“真实”名称是name
还是person
?这是一个技巧问题。字符串本身没有名称。它只是一个字符串。 name
不是包含\“ Slartibartfast \”的框,它只是指向对象的标识符。 person
在Python中的地位完全相同; name
不是“更重要”,仅仅是因为它被首先分配。
注意:某些对象,例如函数和类,具有__name__
属性,该属性保存在def
或class
语句中用于声明它的名称。如果可以说是一个对象,则为对象的“真实名称”。但是,您仍然可以通过任意数量的分配名称来引用它。
现在,假设您对字符串进行“修改”以使其具有更多荷兰风味:
person = person.replace(\"art\",\"aart\")
\“修改\”用引号引起来,因为您不能修改字符串。由于字符串是不可变的,因此每个字符串操作都会创建一个新字符串。什么时候发生?立即。在这种情况下,将创建新的字符串“ Slaartibaartfast \”,并调整名称“ 2”以引用该字符串。但是,名称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()
方法,从而创建新的字符串。然后,将标识符“ 1”重新分配为指向新字符串。在函数外部,全局标识符person
仍然引用原始字符串,因为没有任何更改将其指向其他任何内容。
,我不是在谈论python本身。但是通常,在不可变数据结构中,您使用的每个需要更改状态的方法都将返回一个新对象(具有修改后的状态)。旧的将保持不变。
例如,Java可变列表可以具有:
void addItem(Object item) { ... }
对应的不可变列表将在
List addItem(Object item) { ... }
因此,通常不变的数据结构没有什么特别的。您可以使用任何语言创建不可变的数据结构。但是某些语言使创建可变数据结构变得困难或不可能(通常是功能语言)。
某些语言可能会提供伪不可变数据结构。它们使某些特殊的数据结构对于编码人员而言似乎是不变的,但实际上并非如此。
,如果对象是不可变的,则无法更改它。您可以为以前与参数对象关联的名称分配一个新对象。为此,您首先需要制作一个新对象。所以是的,您将为一个完整的新对象分配空间。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。