Hub*_*bro 15 python sequences value-type reference-type
我假设Python中的序列类型是值类型.事实证明它们是引用类型(意味着当分配给新变量但引用时,不会复制变量的值).所以现在我想知道,Python中的值类型是什么?也就是说,我可以将Python中的哪些类型分配给新变量而不必担心变量被引用?
Ign*_*ams 23
Python中的所有值都是引用.你需要担心的是一个类型是否可变.基本的数字和字符串类型,以及tuple和frozenset是不可变的; 绑定到其中一种类型的对象的名称只能被反弹,而不能进行变异.
>>> t = 1, 2, 3
>>> t[1] = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
Run Code Online (Sandbox Code Playgroud)
来自使用强类型 Swift 语言的 iOS 开发,Python 参考有点令人困惑,所以我决定做一些比较。以下是总结:-
a = 10你只是指向/引用在这种情况下10存储在内存中的对象。因此,如果该对象更改,则变量的值a也会更改,但更改a不会更改该对象10,这类似于 Swift 原始值类型,例如Int.为了说明这一点,这里有一个例子:-
# "a" points to an object in this case 10
a = 10
# "b" points to the same object which a points but does not point to a variable a.
b = a
# Now if we change "a" to point to another object in memory say 20.
a = 20
# "b" still points to the old object 10 in other words
# "b == 10" but "a == 20", This is because "b" was never pointing to the variable "a"
# even though we assigned it as "b = a" instead it was pointing to the object 10
# which is # the same as writing b = 10.
Run Code Online (Sandbox Code Playgroud)
让我们检查一个更复杂的数据结构 List
list1 = [10,20,30,40]
list2 = list1 #[10,20,30,40]
list1 = [3,4]
# list1 ==> [3,4]
# list2 ==> [10,20,30,40]
Run Code Online (Sandbox Code Playgroud)
同样,对于 Swift 和其他类似语言的行为也是如此。这是巨大的差异让我们尝试在某个索引处更改值(这变得更加棘手)
list1 = [10,20,30,40]
list2 = list1 #[10,20,30,40]
# change value of list 1 at a certain index say index 0
list1[0] = 500
# If you check again the values of list1 and list2 you will be surprised.
#list1 ==> [500,20,30,40]
#list2 ==> [500,20,30,40]
Run Code Online (Sandbox Code Playgroud)
它们都发生了变化,因为它们都指向同一个对象,因此更改对象会更改所有list1和list2。这与 Swift 等其他语言非常混淆。在 Swift List/Array 中是值类型意味着它们不被引用而是被复制,但是在 python 中这是另一回事,更改某个索引处的值会导致更改引用该对象的所有属性的值,就像在上面的例子。对于来自 Swift 或其他类似语言的人来说,记住这一点非常重要。
那么我们如何在python中复制呢?
list1 = [10,20,30,40]
list2 = list(list1)
# list1 ==> [10,20,30,40]
# list2 ==> [10,20,30,40]
Run Code Online (Sandbox Code Playgroud)
这样做将避免在list1更改list2保持不变时产生不良影响。
举个例子
list1[0] = 500
#list1 ==> [500,20,30,40] # Changed
#list2 ==> [10,20,30,40] # Unchanged
Run Code Online (Sandbox Code Playgroud)
上面的答案是正确的,但我反对“引用”的语义。
类似于C的语言将变量视为固定的存储区,并在其中存储值。调用函数时,将创建一组新的存储桶,并将值复制到其中。有时,存储桶是按引用传递的,实际上成为了调用者存储桶的别名。
另一方面,Python将变量视为值(对象)的单纯标签(名称)。调用函数时,将创建一组新标签并将其拍打到这些相同的对象上。
在Python的上下文中提到“引用”是没有意义的,因为在所有其他语言中,“引用”是“值”的替代。Python没有这种双重性。它只是经过并分配对象。并未提及到。
也许有点讽刺,但是对于C ++程序员而言,这种术语不会引起混乱,例如,他们听到Python通过引用传递并且不理解如何重新分配调用者的名称。