似乎字符串和字符串在python中的行为根本不同。当我将一个字符串传递给一个函数时,它只在本地函数的作用域中被修改,但是当我对dict做同样的事情时,它会在函数范围之外被修改:
def change_str(s):
s += " qwe"
def change_arr(a):
a[1] = "qwe"
ss = "asd"
change_str(ss)
print ss
# prints:
# asd
aa = {0:"asd"}
change_arr(aa)
print aa
# prints:
# {0: 'asd', 1: 'qwe'}
这种行为是故意的,如果是,那么为什么?
答案 0 :(得分:5)
这是故意行为。字符串在python中是不可变的,因此基本上所有字符串操作都返回一个新的字符串,并且由于您的函数不返回任何内容,因此您无法看到新字符串asd qwe
。您可以在本地范围之外更改可变容器的内容,而无需将其声明为全局。
您可以在pythons data model的官方文档中阅读有关可变类型的更多信息。
答案 1 :(得分:1)
是的,这是故意的。每种类型都决定了运营商如何处理它。设置dict类型,以便a[1] = "qwe"
修改dict对象。这些更改将在引用该对象的任何代码中看到。设置字符串类型,以便s += "qwe"
不修改对象,但返回一个新对象。因此,引用原始对象的其他代码将看不到任何更改。
说法的简写方式是字符串是不可变的,而且字符串是可变的。但是,值得注意的是" dicts是可变的"并不是行为发生的全部原因。原因是项目赋值(someDict[item] = val
)是一个动作突变dict的操作。
答案 2 :(得分:1)
不要让'赋值'操作符欺骗你。这就是每个功能中真正发生的事情:
def change_str(s):
# operation has been split into 2 steps for clarity
t = s.__iadd__("qwe") # creates a new string object
s = t # as you know, without the `global` keyword, this `s` is local.
def change_arr(a):
a.__setitem__(1, "qwe")
如您所见,这些函数中只有一个实际上具有赋值操作。 []=
是(或等效于).__setitem__()
的缩写。