字符串值;通过引用字典?

时间:2017-06-13 01:14:37

标签: python python-3.x dictionary

我来自C,学习Python。在Python(3.5.2)中,似乎将一种数据类型分配给同一类型的另一种数据类型有时通过值来完成,有时通过引用来完成。

例如,字符串按值分配:

>>> str1 = "hello"
>>> str2 = str1
>>> print(str1, str2)
hello hello
>>> str2 = "goodbye"
>>> print(str1, str2)
hello goodbye

这是我期望的行为。但是,它与词典的工作方式不同:

>>> dict1 = {'key1':'val1', 'key2':'val2'}
>>> dict2 = dict1
>>> print(dict1, dict2)
{'key2': 'val2', 'key1': 'val1'} {'key2': 'val2', 'key1': 'val1'}
>>> dict2['key1'] = 'newval'
>>> print(dict1, dict2)
{'key2': 'val2', 'key1': 'newval'} {'key2': 'val2', 'key1': 'newval'}

请注意,dict1 dict2都已更改。同样,如果我将键/值对添加到其中一个词典中,它将同时出现在两个词典中。的哎呀!

(对不起,那是我的C-background演讲):))

我如何知道任何给定变量类型的行为?有这种疯狂的方法还是我只需要记住任意规则?

P.S。我意识到我可以使用dict2 = dict(dict1)来获得我预期的行为。

“可能重复”包含关于如何执行此操作的良好信息,但我对为什么我感兴趣。这个问题的答案已经非常有用了!

2 个答案:

答案 0 :(得分:5)

在Python中,一切都是通过引用;但与C,Java不同,变量不是一个盒子。作业具有约束力。

str1 = "hello"
str2 = str1

str1str2都引用" hello",但Python中的字符串是不可变的,所以修改str2,会创建一个新的绑定,因此不会影响str1

的值
str2 = "hack"
# here str1 will still reference to "hello" object

Dict是一样的:

d1 = {"name": "Tom"}
d2 = d1

d2d1将引用同一个对象。如果将d2设置为新值,则不会影响d1的值;但相反,如果我们仅修改d2,例如d2['age'] = 20d1的值将会更改,因为它们共享同一个对象。

d2 = {"name": "Hack"}
# the value of d1 does not change

Luciano Ramalho用流利的Python ,第8章,变量不是框部分对其进行了总结

  

要理解Python中的赋值,请始终先阅读右侧:这是创建或检索对象的位置。之后,左边的变量绑定到对象,就像粘贴在它上面的标签一样。别忘了盒子。

答案 1 :(得分:2)

你误解了作业的运作方式。在Python中,赋值(=)将左侧的名称设置为右侧的值。

这大致相当于在C中分配指针,其中存在相同的行为:

char* str1 = "hello";
char* str2 = str1;
str2 = "world";
printf("%s %s", str1, str2); // prints "hello world"

如果要在Python中创建值的副本,请调用执行该操作的函数或使用理解来定义新版本。例如,要复制字典,请执行以下操作:

dict2 = dict(dict1)          # dict constructor (shallow copy)
dict2 = copy.copy(dict1)     # shallow copy
dict2 = copy.deepcopy(dict1) # deep copy
dict2 = {k: v for k, v in dict1.items()} # dict comprehension

# or, in multiple lines ...
dict2 = {} # literal: create a brand-new dict, equivalent to dict()
for k, v in dict1.items():
    dict2[k] = v