闭包

自由变量:未在本地作用域中定义的变量,例如定义在内存函数外的外层函数的作用域中的变量;

闭包:出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包;

示例1:

# -*- coding: utf-8 -*-
def counter():
c = [0]
print(id(c),"wai")
def inc():
c[0] += 1
print(id(c),"nei")
return c[0]
return inc
foo = counter()
print(foo(),foo())
print(foo())

  代码解析:

  第四行不会报错,c已经在counter函数中定义过了,而且inc中的使用方式是为c的元素修改值,而不是重新定义;

  第七行return inc 返回的是一个函数对象;

  第八行打印1,2;调用函数对象;

  第十行打印3,因为第九行的c和counter中的c不一样,而inc引用的是自由变量正式counter的函数;

  这是python2中实现闭包的方式,pyton3还可以使用nonlocal关键字;

示例2:

  

   上图代码使用global可以运行,但是这使用的是全局变量,而不是闭包;

   如果要对普通变量的闭包,python3中可以使用nonlocal;

nonlocal关键字

  使用了nonlocal关键字,将变量标记为在上级的局部作用域中定义,但不能在全局作用域中定义

示例:

      

  上图中count是外层函数的局部变量,被内部函数引用;内部函数使用nonlocal关键字声明count变量在上一级作用域中;

  左边代码可以正常使用,且形成闭包,右边代码不能正常运行,变量a不能在全局作用域中;

默认值的作用域

  

  为什么第二次调用foo函数打印的是[1,1]?因为函数也是对象,python把函数的默认值放在了属性中,这个属性就是是伴随着这个函数对象的整个生命周期;如果print(xyz) #NameError,当前作用域没有xyz变量;

  

  如上图所示,函数的地址并没有变,就是说函数这个对象没有变,调用它,它的属性__defaults__中使用元组保存所有默认值;xyz默认值是引用类型,引用类型的元素变动,并不是元组的变化;

非引用类型例子

  

  如上图所示:属性__defaults__中使用元组保存所有默认值,它不会因为在函数体内使用了它而发生改变;

可变类型默认值,如果使用默认值,就可能修改这个默认值;

  方法一:使用影子拷贝创建一个新的对象,永远不能改变传入的参数;

  

  如上图所示:函数体内,不改变默认值;xyz都是传入参数或者默认参数的副本,如果就想修改原参数,无能为力;

  方法二:通过值的判断就可以灵活的选择创建或者修改传入对象,这种方式灵活应用广泛,很多函数的定义,都可以看到使用None这个不可变的值作为默认参数,可以说这是一种惯用法;

  

  如上图所示:使用不可变类型默认值,如果使用缺省值None就创建一个列表,如果传入一个列表,就修改这个列表;

