这个起源于我逛社区看到一个人的提问,本质上就是变量作用域的问题。

scores = {‘语文’:89, ‘数学’:95, ‘英语’:80}

sum_score = 0

def get_average(scores):

for subject, score in scores.items():

sum_score += score

print(‘现在的总分是%d’%sum_score)

ave_score = sum_score/len(scores)

print(‘平均分是%d’%ave_score)

get_average(scores)

要是直接运行会报以下 的错误

Traceback (most recent call last):

File “1.py”, line 11, in

get_average(scores)

File “1.py”, line 6, in get_average

sum_score += score

UnboundLocalError: local variable ‘sum_score’ referenced before assignment

根据错误的类型发现是局部变量的问题导致的,这就扯到了变量作用域的问题。

如果你不对sum_score做赋值 的操作,你会发现在函数里直接打印或者干其他事都不会报错比如以下的

代码

def get_average_1(scores):

print(sum_score)

出现这种情况的根本原因在于 Python在编译的时候在函数的定义内发现你对这个变量赋值,默认就会在本地找定义,生成的字节码也会验证这个问题。所以会报上面的错误。

套用官方的说法,这不是缺陷,这是设计方式:Python 不要求你明确声明变量,但是假定函数体内赋值的变量都是局部变量。

顺便验证一下字节码吧,需要dis这个包

from dis import dis

print(dis(get_average))

你会看到以下 的结果

0 SETUP_LOOP 28 (to 30)

2 LOAD_FAST 0 (scores)

4 LOAD_ATTR 0 (items)

6 CALL_FUNCTION 0

8 GET_ITER

>> 10 FOR_ITER 16 (to 28)

12 UNPACK_SEQUENCE 2

14 STORE_FAST 1 (subject)

16 STORE_FAST 2 (score)

6 18 LOAD_FAST 3 (sum_score)

20 LOAD_FAST 2 (score)

22 INPLACE_ADD

24 STORE_FAST 3 (sum_score)

26 JUMP_ABSOLUTE 10

>> 28 POP_BLOCK

7 >> 30 LOAD_GLOBAL 1 (print)

32 LOAD_CONST 1 (‘现在的总分是%d’)

34 LOAD_FAST 3 (sum_score)

36 BINARY_MODULO

38 CALL_FUNCTION 1

40 POP_TOP

8 42 LOAD_FAST 3 (sum_score)

44 LOAD_GLOBAL 2 (len)

46 LOAD_FAST 0 (scores)

48 CALL_FUNCTION 1

50 BINARY_TRUE_DIVIDE

52 STORE_FAST 4 (ave_score)

9 54 LOAD_GLOBAL 1 (print)

56 LOAD_CONST 2 (‘平均分是%d’)

58 LOAD_FAST 4 (ave_score)

60 BINARY_MODULO

62 CALL_FUNCTION 1

64 POP_TOP

66 LOAD_CONST 0 (None)

68 RETURN_VALUE

这LOAD_FAST 3 (sum_score)  就是从本地去读取数据这样明显就会报错。

所以解决上述问题有两种解决方法:

1、函数内 global sum_score

2、函数内定义局部变量 sum_score

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