深入了解Python 变量作用域

 更新时间:2020年07月24日 11:39:19   作者:看云  
这篇文章主要介绍了Python 变量作用域的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下

特点

python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量能被访问的范围。即Python变量的作用域由变量所在源代码中的位置决定。Python中并不是所有的语句块中都会产生作用域。只有当变量在Module(模块)、Class(类)、def(函数)中定义的时候,才会有作用域的概念。

1. 函数内部的变量,函数外部不能访问

def func():
  variable = 100 
  print(variable) 
print(variable) # name 'variable' is not defined

2. 函数上层的变量(标量)只能读取,不能再次定义,初始化

def counter1():
  n = 0
  def compute():
    n = n + 1 # n为标量(数值,字符串,浮点数),Python程序会因为“如果内部函数有引用外部函数的同名变量或者全局变量,并且对这个变量有修改.那么python会认为它是一个局部变量,又因为函数中没有n的定义和赋值,所以报错
    # y = n + 1 # 更改为y就没事
    # return y
    return n
  return compute
variable = 300
def test_scopt():
  print(variable) # 此时调用局部变量variable并有没绑定到一个内存对象(没有定义和初始化,即没有赋值)。本质上还是遵循的LEGB法则
  variable = 200 #因为这里,前面调用过一次,所以variable就变为了局部变量
  # print(variable) # 写在下面就没问题,因为variable是新的局部变量,而不是重新被定义,却没有绑定
test_scopt()

Python中的模块代码在执行之前,并不会经过预编译,但是模块内的函数体代码在运行前会经过预编译,因此不管变量名的绑定发生在作用域的那个位置,都能被编译器知道。Python虽然是一个静态作用域语言,但变量名查找是动态发生的,直到在程序运行时,才会发现作用域方面的问题,

3. list,dict等复合变量里面的值都可以引用更改

def counter():
  n = [0]
  def compute():
    n[0] += 1 # 更改的是n里面的第一个值,不是更改n
    return n[0]
  return compute

func = counter()
func() # 1
func() # 2
func() # 3

4. global 声明全局变量,如果在局部要对全局变量修改,需要在局部也要先声明该全局变量

def counter1():
  n = 0
  def compute():
    global n # 如果在局部要对全局变量修改,需要在局部也要先声明该全局变量,但此处也会报错,因为没有全局变量n
    n += 1
    return n
  return compute


# right
def counter1():
  global n
  n = 0
  def compute():
    global n
    n += 1
    return n
  return compute

5. nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量

def make_counter():
  count = 0
  def counter():
    nonlocal count # 使用外层非全局变量
    count += 1
    return count
  return counter

作用域的类型

在Python中,使用一个变量时并不严格要求需要预先声明它,但是在真正使用它之前,它必须被绑定到某个内存对象(被定义、赋值);这种变量名的绑定将在当前作用域中引入新的变量,同时屏蔽外层作用域中的同名变量。

L(local)局部作用域

局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。有些情况需要在函数内部定义全局变量,这时可以使用global关键字来声明变量的作用域为全局。局部变量域就像一个 栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。
注意:如果需要在函数内部对全局变量赋值,需要在函数内部通过global语句声明该变量为全局变量。

E(enclosing)嵌套作用域

E也包含在def关键字中,E和L是相对的,E相对于更上层的函数而言也是L。与L的区别在于,对一个函数而言,L是定义在此函数内部的局部作用域,而E是定义在此函数的上一层父级函数的局部作用域。主要是为了实现Python的闭包,而增加的实现。

G(global)全局作用域

即在模块层次中定义的变量,每一个模块都是一个全局作用域。也就是说,在模块文件顶层声明的变量具有全局作用域,从外部开来,模块的全局变量就是一个模块对象的属性。
注意:全局作用域的作用范围仅限于单个模块文件内

B(built-in)内置作用域

系统内固定模块里定义的变量,如预定义在builtin 模块内的变量。

作用域链:变量名解析LEGB法则

搜索变量名的优先级:局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域
LEGB法则: 当在函数中使用未确定的变量名时,Python会按照优先级依次搜索4个作用域,以此来确定该变量名的意义。首先搜索局部作用域(L),之后是上一层嵌套结构中def或lambda函数的嵌套作用域(E),之后是全局作用域(G),最后是内置作用域(B)。按这个查找原则,在第一处找到的地方停止。如果没有找到,则会出发NameError错误。