第九天python3 闭包、nonlocal、默认值的作用域的更多相关文章

  1. ES6函数参数默认值作用域的模拟原理实现与个人的一些推测

    一.函数参数默认值中模糊的独立作用域 我在ES6入门学习函数拓展这一篇博客中有记录,当函数的参数使用默认值时,参数会在初始化过程中产生一个独立的作用域,初始化完成作用域会消失:如果不使用参数默认值,不 ...

  2. Python入门篇-返回值和作用域

    Python入门篇-返回值和作用域 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.返回值 1>.返回值概述 Python函数使用return语句返回“返回值” 所有函数都 ...

  3. Python函数的返回值和作用域

    函数的返回值和作用域 1.返回值 def guess(x):    if x > 3:        return "> 3"    else:        retu ...

  4. swift学习笔记(六)析关闭过程和使用分配给属性的默认值

    一.通过关闭和功能的默认实现财产值 当存储属性默认值需要定制,能为客户提供通过关闭或全局函数的自定义默认值. 注意:全局函数的结构,和枚举使用keywordstatic大喊    用classkeyw ...

  5. es6(三):es6中函数的扩展(参数默认值、rest参数、箭头函数)

    1.函数可以设置参数默认值 function test1(x,y=1){ console.log(x,y) } test1(10)//10 1 2.rest参数:形式为...变量名 function ...

  6. ES6 学习笔记之三 函数参数默认值

    定义函数时为参数指定默认值的能力,是现代动态编程语言的标配.在ES6出现之前,JavaScript是没有这种能力的,框架为了实现参数默认值,用了很多技巧. ES6 的默认参数值功能,与其他语言的语法类 ...

  7. JS中给函数参数添加默认值

    最近在Codewars上面看到一道很好的题目,要求用JS写一个函数defaultArguments,用来给指定的函数的某些参数添加默认值.举例来说就是: // foo函数有一个参数,名为x var f ...

  8. ES6笔记之参数默认值(译)

    原文链接:http://dmitrysoshnikov.com/ 原文作者:Dmitry Soshnikov 译者做了少量补充.这样的的文字是译者加的,可以选择忽略. 作者微博:@Bosn 在这个简短 ...

  9. JS中给函数参数添加默认值(多看课程)

    JS中给函数参数添加默认值(多看课程) 一.总结 一句话总结:咋函数里面是可以很方便的获取调用函数的参数的,做个判断就好,应该有简便方法,看课程. 二.JS中给函数参数添加默认值 最近在Codewar ...

随机推荐

  1. DOM0级同DOM2级

    DOM0级分为两个:一是写在标签内的onclick事件: <button id="btn" onclick="alert('happy')">按钮& ...

  2. xrdp出现xrdp vnc error problem connecting解决办法

    # generate a file called .xsession in your home directory, and set default desktop echo "xfce4- ...

  3. Docker中Nginx,部署Tomcat,部署es + kibana,Docker的可视化,Commit镜像

    docker安装使用Nginx # 搜索信息 docker search nginx # 下载镜像 docker pull nginx # 运行测试 # --name给容器命名 # -p 宿主机端口: ...

  4. WPF 制作雷达扫描图

    实现一个雷达扫描图. 源代码在TK_King/雷达 (gitee.com),自行下载就好了 制作思路 绘制圆形(或者称之轮) 绘制分割线 绘制扫描范围 添加扫描点 具体实现 首先我们使用自定义的控件. ...

  5. GIL与普通互斥锁区别,死锁现象,信号量,event事件,进程池与线程池,协程

    GIL与普通互斥锁区别 GIL锁和互斥锁的异同点 相同: 都是为了解决解释器中多个线程资源竞争的问题 异: 1.互斥锁是Python代码层面的锁,解决Python程序中多线程共享资源的问题(线程数据共 ...

  6. VMware-workstation 安装步骤

    目录 VMware Workstation简介 软件获取 百度网盘获取 VM激活码: 安装步骤: VMware Workstation简介 VMware Workstation(中文名"威睿 ...

  7. JavaScript 任务池

    JavaScript 任务池 本文写于 2022 年 5 月 13 日 线程池 在多线程语言中,我们通常不会随意的在需要启动线程的时候去启动,而是会选择创建一个线程池. 所谓线程池,本意其实就是(不止 ...

  8. 143_Power BI&Power Pivot月度、季度、半年度、全年同维度展示

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 最近在做下一年度的预算,做出来需要月度.季度.半年度.全年都展示出来,在做测算的是时候,默认的透视表已经无法满足 ...

  9. 对比不同版本windows对libreoffice的支持情况

    由于最近需要用到libreoffice进行对文档转换为pdf,不光需要考虑在linux下的表现,还需要对比下Windows下的兼容性. 在网上各个论坛都找了下,以及libreoffice的中文社区发帖 ...

  10. 【Unity Shader学习笔记】Unity光照基础-半兰伯特光照

    在光照无法达到的区域,模型的外观通常是全黑的,没有任何明暗变化,这会使模型的背光区域看起来就像一个平面. 使用半兰伯特光照可以解决这个问题. 逐顶点光照技术也被称为兰伯特光照模型.因为它符合兰伯特定律 ...