看一个Python变量作用域的问题

172次阅读次阅读
没有评论

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

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 <module> 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
admin
版权声明:本站原创文章,由admin2021-01-09发表,共计2204字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)