浅谈python函数之作用域(python3.5)


Posted in Python onOctober 27, 2017

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在函数中没有定义,在全局变量中查找

以上这篇浅谈python函数之作用域(python3.5)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中的FTP通信模块ftplib的用法整理
Jul 08 Python
Python使用Selenium+BeautifulSoup爬取淘宝搜索页
Feb 24 Python
python解决js文件utf-8编码乱码问题(推荐)
May 02 Python
500行Python代码打造刷脸考勤系统
Jun 03 Python
Python语法分析之字符串格式化
Jun 13 Python
Python网络编程之使用TCP方式传输文件操作示例
Nov 01 Python
使用TensorFlow搭建一个全连接神经网络教程
Feb 06 Python
Python各种扩展名区别点整理
Feb 27 Python
python实现逻辑回归的示例
Oct 09 Python
使用python把xmind转换成excel测试用例的实现代码
Oct 12 Python
使用python向MongoDB插入时间字段的操作
May 18 Python
如何用python清洗文件中的数据
Jun 18 Python
python+pyqt实现右下角弹出框
Oct 26 #Python
python中模块的__all__属性详解
Oct 26 #Python
Python内建函数之raw_input()与input()代码解析
Oct 26 #Python
python分布式环境下的限流器的示例
Oct 26 #Python
Python Nose框架编写测试用例方法
Oct 26 #Python
Python面向对象编程基础解析(二)
Oct 26 #Python
Python面向对象编程基础解析(一)
Oct 26 #Python
You might like
桌面中心(二)数据库写入
2006/10/09 PHP
PHP similar_text 字符串的相似性比较函数
2010/05/26 PHP
PHP中使用xmlreader读取xml数据示例
2014/12/29 PHP
PHP addAttribute()函数讲解
2019/02/03 PHP
表单提交时自动复制内容到剪贴板的js代码
2007/03/16 Javascript
js trim函数 去空格函数与正则集锦
2009/11/20 Javascript
目前流行的JavaScript库的介绍及对比
2013/09/29 Javascript
jquery validate 自定义验证方法介绍 日期验证
2014/02/27 Javascript
查询json的数据结构的8种方式简介
2014/03/10 Javascript
在JavaScript中重写jQuery对象的方法实例教程
2014/08/25 Javascript
使用jQuery操作HTML的table表格的实例解析
2016/03/13 Javascript
AngularJS动态加载模块和依赖的方法分析
2016/11/08 Javascript
Popup弹出框添加数据实现方法
2017/10/27 Javascript
Vue中添加手机验证码组件功能操作方法
2017/12/07 Javascript
jquery实现楼层滚动效果
2018/01/01 jQuery
javascript性能优化之分时函数的介绍
2018/03/28 Javascript
Vue 将后台传过来的带html字段的字符串转换为 HTML
2018/03/29 Javascript
React 无状态组件(Stateless Component) 与高阶组件
2018/08/14 Javascript
[15:15]教你分分钟做大人:狙击手
2014/10/30 DOTA
[01:14:12]2018DOTA2亚洲邀请赛4.7 总决赛 LGD vs Mineski 第二场
2018/04/09 DOTA
[49:28]VP vs Optic 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python3编写C/S网络程序实例教程
2014/08/25 Python
Python深入学习之特殊方法与多范式
2014/08/31 Python
Python检测字符串中是否包含某字符集合中的字符
2015/05/21 Python
CentOS7下python3.7.0安装教程
2018/07/30 Python
Python 3 使用Pillow生成漂亮的分形树图片
2019/12/24 Python
基于Tensorflow的MNIST手写数字识别分类
2020/06/17 Python
Python连接mysql方法及常用参数
2020/09/01 Python
意大利火车票和铁路通行证专家:ItaliaRail
2019/01/22 全球购物
泰海淘:泰国king Power王权免税集团旗下跨境海淘综合型电商
2020/07/26 全球购物
卫校毕业生自我鉴定
2013/10/31 职场文书
《池塘边的叫声》教学反思
2014/04/12 职场文书
医院院务公开实施方案
2014/05/03 职场文书
医疗专业毕业生求职信
2014/08/28 职场文书
2015年度个人业务工作总结
2015/04/27 职场文书
win10电脑关机快捷键是哪个 win10快速关机的几种方法
2022/08/14 数码科技