Python 作用域和命名空间

Python Scopes and Namespaces

namespace is a mapping from names to objects.

命名空间是一个从名字到对象的映射(指向,明确的路径)。

Most namespaces are currently implemented as Python dictionaries。

大部分都是由字典dict(其他语言也称为hash)实现。

例子:

the set of built-in names 。放置内置函数的集合。模块中的全局名称;函数调用中的局部名称。 从某种意义上说,对象的属性集合也是一种命名空间的形式。

namespaces is that there is absolutely no relation between names in different namespaces.

不同命名空间的名字之间没有关系,即相同的名字,在不同的命名空间是没有任何关系的。

生存周期lifetimes。

Namespaces are created at different moments and have different lifetimes.

例如:

模块的全局命名空间在模块定义被读入时创建,并持续到解释器退出。内置名称实际上也存在于一个模块builtins中。

函数的local namespace在函数被调用时创建,在函数返回或抛出一个不在函数内处理的?时被删除。

作用域

scope is a textual region of a Python program where a namespace is directly accessible.

作用域是一个代码区域,是一个命名空间可以直接引用的区域。

我的理解:

调用函数形成的函数内部的命名空间(映射/指针/路径/hash),在函数内部可以使用函数代码外定义的名字,由此得到名字对应的对象。那么函数代码外部的代码区域,就是一个可被这个函数直接使用的作用域。

??函数的外部作用域是在函数定义时,对应的位置,而不是调用时对应的位置。

??:参考了这篇文章:https://www.linuxidc.com/Linux/2018-12/155918.htm

命名空间的查找顺序:

 Local首先搜索,包含局部名字的最内层(innermost)作用域,如函数/方法/类的内部局部作用域;

 Enclosing根据嵌套层次从内到外搜索,包含非局部(nonlocal)非全局(nonglobal)名字的任意封闭函数的作用域。如两个嵌套的函数,内层函数的作用域是局部作用域,外层函数作用域就是内层函数的 Enclosing作用域;

 Global倒数第二次被搜索,包含当前模块全局名字的作用域;

 Built-in最后被搜索,包含内建名字的最外层作用域。

Python按照以上LEGB的顺序依次在四个作用域搜索名字,没有搜索到时,Python抛出NameError异常。

用一个类比来理解命名空间与作用域:

  四种作用域相当于我们生活中的国家(Built-in)、省(Global)、市(Enclosing)、县(Local),命名空间相当于公务员花名册,记录着哪个职位是哪个人。国家级公务员服务于全国
