Python——函数作用域

Python作用域基础

当在程序中使用变量名时,Python创建、改变或查找变量名都是在所谓的命名空间中进行的。作用域这个术语指的就是命名空间。在代码中变量名被赋值的位置决定了变量名能被访问到的范围

  • 所有的变量名,包括作用域的定义在内,都是Python赋值的时候生成的。Python中的变量名在第一次赋值时已经创建,并且必须经过赋值后才能使用。
  • 在代码中给一个变量赋值的地方决定了这个变量将存在哪个命名空间,也就是可见范围

函数的作用域

  • 在默认情况下,一个函数的所有变量名都是与函数的命名空间相关联的
    * 一个在def内定义的变量名能够被def内的代码使用,不能再函数的外部引用这样的变量名
    * def之中的变量名与def之外的变量名并不冲突,即使变量名相同也不会冲突。一个在def之外被赋值的变量x与在这个def之中的赋值的变量x时完全不同的变量

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

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

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

作用域法则

  • 函数定义了本地作用域,模块定义了全局作用域
    * 内嵌的模块是全局作用域,每个模块都是一个全局作用域。
    * 全局作用域的作用范围仅限于单个文件,是指在一个文件的顶层的变量名仅对于这个文件内部的代码而言是全局的。必须精确的导入一个模块文件才能够使用这个文件中定义的变量名
    * 每次对函数的调用都创建了一个新的本地作用域,函数只要被调用,就会重新创建函数内的本地作用域
    * 赋值的变量名除非声明为全局变量或非本地变量否则均为本地变量。默认情况下,所有函数定义内部的变量都是本地作用域。
    * 如果需要给一个在函数内部却位于模块文件顶层的变量名赋值,需要在函数内部通过global语句声明
    * 如果需要给位于一个嵌套的def中的名称赋值,在Python3.0开始可以通过在一条nonlocal语句中声明

作用域的产生

在Python中,只有函数(def) 类(class) 模块(module)才会引入新的作用域,其他的代码块不会产生新的作用域

变量名解析:LEGB原则

  • L local 函数中定义的变量
  • E enclosing 嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
  • G global 全局变量 模块级别定义的变量
  • B built-in 系统固定模块里面的变量,比如int, bytearray等
    **Python搜索变量的作用域的优先级是:局部作用域>嵌套作用域>全局变量作用域>内置作用域
    对于一个def语句
  • 变量名引用分为四个作用域进行查找:首先是本地作用域(L),之后是上一层结构中的def或lambda的本地作用域(E),然后是全局作用域(G),最后是Python内置作用域(B),在找到这个变量名后会停止搜索,如果没有找到会报错
  • 在默认情况下,变量名赋值会创建或者改变本地变量
  • 全局声明和非本地声明将赋值的变量名映射到模块文件内部的作用域
>>> # Global scope
>>> X = 99
>>> def func(Y):
...     Z=X+Y
...     return Z 
>>> fun(1)
>>> func(1)
100

内置作用域

  • 内置作用域仅仅是一个名为builtin的内置模块,但是必须要导入后才能使用内置作用域
  • 内置作用域是通过一个名为builtin的标准库模块来实现的,没有放置在作用域内,必须导入这个文件才能使用
LEGB 存在的问题

由于LEGB查找的流程,会使它在找到第一处变量名的地方生效,在本地作用域的变量名可能会覆盖在全局作用域和内置作用域的有着相同变量名的变量。全局变量名可能副高内置的变量名

  • 如果在def内不增加global(nonlocal)声明的话,是没有办法在函数内改变函数外部的变量

locals() globals()

  • locals() 返回一个局部命名空间内容的字典
  • globals() 返回一个全局命名空间内容的字典
>>> animal = 'fruitbat'
>>> def change_local():
...     animal = 'wombat'
...     print('locals',locals())
... 
>>> animal
'fruitbat'
>>> change_local()
locals {'animal': 'wombat'}
>>> print('globals',globals())
globals {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': 
>>> animal
'fruitbat'

名称中 _用法

Python中以两个下划线__开头和结束的名称都是Python的保留用法。因此在自定义的变量中不能使用它们

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

推荐阅读更多精彩内容