先看下面这段代码,显然无法work. 因为代码试图在TestVariableScope()中引用一个没有被定义的变量a.所以必须报错,如下图-1.

不过如果你将第2行代码注释掉。代码就能跑通了,如图-2。

问题1来了:TestVariableScope.a 不是也没有被定义吗,为什么可以work呢?解释如下:先看代码第8行,TestVariableScope.a在SetVariable方法中被定义了,SetVariable()又 在TestVariableScope()前被调用。所以TestVariableScope()在被调用的时候TestVariableScope.a已经被定义了。

问题2来了:代码第7行,a也被定义了。为什么TestVariableScope()在引用a是报错呢。区别在于:a 只是SetVariable()中的一个local变量,TestVariableScope当然无法引用SetVariable中定义的局部变量了。因为违反了LEGB原则吗。TestVariableScope.a 就不一样了,他是一个全局变量哦。所以TestVariableScope当然可以访问这个全局变量了,完全不违反LEGB原则。

问题3来了:为什么TestVariableScope.a是个全局变量,而a却不是呢。因为python中函数皆是对象,而且是全局对象。TestVariableScope.a其实就是TestVariableScope这个全局对象下的一个变量而已,自然也是全局变量喽。 见图-3

 def TestVariableScope():
print(a)
print(TestVariableScope.a)
TestVariableScope.a=13 def SetVariable():
a=12
TestVariableScope.a=12 if __name__=='Demo':
print('Demo is running') if __name__ == '__main__':
SetVariable()
TestVariableScope()
b=TestVariableScope
b()

图-1

图-2

图-3

以下关于LEGB, 引用自:https://magicalboy.com/python-scope-legb

Python 的变量作用域和 LEGB 原则

在 Python 程序中创建、改变或查找变量名时,都是在一个保存变量名的地方进行中,那个地方我们称之为命名空间。作用域这个术语也称之为命名空间。

具体地说,在代码中变量名被赋值(Python 中变量声明即赋值,global 声明的只是变量的使用域)的位置决定了该变量能被访问的范围。函数定义了本地作用域,而模块定义的是全局作用域。这两个作用域之前有如下关系:

  • 每一个模块都是全局作用域。也就是说,创建于模块文件顶层的变量具有全局作用域,对于外部访问就成了一个模块对象的属性。
  • 全局作用域的作用范围仅限于单个文件。“全局”指的是在一个文件的顶层变量名对于这个文件而言是全局的。
  • 每次对函数的调用都创建了一个新的本地作用域。Python 中也有递归,即可以调用自身,每次调用都会创建五个新的本地命名空间。
  • 赋值的变量名除非声明为全局变量,否则均为本地变量。如果需要在函数内部对模块文件顶层的变量名赋值,需要在函数内部通过 global 语句声明该变量。
  • 所有的变量可归纳为本地、全局或者内置三种。范围分别为 def 内部,在一个模块的命名空间内部和预定义的 __builtin__ 模块提供的变量。

变量名解析:LEGB 原则

如果对以上内容有所迷惑的话,请看以下总结出的几条原则。在函数命名空间中:

  • 变量名引用分为三个作用域进行查找:首先是本地,然后是函数内(如果有的话),之后是全局,最后是内置。
  • 在默认情况下,变量名赋值会创建或者改变本地变量。
  • 全局声明将会给映射到模块文件内部的作用域的变量名赋值。
  • Python 的变量名解析机制也称为 LEGB 法则,具体如下: 当在函数中使用未确定的变量名时,Python 搜索 4 个作用域:本地作用域(L),之后是上一层嵌套结构中 def 或 lambda 的本地作用域(E),之后是全局作用域(G),最后是内置作用域(B)。按这个查找原则,在第一处找到的地方停止。如果没有找到,Python 会报错的。
  • 下图说明了搜索流程(由内及外):

