字典和列表在传递给函数时看起来是不可变的
Dictionaries and lists appear immutable when passed to function
我认为字典和列表在 Python 中是可变的。如何解释这种行为?
#!/usr/bin/python3
def change_list(l):
l = ['changed!']
def change_dict(d):
d = {'changed!'}
mydict = {'bob': ['blah', 5], 'asdf' : 'asdf'}
change_dict(mydict)
print(mydict)
mylist = ['hello', 'foo', 'bar']
change_list(mylist)
print(mylist)
输出:
$ python3 test3.py
{'asdf': 'asdf', 'bob': ['blah', 5]}
['hello', 'foo', 'bar']
预期输出:
$ python3 test3.py
{'changed!'}
['changed!']
您正在尝试分配,而不是更改 list/dictionary。要更改内容,您可以使用 list/dictionary 方法。另一方面,您只是在尝试分配新对象。
您可以使用的方法是:
- lists:
append()
, remove()
, insert()
, extend()
,...
- dictionaries:
update()
, clear()
,...
也许 "picture" 会有所帮助:
d = ['a', 'list']
# d -> [ 0 , 1 ]
# / |
# 'a' 'list'
d.append('changed')
# d -> [ 0 , 1 , 2 ]
# / | \
# 'a' 'list' 'changed'
d[0] = 'my'
# d -> [ 0 , 1 , 2 ]
# / | \
# 'my' 'list' 'changed'
d = []
# [] <- d [ 0 , 1 , 2 ]
# / | \
# 'my' 'list' 'changed'
重新分配名称 d
(无论是函数内部的参数还是其他参数)不会影响它之前引用的列表。
This 很好地介绍了 names/identifiers 如何在 Python 中工作,以及它如何与例如赋值和不变性。
你是RE攻击,没有改变。
而在一个函数中,您的 scope
是不同的。
d
、l
、mydict
和mylist
是指向存在于内存中某处的对象的变量。重要的是要记住变量和它指向的东西之间的区别。变量有点像代词。如果我指着一个罐子说 "pick that up" 然后我指着一个盒子说 "pick that up," "that" 每次指的是不同的东西。
当您说 l = ['changed']
时,您是在告诉 Python 将变量指向其他对象,仅此而已。这就像说 "from now on, when I say l
, I mean this new list: ['changed']
." 但它不会改变指向的事物本身。
如果你想改变一个对象,你需要使用一种对对象本身进行操作的技术,比如分配给对象的一个键(l['0'] = 'changed'
)。
有些语言确实支持说 "anything that referred to this object should now refer to this other object." 不过这似乎已经过时了,因为我不知道在任何当前流行的语言中都有什么方法可以做到这一点。
我认为字典和列表在 Python 中是可变的。如何解释这种行为?
#!/usr/bin/python3
def change_list(l):
l = ['changed!']
def change_dict(d):
d = {'changed!'}
mydict = {'bob': ['blah', 5], 'asdf' : 'asdf'}
change_dict(mydict)
print(mydict)
mylist = ['hello', 'foo', 'bar']
change_list(mylist)
print(mylist)
输出:
$ python3 test3.py
{'asdf': 'asdf', 'bob': ['blah', 5]}
['hello', 'foo', 'bar']
预期输出:
$ python3 test3.py
{'changed!'}
['changed!']
您正在尝试分配,而不是更改 list/dictionary。要更改内容,您可以使用 list/dictionary 方法。另一方面,您只是在尝试分配新对象。
您可以使用的方法是:
- lists:
append()
,remove()
,insert()
,extend()
,... - dictionaries:
update()
,clear()
,...
也许 "picture" 会有所帮助:
d = ['a', 'list']
# d -> [ 0 , 1 ]
# / |
# 'a' 'list'
d.append('changed')
# d -> [ 0 , 1 , 2 ]
# / | \
# 'a' 'list' 'changed'
d[0] = 'my'
# d -> [ 0 , 1 , 2 ]
# / | \
# 'my' 'list' 'changed'
d = []
# [] <- d [ 0 , 1 , 2 ]
# / | \
# 'my' 'list' 'changed'
重新分配名称 d
(无论是函数内部的参数还是其他参数)不会影响它之前引用的列表。
This 很好地介绍了 names/identifiers 如何在 Python 中工作,以及它如何与例如赋值和不变性。
你是RE攻击,没有改变。
而在一个函数中,您的 scope
是不同的。
d
、l
、mydict
和mylist
是指向存在于内存中某处的对象的变量。重要的是要记住变量和它指向的东西之间的区别。变量有点像代词。如果我指着一个罐子说 "pick that up" 然后我指着一个盒子说 "pick that up," "that" 每次指的是不同的东西。
当您说 l = ['changed']
时,您是在告诉 Python 将变量指向其他对象,仅此而已。这就像说 "from now on, when I say l
, I mean this new list: ['changed']
." 但它不会改变指向的事物本身。
如果你想改变一个对象,你需要使用一种对对象本身进行操作的技术,比如分配给对象的一个键(l['0'] = 'changed'
)。
有些语言确实支持说 "anything that referred to this object should now refer to this other object." 不过这似乎已经过时了,因为我不知道在任何当前流行的语言中都有什么方法可以做到这一点。