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

1,448次阅读
没有评论

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

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发表,共计1528字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)