python基础 :作用域

发布时间 2023-10-31 17:58:37作者: 工作手记

一 前言

环境:
python 3.10.11
win10

二 关于作用域

先来一个简单的例子,如下
image

执行结果
image

如上,在eating_other函数内为变量重新赋值,指向了一个新的对象,在该函数内输出的是新值,在该函数外输出的依旧是旧值,因为给变量重新赋值所产生的影响仅仅局限在在赋值所在的函数内,对赋值所在函数的外面的代码是无影响的

eating函数内本身并没有定义变量food,要读取该变量时,只能是从函数的外面寻找,如果外部也没有定义该变量,就会报错说该变量未定义。如果函数内和函数外都有food变量,会优先读取函数内的变量值

自己的粗浅理解是,每个py文件以及每个class以及每个函数都有自己的影响范围,这个范围就是作用域。作用域表现在两方面

  • 在每个py文件内及class内及函数内,读取变量时,它会优先在对应件内或class内或函数内寻找变量,若寻找不到,才会去外部寻找
  • 在每个py文件内及class内及函数内,给变量赋值时(即用符号=把该变量指向一个对象),该变量被默认为局部变量,只会被对应文件或class或函数内的代码读取

需要注意的是,作用域是可以互相包含的,如py文件内有class,class内有函数,那函数的作用域在class作用域内部,class作用域在py文件作用域内部
关于class的作用域,即读取或者给其作用域的变量重新赋值还需要结合class的相关特性来使用

三 外部作用域的值

读取外部作用域中的值

外部作用域为非函数

里面的函数作用域和外部作用域有同名变量,这时候,读取变量的代码位于哪一个作用域,就会优先读取哪一个作用域中变量
如果想在里面的函数读取外面函数作用域的同名变量,这时候要用函数gloabls,如下
image
如上,输出的就是外部作用域中的值

外部作用域为函数

即函数嵌套的情况,如下
image
和前面类似,外部函数和内部函数都有自己的作用域,读取变量的代码位于哪一个作用域,就会读取哪一个作用域中变量,如果未找到,才会去更外一层作用域中寻找

和之前不同的是,内外部函数有同名变量,在内部函数作用域中要读取同名属于外部函数的变量,此时并没有类似的函数供我们使用,此时只有打破同名的限制,有下面3种方法

  • 只能让内外部函数变量不同名,这样就可以找到外部的变量名
  • 定义内部函数时带上一个参数,执行时,外部函数把值传给该参数,从而带入到内部函数中
  • 像后面介绍的使用关键字nonlocal,在内部函数中声明要使用的变量为外部函数的变量

为外部作用域中的变量重新赋值

外部作用域为非函数

如下,在内部作用的变量赋值时无法对外面
image
输出值为water

要在函数内修改外面的变量值,要用关键字global,声明变量为全局变量
image
现在输出的值就是 ice

外部作用域为函数

嵌套函数中用关键字nonloal,用法和gloabl很像,但nonlocal并不是声明变量为全局变量,而是声明该变量为外部函数中的变量
image
如上,输出值是ice,若没有nonlocal food这一行,输出值是water

四 一些易错的例子

image
如上,函数内先读取再赋值,以为是先输出外部的值water,在输出内部的值ice
但执行结果确实报错
image
啥意思,说food是一个局部变量, 在它赋值前读取了它

函数内的第2行是赋值,读取是第一行。就是说第一行的读取不应该写在第二行的复制前面
我们很容易理解为第一行读取没有问题,没有变量就读取外面的变量,哪里有问题,和第2行有啥关系
但事实是,一旦在作用域内赋值,那在该整个作用域内,该变量都是局部变量,之前第一行的代码中的变量也被视为局部变量, 此时只有删掉第一行,或者在第一行声明food为全局变量

image

这个例子输出结果是多少,之前会 认为是{"today": "water"},但结果却是{"today": "ice"}
或者有时我会在函数内申明该字典为全局变量,但其实根本不用

这看起来是和之前在函数内部重新为变量赋值很像,但注意,这里并没有符号=,不是重新赋值。他是对变量指向对象中的值进行更新,之前是为该变量重新指向了一个新的对象,这两者是由根本区别的