侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 7年前   177

1 基本概念

1.1 命名空间 (namespace)

命名空间是变量名到对象的映射(name -> obj)。目前大多数的命名空间以类似于python字典的形式实现,实现形式在未来可能发生变化。命名空间举例:内置变量(内置函数abs, 内置的异常等),模块中的全局变量,函数调用时的局部变量。在某种意义上讲,对象的属性也形成一个命名空间。重要的是,不同的命名空间中的变量没有任何关联,两个不同的命名空间中可以包含相同的变量名。

命名空间有不同的创建时间和生命周期:

•内置变量命名空间在python解释器启动时创建,并且在解释器运行期间永远不会被删除;

•一个模块的命名空间在模块被导入时创建,并且到解释器退出会一直存在;

•函数的本地(局部)命名空间在函数调用时创建,函数退出时删除;

•解释器顶层执行的语句都是 __main__ 模块的组成部分,它们有自己的命名空间。

注:内置变量实际上同样是以模块的形式存在,模块名为 builtins 。

1.2 作用域 (scope)

作用域是Python程序中可以直接访问一个命名空间内变量的文本区域,可直接访问即命名空间内的变量在该文本区域内可见、可引用。

•本地(局部)作用域:函数或者类的内部

•全局作用域:整个程序的运行环境。

全局作用域中无法直接访问本地作用域中定义的变量:

def func1(): name = 1print(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 closureinner = fn() print(inner.__closure__)  # (<cell at 0x10240b408: int object at 0x100277bc0>,)inner() # 2inner() # 3

外层函数执行完,其命名空间删除。但是因为 a 是内层函数的自由变量,所以变量 a 被保留,可以看作是 closure 函数对象的一个附加属性。

3 静态检测

3.1 本地变量

python是在编译def语句时静态检测其本地变量的。

a = 1def local_test():  a += 1  print(a)local_test()  # UnboundLocalError: local variable 'a' referenced before assignmentprint(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+pyqt实现右下角弹出框
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(95个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客