浅谈python函数之作用域(python3.5)
作者:Wadirum 发布时间:2021-09-22 05:49:42
1 基本概念
1.1 命名空间 (namespace)
命名空间是变量名到对象的映射(name -> obj)。目前大多数的命名空间以类似于python字典的形式实现,实现形式在未来可能发生变化。命名空间举例:内置变量(内置函数abs, 内置的异常等),模块中的全局变量,函数调用时的局部变量。在某种意义上讲,对象的属性也形成一个命名空间。重要的是,不同的命名空间中的变量没有任何关联,两个不同的命名空间中可以包含相同的变量名。
命名空间有不同的创建时间和生命周期:
•内置变量命名空间在python解释器启动时创建,并且在解释器运行期间永远不会被删除;
•一个模块的命名空间在模块被导入时创建,并且到解释器退出会一直存在;
•函数的本地(局部)命名空间在函数调用时创建,函数退出时删除;
•解释器顶层执行的语句都是 __main__ 模块的组成部分,它们有自己的命名空间。
注:内置变量实际上同样是以模块的形式存在,模块名为 builtins 。
1.2 作用域 (scope)
作用域是Python程序中可以直接访问一个命名空间内变量的文本区域,可直接访问即命名空间内的变量在该文本区域内可见、可引用。
•本地(局部)作用域:函数或者类的内部
•全局作用域:整个程序的运行环境。
全局作用域中无法直接访问本地作用域中定义的变量:
def func1():
name = 1
print(func1) # <function func1 at 0x101a03d08>
print(name)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# NameError: name 'name' is not defined
本地作用域中的变量定义:
•在python中,变量赋值即定义。在局部作用域内被赋值的变量,除非由 global 或者 nonlocal 声明,否则全部为局部变量,函数调用时存在于函数命名空间。
•global var : 声明变量 var 为全局变量,它所有的引用和赋值都在模块的命名空间进行。
•nonlocal var : 将外层函数命名空间中的变量 var 绑定到本地作用域,使其在本地作用域可重新赋值。如果变量没有被声明为 nonlocal,这些变量在本地作用域仅可读,尝试给变量赋值则会在本地命名空间创建一个同名变量。
nonlocal声明的变量在上层函数中必须存在,否则报错:
test = 'global variable'
def scope_test():
def inner():
nonlocal test
print(test)
scope_test() # SyntaxError: no binding for nonlocal 'test' found
2 示例
2.1 本地作用域中变量的搜索遵守LEGB规则
1.L-Local(function):函数或类的命名空间,其中的变量称为本地变量
2.E-Enclosing function locals:外层函数的命名空间(例如closure),包含被声明为non-local的变量
3.G-Global(module):函数定义所在模块的命名空间,其中的变量称为全局变量
4.B-Builtin(Python):Python内置模块的名字空间
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam# 递归向上寻找上层函数命名空间中的spam变量
spam = "nonlocal spam"
def do_global():
global spam # 在全局变量中寻找spam变量,没有则创建
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam) # 输出本地变量 spam
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test()
print("In global scope:", spam)
结果
<SPAN style="FONT-SIZE: 14px">1 After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
</SPAN>
2.2 闭包
闭包:在嵌套函数中,如果内层函数引用了外层函数的变量,就形成了一个闭包。
自由变量:被引用的外层函数变量,称为内层函数的自由变量。
def fn():
a = 1
def closure():
nonlocal a
a += 1
print(a)
return closure
inner = fn()
print(inner.__closure__) # (<cell at 0x10240b408: int object at 0x100277bc0>,)
inner() # 2
inner() # 3
外层函数执行完,其命名空间删除。但是因为 a 是内层函数的自由变量,所以变量 a 被保留,可以看作是 closure 函数对象的一个附加属性。
3 静态检测
3.1 本地变量
python是在编译def语句时静态检测其本地变量的。
a = 1
def local_test():
a += 1
print(a)
local_test() # UnboundLocalError: local variable 'a' referenced before assignment
print(b) # NameError: name 'b' is not defined
在编译local_test函数时,python就确定了变量 a 为函数的本地变量。所以在执行 a += 1 是会直接在本地命名空间寻找变量a。
3.2 命名空间搜索链
name = "lzl"
def f1():
print(name)
def f2():
name = "eric"
f1()
f2() # lzl
一个函数的变量搜索路径是在它定义的时候决定的,不受它调用位置的影响。
f1定义在全局作用域中,其变量的搜索路径为:本地命名空间 --> 模块命名空间。所以最后的输出结果为‘lzl'。
4 匿名函数
Python借助lambda关键字定义匿名函数,格式如下:
lambda 参数列表: 表达式
lambda x: x + 1
# 函数功能类型于下面的函数
def _(x):
return x + 1
示例
下面一段代码的输出结果是什么:
li = [lambda :x for x in range(10)]
print(li[0]())
其等价形式:
def fn():
return x
li = []
for x in range(10):
li.append(fn)
li[0]() # fn() -> 9,根据变量搜索规则,x在函数中没有定义,在全局变量中查找
来源:http://www.cnblogs.com/wadirum/archive/2017/10/26/7674740.html
猜你喜欢
- 前端时间写了一篇《利用CSS框架进行高效率的站点开发》,有不少朋友问我相关的问题。很早5key就在公司进行CSS框架的架构,也对不少朋友提出
- 最近看到了两行 JavaScript 代码,很受启发。1. 封装 DOM 属性在 JavaScript 中,我们可以获取HTML元素的属性值
- 在获得网页响应对象res后,使用res.text属性可以获得网页源代码,但可能出现乱码!因为requests库会使用自动猜测的解码方式将抓取
- 你是否对获得MySQL改变字符集的实际操作感到十分头疼?不用急,以下的文章将会给你正确的解答方案,以下的文章主要是介绍获得MySQL改变字符
- 1.通过pip安装python第三方模块paramikopip install paramiko2.创建脚本##导入paramiko、tim
- Dreamweaver MX 2004 试用试用心得:安装:选择工作界面(我选了默认的设计模式)初次启动,选择30天试用如果你也看到这个警告
- 本文实例讲述了Python装饰器(decorator)定义与用法。分享给大家供大家参考,具体如下:什么是装饰器(decorator)简单来说
- 以前的服务器,由于内存的价格过高,一般配置的内存不是很多,超过4GB的当然就不多了.现在的服务器,配置超过4GB就很多,在配作SQL 数据库
- 我看blog里,还有很多地方都引用过我写的这个类,转了不少,但自己一直也没发表过,这次正式发表一下。在蓝色理想中有人不懂怎么用,我在baid
- 好几年前我在做一些自动化的脚本时,脑子里也闪过这样的想法:能不能直接把浏览器的cookies取出来用呢?直到昨天看到代码《python模拟发
- 使用微信获取地址信息是和微信支付一道申请的,微信支付申请通过,就可以使用该功能。微信商城中,使用微信支付获取用户的收货地址,可以省略用户输入
- 阅读上一章:Chapter 10 应用CSSChapter 11 打印样式先前在第10章中,讨论了几种为文档应用CSS的方法,这一章是要研究
- HTML5 中 div section article 的区别刚刚开始接触 HTML5 时,对它的标签很不适应,甚至一度有点反感。尤其是对
- 先上个效果图: Sample6_1.php 中创建Form: //显示上传状态和图片 <div id="showi
- 前言21世纪是信息的世纪,综合国力的竞争在很大程度上是信息的竞争,更是信息利用率的竞争。近年来,随着“数字地球”和“数字国土”战略的提出和实
- 算法是计算机科学中一个重要的研究方向,是解决复杂问题的关键。在计算机世界中,算法无处不在。数据库是存储数据和执行大批量计算的场所,在数据库中
- 三元条件判断的3种实现方法C语言中有三元条件表达式,如 a>b?a:b,Python中没有三目运算符(?:),但Python有它自己的
- PayPal支付功能其实一直在更新文档和接口,这里说的是一个简单的支付功能大概流程如下1,在网站的结账页面,设置一个提交到PayPal网站的
- 因此,我们主要解决的思路是效验session ID的有效性. 以下为引用的内容: <?php if(!isset($_SESSION[
- insert into(列名) select 列名 from 表名 where 条件 --不创建表,只复制表数据 select 列名 int