第十七章、作用域

Python作用域基础

当你在一个程序中适用变量名时,Python创建、改变或查找变量名都是在所谓的命名空间(一个保存变量名的地方)中进行的。当我们谈论到搜索变量名对应于代码的值的时候,作用域这个术语指的就是命名空间。

关于所有变量名,包括作用域的定义在内,都是Python赋值的时候生成的。

在默认的情况下,一个函数的所有变量名都是与函数的命名空间相关联的。这意味着:

①、一个在def内定义的变量名能够被def内的代码使用。不能在函数的外部引用这样的变量名。

②、def之中的变量名与def之外的变量名并不冲突,即使是使用在别处的相同的变量名。

变量可以在3个不同的地方分配,分别对应3个不同的作用域:

①、如果一个变量在def内赋值,它被定位在这个函数之内。

②、如果一个变量在一个嵌套的def中赋值,对于嵌套的函数来说,它是非本地的。

③、如果在def之外赋值,它就是整个文件全局的。

1、作用域法则:

①、内嵌的模块是全局作用域。

②、全局作用域的作用范围仅限于单个文件。

③、每次对函数的调用都创建了一个新的本地作用域。

④、赋值的变量名除非声明为全局变量或非本地变量,否则均为本地变量。

⑤、所有其他的变量名都可以归纳为本地、全局或者内置的。

2、变量名解析:LEGB原则:

对于一个def语句:

①、变量名引用分为三个作用域进行查找:首先是本地,之后是函数内(如果有的话),之后是全局,最后是内置。

②、在默认情况下,变量名赋值会创建或者改变本地变量。

③、全局声明和非本地声明将赋值的变量名映射到模块文件内部的作用域。

Python的变量名解析机制有时称为LEGB法则,这也是由作用域的命令而来的。

①、当在函数中使用未认证的变量名时,Python搜索4个作用域【本地作用域(L),之后是上一层结构中def或者lambda的本地作用域(E),之后是全局作用域(G)),最后是内置作用域(B)】并且在第一处能够找到这个变量名的地方停下来。如果变量名在这次搜索中没有找到,Python会报错。

②、当在函数中给一个变量名赋值时(而不是在一个表达式中对其进行引用),Python总是创建或改变本地作用域的变量名,除非它已经在那个函数中声明为全局变量。

③、当在函数之外给一个变量名赋值时(也就是,在一个模块文件的顶层,或者是在交互提示模式下),本地作用域与全局作用域(这个模块的命名空间)是相同的。

3、作用域实例:

4、内置作用域:

5、global语句:

①、全局变量是位于模块文件内部的顶层的变量名。

②、全局变量如果是再函数内被赋值的话,必须经过声明。

③、全局变量名在函数的内部不经过声明也可以被引用。

6、最小化全局变量:

7、最小化文件间的修改:

8、其他访问全局变量的方法:

作用域和嵌套函数

1、嵌套作用域的细节:

对于一个函数:

①、一个引用(X)首先在本地(函数内)作用域查找变量名X;之后会在代码的语法上嵌套了的函数中的本地作用域,从内到外查找;之后查找当前的全局作用域(模块文件);最后再内置作用域内(模块__builtin__)。全局声明将会直接从全局(模块文件)作用域进行搜索。

②、在默认情况下,一个赋值(X=value)创建或改变了变量名X的当前作用域。

2、嵌套作用域举例:

①、工厂函数:

根据要求的对象,这种行为有时也叫做闭合(closure)或者工厂函数——一个能够记住嵌套作用域的变量值的函数,尽管那个作用域或许已经不存在了。

②、使用默认参数来保留嵌套作用域的状态:

③、嵌套作用域和lambda:

像def一样,lambda表达式引入了新的本地作用域。

④、作用域与带有循环变量的默认参数相比较:

在已给出的法则中有个值得注意的特例:如果lambda或者def在函数中定义,嵌套在一个循环之中,并且嵌套的函数引用了一个上层作用域的变量,该变量被循环所改变,所有在这个循环中产生的函数将会有相同的值——在最后一次完成时被引用变量的值。

⑤、任意作用域的嵌套:

nonlocal语句

1、nonlocal基础:

①、global使得作用域查找从嵌套的模块的作用域开始,并且允许对那里的名称赋值。如果名称不存在于该模块,作用域查找继续到内置作用域,但是,对全局名称的赋值总是在模块的作用域中创建或修改它们。

②、nonlocal限制作用域查找知识嵌套的def,要求名称已经存在于那里,并且允许对它们赋值。作用域查找不会继续到全局或内置作用域。

2、nonlocal应用:

①、使用nonlocal进行修改:

②、边界情况:

首先,和global语句不通,当执行一条nonlocal语句时,nonlocal名称必须已经在一个嵌套的def作用域中赋值过,否则将会得到一个错误——不能通过在嵌套的作用域中赋给它们一个新值来创建它们。

其次,nonlocal限制作用域查找仅为嵌套的def,nonlocal不会在嵌套的模块的全局作用域或所有def之外的内置作用域中查找,即便已经有了这些作用域。

3、为什么使用nonlocal:

①、与全局共享状态:

在Python2.6中实现nonlocal效果的一种通用方法也是较早的方法,就是直接把状态移出全局作用域(嵌套的模块)。

②、使用类的状态(预览):

Python2.6中针对可改变信息的另一种较早的方法是使用带有属性的类,从而让状态信息的访问比隐式的范围查找规则更明确。

③、使用函数属性的状态:

我们有时候可以使用函数属性实现与nonlocal相同的效果——用户定义的名称直接附加给函数。

本章小结

这一章,我们学习了关于函数的两个关键概念:作用域(当使用时变量如何查找)。正如我们所学的那样,变量作为它所赋值的函数定义的本地变量,除非它们特定地声明为全局变量或非本地变量。我们也学过了一些更高级的作用域概念,包括嵌套函数作用域和函数属性。最后,我们学习了一些通用的设计观点(避免使用全局变量和跨文件间的修改)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容