民众(全国老百姓都可以喊他办事),省级公务员只服务于本身民众(国家层面的人或者其他省的人我不管),市(Enclosing)、县(Local)也是一个道理。当我们要找某一类领导(例如想找
个警察帮我打架)时(要访问某个名称),如果我是在县(Local)里头,优先在县里的领导花名册中找(优先在自己作用域的命名空间中找),县里花名册中没警察没有就去市里的花名册找(往
上一层作用域命名空间找),知道找到国家级都还没找到,那就会报错。如果省级民众想找个警察帮忙大家,不会找市里或者县里的,只会找自己省里的(其它省都不行),或者找国家级的。国家、
省、市、县肯定一直都在那里,可不会移动(作用域是静态的);领导可以换届,任期移到就换人(命名空间是动态的,每次调用函数都会新的命名空间,函数执行

glocal与nonlocal的区别

第一,两者的功能不同。

global关键字修饰变量后标识该变量是全局变量,对该变量进行修改就是修改全局变量,而nonlocal关键字修饰变量后标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal位置会发生错误。

def f1():
    # i = 1
    def f2():
        nonlocal i
        print(i)
        i = 2
    f2()
    print(i)

f1()
# SyntaxError: no binding for nonlocal ‘i‘ found

第二,两者使用的范围不同。

  • global关键字可以用在任何地方,包括最上层函数中和嵌套函数中,即使之前未定义该变量,global修饰后也可以直接使用。
  • nonlocal关键字只能用于嵌套函数中,并且外层函数中定义了相应的局部变量,否则会发生错误。
i = 0
def f1():
    i = 1
    def f2():
        global i     #重新绑定
        print("global", i)
        i = 2
    f2()
    print("local",i)

f1()
# 输出:
# global 0
# local 1

几个例子:

i = 1

def f1():
    print(i)

def f2():
    i = 2
    f1()

f2()

print(i)

#输出
#1
#1

解释:这个例子,说明了函数的外部作用域,是函数定义时的外部代码。

if True:

  i = 1

print(i) # 可以正常输出i的值1,不会报错

解释:这说明了if语句不产生新的作用域, 只有函数/类才会产生新作用域。

for i in range(10):

  pass

print(i) #输出结果是9,而不是NameError

解释: 无关作用域,i被声明,并被赋值。

def test():

    print(i)

  i= 2

i = 0

test()

解释:会报告错误,UnboundLocalError: local variable ‘i‘ referenced before assignment。i已经被占用了。所以不能再被重新声明。

class A(object):

    a = 2

    def fun(self):

        print(a)

new_class = A()

new_class.fun()
#NameError: name ‘a‘ is not defined

解释:还不理解。fun函数的外部作用领中,没有a。

原文地址:https://www.cnblogs.com/chentianwei/p/11969856.html

时间: 2024-09-28 16:37:18

Python 作用域和命名空间的相关文章

Python3.2官方文档翻译--作用域和命名空间

6.2 Python作用域和命名空间 在介绍类之前,首先我想告诉你一些关于python作用域的规则.类的定义非常巧妙地运用了命名空间,你需要知道范围和命名空间的工作原理以能全面了解接下来发生的. 顺便说一下,关于这节讲到的知识对于任何优秀的python程序员非常有用. 让我们开始以一些定义开始. 命名空间(namespace)是一个从名称到对象的映射.大多命名空间目前用Python字典实现的,但那通常不会被注意(除非为了性能),在将来它可以改变.命名空间的例子是:内置名称的set(包含函数如ab

详解Python的作用域和命名空间

最近在学习Python,不得不说,Python真的是一门很好用的语言.但是学习的过程中关于变量作用域(scope)的命名空间(namespace)的问题真的把我给搞懵了.在查阅了相关资料之后,觉得自己对Python的作用域和命名空间有了一定得了解.故写在这里,一方面加深自己的理解,另一方面分享知识. 一.本篇博客需要解决的问题. 1.什么是作用域和命名空间? 2.Python中作用域和命名空间的工作原理是什么? 3.我怎样在Python中声明一个全局变量(global variable),局部变

Python3.2官方文档翻译--作用域和命名空间实例

6.2.1 作用域和命名空间实例 以下的实例主要用来示范怎样引用不同的作用域和命名空间,keywordglobal和nonlocalru怎样影响变量绑定. 实例执行结果是: After local assignment: test spam After nonlocal assignment: nonlocal spam After global assignment: nonlocal spam In global scope: global spam 注意局部赋值(这是默认的)不能改变sco

python作用域和多继承

python作用域 python无块级作用域 看c语言代码: #include<stdio.h> int main() { if(2 > 0) { int i = 0; } printf("i = %d", i); return 0; } 在这段代码中,if子句引入了一个局部作用域,变量i就存在于这个局部作用域中,但对外不可见,因此,接下来在printf函数中对变量i的引用会引发编译错误,但是在python中并非如此 看下面代码: if 1 == 1: name =

day10 Python作用域 Python2.7与Python3.x的类继承的区别及其他

一.Python作用域   1.Python中无块级作用域 if 1 == 1: name = 'test' print(name) #输出会报错,因为name的作用域仅限于if下的代码块,而不属于全局   2.Python中以函数为作用域 def func(): func_name = 'func_test' print(func_name) #这里同样会报错,因为变量func_name的作用于func函数中   3.Python作用域链,层层嵌套,使用时从内向外找   4.Python的作用

Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print("test1") def test(): print("test") return test1 res = test() print(res) 输出结果 test <function test1 at 0x021F5C90> 分析:这里print(res)输出的是te

Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数

一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(First-Class Object)呢? 在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量.可以作为元素添加到集合对象中.可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性就是第一类对象所特有的. 1.函数身为一个对象,拥有对象模型的三个通用属性:id.类型.和值.

【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】

一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(First-Class Object)呢? 在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量.可以作为元素添加到集合对象中.可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性就是第一类对象所特有的. 1.函数身为一个对象,拥有对象模型的三个通用属性:id.类型.和值.

python进阶之命名空间与作用域

python进阶内功篇 命名空间和作用域 命名空间 Namespace Namespace命名空间,命名空间是一个字典(dictionary),它的键就是变量名,它的值就是那些变量的值.命名空间的一大作用是避免名字冲突. python使用命名空间记录变量的轨迹.python中有三个命名空间: 命名空间 名称 记录数据 函数的命名空间 局部命名空间 (local namespace) 记录了函数的参数和局部定义的变量 模块的命名空间 全局命名空间 (global namespace) 记录了模块的