可变范围(Python新手)

时间:2014-02-28 14:19:04

标签: python scope

我在功能块内的全局列表中使用.pop方法,但是在块外部正在更新全局列表。我以为局部变量不能修改全局变量。

这应该不起作用,但确实如此:

import random

PhraseBank = ['a','b','c','d']

def getPuzzle(secretphrase):
    phraseIndex = random.randint(0,len(PhraseBank)-1)
    secretphrase = PhraseBank.pop(phraseIndex)
    return secretphrase #Returns and item indexed from the PhraseBank

while len(PhraseBank) != 0:
    secretphrase = getPuzzle(PhraseBank) #works
    print(secretphrase, PhraseBank)

OUTPUT是:

a ['b', 'c', 'd']
d ['b', 'c']
c ['b']
b []

为什么PhraseBank在我只在功能块中修改时会全局更新?

3 个答案:

答案 0 :(得分:4)

列表是可变的。您正在更改PhraseBank引用的列表,但它仍然引用相同的列表。所以变量没有改变(仍然指同一个东西),但那个东西已经改变了。

答案 1 :(得分:3)

如果要为PhraseBank分配值,除非您明确表示正在使用全局变量,否则不会更改该值。但是,Python中的每个var只是对象的命名引用。您读取var然后修改它引用的对象。是的,您无法更改引用本身,但您可以更改对象。

因此,您所面临的是Python最典型的功能之一。一切都是对象,所有变量都是引用。了解这一事实通常有助于理解许多可能看起来很奇怪的事情。一个很好的例子:

>>> li = [1]
>>> a = (li, li)
>>> a[0].append(1)
>>> a[1]
[1, 1]
>>> li
[1, 1]
>>> li.append(1)
>>> a
([1, 1, 1], [1, 1, 1])

如果上述代码的行为没有让您感到惊讶,那么您就能理解变量和对象是如何相关的。 :-)这里未更改的变量会被更改,但不是因为它们开始引用其他对象,而是因为它们引用的对象被修改。那些不可变的元组也是如此。对,他们是。元组一旦创建,总是指相同的对象。但是每个对象都可能会改变。

答案 2 :(得分:2)

您不能分配给函数内的全局变量(除非您明确使用global声明)。您可以很好地修改存储在全局变量中的对象。