热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:Python名称绑定和作用域的关系??

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python名称绑定和作用域的关系??相关的知识,希望对你有一定的参考价值。1.作用域Pyth

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python名称绑定和作用域的关系??相关的知识,希望对你有一定的参考价值。



1.作用域

Python中的作用域定义了名字在代码块中的可见性。如果在代码块中定义了一个局部变量,那么这个局部变量的作用域就是所在的这个代码块。如果这个定义发生在函数体内,则这个变量的作用域就扩展到包含在这个函数中的任何代码块中,但是,如果包含在这个函数中的一个代码块中,同样的名字被绑定到了不同的对象上,(创建了新对象并绑定了新名字)那么外面的名字将不能被扩展到这个代码块中。


2.名称绑定和作用域的关系

如果一个名字绑定到一个代码块中,除非这个名字声明为nonlocal(nonlocal声明的作用是:使得变量在外围作用域中,在全局作用域之前被解析),否则这个名字就是这个代码块的局部变量。如果一个名字被绑定到模块级别,则这个名字的作用域是全局的,这个变量是全局变量(模块中的变量,对于模块而言是局部变量,而对于模块中的代码块而言,则是全局变量)。如果一个名字在一个代码块中使用,但是不是在这个代码块中被定义的,则这个变量就是一个自由变量

发生名字绑定的行为主要有:



  • 通常的给函数传递参数的时候,参数名会和传递过来的对象进行绑定

  • 使用import语句进行导入的时候,其中 from ... import * 语句会将被导入的模块中的所有可以被导入的名字进行绑定操作

  • 类定义的时候

  • 函数定义的时候

  • 进行赋值操作的时候

  • 在for循环的for语句中

  • 在with语句中的as后面

  • 在expect语句中的as后面


3.Python中名字绑定的陷阱

在Python中,名字绑定的一些规则,会导致在使用名字的时候,出现不能理解的错误,特别是对于有C、C++ 和 Java经验的用户。

在Python中,名字绑定操作无论发生在当前块的 任何 位置,在这个代码块中对这个名字的引用都会使用在当前块中绑定的对象。那么,问题就来了,如果我们在名字绑定操作发生之前对这个名字进行了引用,那么就会出现错误,抛出 UnboundLocalError 异常。



>>> a = 10
>>> def function():
print(a)
a
= 20 # a的绑定操作发生在print之前

>>> function()
Traceback (most recent call last):
File
"", line 1, in
function()
File
"", line 2, in function
print(a)
UnboundLocalError: local variable
a referenced before assignment


在Python中,代码块中的局部变量可以通过扫描整个代码块来获得绑定的名字,所以在上面的代码中,a这个名字在执行print的时候通过对代码块的扫描已经被找到,但是名字a的绑定操作却还没有发生,所以出现了错误。

在上面的代码中,如果我们需要外面定义的全局变量a,则可以使用global 语句进行声明。



>>> a = 10
>>> def function():
global a
print(a)
a
= 20 #这里并不引入新的名字,而是将全局变量a绑定到20上

>>> function()
10
>>> a
20

 

 

global 语句的作用是,使得后面对通过这条语句声明的对象的引用,使用的是顶层名字空间中的名字。在顶层名字空间中,包含了全局名字空间和内建名字空间,全局名字空间会首先被搜索,如果没有找到,会对内建名字空间进行搜索global 语句必须出现在名字使用之前。

如果在外围作用域中的自由变量包含了一个global声明,则这个自由变量被认为是全局的。


4.内建名字空间

在查找内建名字空间的时候,会访问当前代码块的全局名字空间中的 __builtins__名字,这个名字引用的是一个名字字典或者是一个模块。在 __main__ 模块中, __builtins__ 的引用是内建模块 builtins,然而,如果是在其他模块中, __builtins__ 引用的是 builtins 模块的名字字典。


print(globals())


{__name__: __main__, __doc__: None, __package__: None, __loader__: <_frozen_importlib_external.SourceFileLoader object at 0x000000000211B0F0>, __spec__: None, __annotations__: {},
__builtins__‘: , __file__: C:/Users/Administrator/PycharmProjects/15group/level_2/day2/core/mm/aaad.py, __cached__: None}

 


import builtins
print(builtins.abs(-2)) #内建模块可以调用内置方法

 


注意:
CPython的实现中,不能手动修改 __builtins__ 这个变量,如果需要覆盖这个内建名字空间中的名字,需要导入 builtins 模块,然后修改这个模块中相应的属性。


 

学习自:http://www.cnblogs.com/now-fighting/p/4622453.html








推荐阅读
author-avatar
成都迅捷代驾
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有