Python中通过函数对象创建全局变量的更多相关文章

  1. Python中的函数对象与闭包

    函数在Python中是第一类对象,可以当做参数传递给其他函数,放在数据结构中,以及作为函数的返回结果. 下面的例子为接受另外一个函数作为输入并调用它 #foo.py def callf(func): ...

  2. python中的函数对象与闭包函数

    函数对象 在python中,一切皆对象,函数也是对象 在python语言中,声明或定义一个函数时,使用语句: def func_name(arg1,arg2,...): func_suite 当执行流 ...

  3. python中的函数对象的内存地址是多少

    今天和同学讨论一个问题,发现了函数的内存地址和我想象的不一样. 我以为同一个函数,假如给的参数不一样,那么这两个函数的id就不一样. 然后经过实验,发现python为了便于管理函数,所有的函数都放在同 ...

  4. python中range()函数的用法

    python中range()函数可创建一个整数列表,一般用在for循环中. range()函数语法: range(start,stop[,step]) 参数说明: star: 计数从star开始.默认 ...

  5. python中的一等对象--函数

    一等对象 什么是一等对象: 在运行时创建 能赋值给变量或数据结构中的元素 能作为参数传递给函数 能作为函数的返回结果 python中的字符串,列表什么的都是一等对象,但对如果之前只是使用c++.jav ...

  6. js中函数对象创建的总结

    在JavaScript的函数对象创建方法中,可以分为三种情况: 1:第一种是使用function语句定义函数 <script type="text/javascript"&g ...

  7. python中的函数、生成器的工作原理

    1.python中函数的工作原理 def foo(): bar() def bar(): pass python的解释器,也就是python.exe(c编写)会用PyEval_EvalFramEx(c ...

  8. [19/10/13-星期日] Python中的函数

    一.函数 # 第五章 函数 ## 函数简介(function) - 函数也是一个对象 - 对象是内存中专门用来存储数据的一块区域 - 函数可以用来保存一些可执行的代码,并且可以在需要时,对这些语句进行 ...

  9. python中isinstance函数

    1.描述 python中isinstance()函数,是python中的一个内置函数,用来判断一个函数是否是一个已知的类型,类似type(). 2.语法 isinstance(object,class ...

随机推荐

  1. 用org.mybatis.generator 生成代码

    1:引入pom 2:增加生成配置xml: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...

  2. hadoop学习笔记(二):centos7三节点安装hadoop2.7.0

    环境win7+vamvare10+centos7 一.新建三台centos7 64位的虚拟机 master node1 node2 二.关闭三台虚拟机的防火墙,在每台虚拟机里面执行: systemct ...

  3. py-函数基础

    定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 1.减少重复代码2.使程序变的可扩展3.使程序变得易维护 函数参数 形参变量 只有在被调 ...

  4. 关于FIR的modelsim

    (1)FIR ip核仿真 (2)FIR 多通道应用 (3)多通道fir ip核需要注意的复位问题 =================================================== ...

  5. 抓包工具 - HttpWatch(功能详细介绍)

    HttpWatch是功能强大的网页数据分析工具,集成在IE工具栏,主要功能有网页摘要.cookies管理.缓存管理.消息头发送/接收,字符查询.POST数据.目录管理功能和报告输出.HttpWatch ...

  6. NLTK之WordNet 接口

    WordNet是面向语义的英语词典,类似于传统字典.它是NLTK语料库的一部分,可以被这样调用: 更简洁的写法: 1.单词 查看一个单词的同义词集用synsets(); 它有一个参数pos,可以指定查 ...

  7. 导出delphi编写的ios程序在xcode下的日志

  8. TFS 如何強制撤銷被簽出的文件

    我们在使用TFS (Team Foundation Server) 源代码管理的时候,源代码管理会在每个PC上创建一个工作区,然后这个工作区域映像到服务器上的源码文件夹,我们在正常签入,签出的时候,我 ...

  9. Jersey构建Restful风格的webservices

    最近一直在搞老项目的开发工作,很少写博文了.听了两位阿里巴巴大牛的讨论,决定试试用restful风格的webservices看看. 这里用的是Jersey这个框架,刚开始弄,有点麻烦,只能到处查资料. ...

  10. [ACM_模拟] UVA 12504 Updating a Dictionary [字符串处理 字典增加、减少、改变问题]

      Updating a Dictionary  In this problem, a dictionary is collection of key-value pairs, where keys ...