python - 使用list slice而不是pop()会导致UnboundLocalError

时间:2014-07-04 15:12:22

标签: python list scope

当我使用while len(my_list) > 5: my_list.pop()截断列表中的条目时,我没有遇到任何错误。但是,当我使用my_list = my_list[:5]尝试实现相同目的时,我会在之前部分的代码中看到UnboundLocalError,切片发生之前。< / p>

我会尝试只发布看似相关的部分。首先,脚本所做的第一件事就是从pickle文件中加载列表 - 如果失败则会为其分配一个默认值。除非我的理解很差,否则此列表只存在于脚本的全局命名空间中。

try:    #either load hi-score list, or create a default list
    with open('scores.py', 'r') as f:
        scoreList = pickle.loads(f.read())
except:
    scoreList = [
                    ['NME', 15000], 
                    ['HAS', 12000], 
                    ['LDS', 10000], 
                    ['AKT', 8000], 
                    ['JAS', 5000]
            ]

然后检查列表以查看是否应该输入新条目;如果是,则收集玩家姓名缩写。否则游戏只会显示分数。

def game_over_loop(self):
        ##other unrelated code that only runs one time

        if ship.score > scoreList[-1][1]:
            go_state = 'get_player_score'

        ###...
        while displayScores:

            ###...
                if len(playerInitials.text) >= 3:
                    scoreList.append([playerInitials.text, ship.score])
                    scoreList.sort(key=lambda x: x[1])
                    scoreList.reverse()
               ###here's the problem###
                    scoreList = scoreList[:5]    #bad
                    #while len(scoreList) > 5:   #good
                    #   scoreList.pop()
               ########################
                    pickleScore = pickle.dumps(scoreList)
                    with open('scores.py', 'w') as f:
                        f.write(pickleScore)
                    go_state = 'build_scores'

如果我使用注释之间的语法,我会收到以下错误:

Traceback (most recent call last):
  File "sf.py", line 1024, in <module>
    TheGame.master_loop()
  File "sf.py", line 904, in master_loop
    self.game_over_loop()
  File "sf.py", line 841, in game_over_loop
    if ship.score > scoreList[-1][1]:   #if ship.score high enough, get_player_score
UnboundLocalError: local variable 'scoreList' referenced before assignment

但是,如果我只是在列表len大于5和pop()条目时进行迭代,则没有问题。

我不清楚在注释代码之前如何发生UnboundLocalError 。由于scoreList是全局的(对吗?),看起来最糟糕的事情就是排序后的本地实例,并且追加将是唯一一个被切片然后腌制的实例,但它并没有#39} ;甚至在抛出错误之前在脚本中得到那么远。

事实上,如果我将这些行添加到脚本中:

if 'scoreList' in globals():
    print "I see it"

然后我得到以下内容:

I see it
Traceback (most recent call last):
  File "sf.py", line 1029, in <module>
    TheGame.master_loop()
  File "sf.py", line 909, in master_loop
    self.game_over_loop()
  File "sf.py", line 844, in game_over_loop
    if ship.score > scoreList[-1][1]:   #if ship.score high enough, get_player_score
UnboundLocalError: local variable 'scoreList' referenced before assignment

那么这是怎么发生的?

更新:我很欣赏将其声明为全局变量的建议,但我的问题是“我该怎样解决这个问题”#34;和#34;为什么这是列表[:index]的事情,但在使用list.pop()&#34;时却没有。

3 个答案:

答案 0 :(得分:1)

首先定义scoreList的位置 - 它是该函数中的本地吗?问题可能是执行scoreList = ...会导致它与本地范围绑定。在这种情况下,请尝试将global scoreList放在函数的顶部。

答案 1 :(得分:1)

对函数中出现的变量的任何赋值(不计算嵌套在该函数中的函数或类中的赋值)会导致Python创建该名称的局部变量。然后,对函数内部变量的所有访问都将尝试访问局部变量,而不是全局变量。因此,

scoreList = scoreList[:5]

导致对函数内scoreList的所有访问尝试访问从未初始化的scoreList本地。

当你这样做时

scoreList.pop()

函数中的scoreList变量没有赋值。 (对象scoreList指的是更改状态,但这不是对变量的赋值。)因此,Python将对scoreList的访问解释为寻找全局变量,这就是你想要的

答案 2 :(得分:0)

试试这个:

def game_over_loop(self):
    global scoreList
    if ship.score > scoreList[-1][1]:
        #rest of my code