example 1

name = "lzl"

def f1():
  print(name)

def f2():
  name = "eric"
  f1()
  
f2() # 在函数未执行之前,作用域链就已经形成了,此时f1()的上一级应该name = 'lzl'

example 2

def scope_test():
  def do_local():
    spam = "local spam" # 此函数定义了另外的一个spam字符串变量,并且生命周期只在此函数内。此处的spam和外层的spam是两个变量,如果写出spam = spam + “local spam” 会报错
  def do_nonlocal():
    nonlocal spam  # 使用外层的spam变量 test spam
    spam = "nonlocal spam"
  def do_global():
    global spam
    spam = "global spam"
  spam = "test spam"
  do_local()
  print("After local assignmanent:", spam) # test spam
  do_nonlocal()
  print("After nonlocal assignment:",spam) # nonlocal spam
  do_global()
  print("After global assignment:",spam) # nonlocal spam ???? 先找是本地变量,找到的本地变量已经在do_nonlocal()里面改变了所以输出的是nonlocal spam

scope_test()
print("In global scope:",spam) # global spam

以上就是深入了解Python 变量作用域的详细内容,更多关于Python 变量作用域的资料请关注脚本之家其它相关文章!

相关文章

  • 详解Python3 基本数据类型

    详解Python3 基本数据类型

    这篇文章主要介绍了Python3 基本数据类型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • Python Paramiko模块中exec_command()和invoke_shell()两种操作区别

    Python Paramiko模块中exec_command()和invoke_shell()两种操作区别

    invoke_shell 使用 SSH shell channel,而 exec_command 使用 SSH exec channel,本文主要介绍了Python Paramiko模块中exec_command()和invoke_shell()两种操作区别,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Python基于SciPy库实现统计分析与建模

    Python基于SciPy库实现统计分析与建模

    SciPy是一个强大的Python库,提供了丰富的科学计算和数据分析工具,本文我们将探讨如何使用Python和SciPy库进行统计分析和建模,感兴趣的可以学习一下
    2023-06-06
  • Pytorch各种维度变换函数总结

    Pytorch各种维度变换函数总结

    本文对于PyTorch中的各种维度变换的函数进行总结,包括reshape()、view()、resize_()、transpose()、permute()、squeeze()、unsqeeze()、expand()、repeat()函数的介绍和对比,感兴趣的可以了解一下
    2024-02-02
  • 用Python将动态GIF图片倒放播放的方法

    用Python将动态GIF图片倒放播放的方法

    GIF(Graphics Interchange Format) 是一种可以用来呈现动画效果的图片格式,原理就是保存很多帧(Frame)静态图像,然后连续呈现。这篇文章主要介绍了用Python将动态GIF图片倒放播放的方法,需要的朋友可以参考下
    2016-11-11
  • python基于pygame实现飞机大作战小游戏

    python基于pygame实现飞机大作战小游戏

    这篇文章主要为大家详细介绍了python基于pygame实现飞机大作战小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • Python代码连接到 Chat GPT API的方法

    Python代码连接到 Chat GPT API的方法

    Chat GPT 由于其独特、近乎准确且类似人类的响应,如今在互联网上引起了过多的讨论,本文讨论如何通过 Python 代码连接到 Chat GPT API,感兴趣的朋友一起看看吧
    2023-02-02
  • python网络爬虫之如何伪装逃过反爬虫程序的方法

    python网络爬虫之如何伪装逃过反爬虫程序的方法

    本篇文章主要介绍了python网络爬虫之如何伪装逃过反爬虫程序的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • Python基础教程之pytest参数化详解

    Python基础教程之pytest参数化详解

    参数化就是把测试过程中的数据提取出来,通过参数传递不同的数据来驱动用例运行,这篇文章主要给大家介绍了关于Python基础教程之pytest参数化的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-01-01
  • Python3和PyCharm安装与环境配置【图文教程】

    Python3和PyCharm安装与环境配置【图文教程】

    这篇文章主要介绍了Python3和PyCharm安装与环境配置,结合图文形式详细分析了Python3和PyCharm的安装、环境配置、测试命令及相关操作注意事项,需要的朋友可以参考下
    2020-02-02

最新评论