洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

时间:2022-08-29 12:19:38

前面你看到嵌套两层的函数,也许你有感而发,想来点刺激的对不?那么如果每层内的变量名如果相同会怎样?拿个例子看下就知道:

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

报错了,报错信息大意是,本地变量‘num’引用前没有被赋值定义。这咋回事,我外层不是定义了吗?这个问题就涉及到今天要说的话题——函数作用域

函数作用域

1.作用域分三个:本地作用域(local),函数内作用域(enclosing),全局作用域(global)

2.三个作用域的优先级规则是这样:L>E>G>B

这里的B是什么呢?是Built-in,眼熟不,好像在哪里用过对吧?我们查看内置函数的命令是什么?dir(__builtins__)对吧?对了,就是这个,这个是内置作用域,知道就行,一般不会拿出来与前面三个作用域做比较

3.包含关系:

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

4.函数定义了本地作用域,模块定义了全局作用域:

1):每个模块都是一个全局作用域,所以全局作用域的范围是单个程序文件

2):每次对函数的调用都会创建一个新的本地作用域,赋值的变量除非声明为全局变量,否则均为本地变量

3):所有的变量名都可以归纳为本地,全局或内置(由__builtin__模块提供)

4):任何的函数在调用结束后,其内的变量都是消失

5.因为有了三个作用域,则会产生全局变量,局部变量

1)全局变量:指除了函数内的外层变量

2)局部变量:指函数内部的变量

6.局部变量和全局变量互不影响,即使变量名相同也如此。

看完以上的概念,上面的例子为何出错应该很好理解了。

在函数内修改外部的全局变量是不可行的,因为python会自动屏蔽掉,但函数内部都可以访问全局变量。

怎么屏蔽的呢?在函数内部创建一个与全局变量相同的局部变量来屏蔽,当你调用时因为优先级关系会自动的调用函数内部的那个变量,而外层的同名变量则永远也不会被调用

例:

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

结果显而易见,num并没有被改掉,这就是屏蔽的效果。num=100这个变量为全局变量,而函数temp内的num=50是局部变量。

那么我确实想改呢?方法是有的,加入一个global参数即可,例:

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

注意:global关键词不能写成  【global num=50 】,必须分开写,不然报错

改了对吧?但其实你有没有发现,其实是局部变量把全局变量改了,调用函数后,全局变量就变了

那假如我不给global是什么结果:

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

由此可以看出,在python中,函数内调用函数外的变量是可以的,当内部没有此变量时,会自动由优先级高到低一一审查,如果这个变量事先确实没有定义,才抛出一个错误【此变量没有被定义】。同时,我还要补充一点的是,代码运行方式是由上而下的,由上面两个例子可以看出。

那么你也许会想,因为上面的例子是局部变量改全局变量,我能不能全局变量改函数内的局部变量呢?这个问题留着,自己下去测试体会

那么既然有global,有没有和global类似的另一个关键词呢?有的——nonlocal,这里暂且不说,下面在合适的地方提到

7.内嵌函数:内嵌函数前面其实也提到了一点,就是函数内再嵌套一层或者多层函数,这种就叫内嵌函数

例:

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

注意:

1).在最后必须加入inn()这段代码,这才是调用inn函数的命令

2).调用函数只能调用外层函数,不能直接调用内层函数,不然报错,因为内部函数整作用域都在外部函数之内

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

3).inn()的调用并且是在out函数层内加入,而非在inn函数层加,如果不加入,则:

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

再看一个例子:

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包

这里例子也很经典,符号‘.’是类的方法的调用【类在后面会讲到】,而此时是函数,函数的调用时是使用符号‘()’,所以以上代码就好解释了

注意,由于前面说的【任何函数调用结束时,其内的变量消失】,但此时的a1是对f1的调用,f1调用完变量就消失,而此时的a1调用时变量还在,因为在函数嵌套时,还有一层函数,所以并没有消失。

所以,总结:如果调用函数是直接返回内层函数(比如这里的a1函数调用),内层会自动记忆外层函数变量,这种行为就是函数的闭包(也叫闭合),也就是所谓的工厂函数

下一篇博文详细介绍闭包问题

洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包的更多相关文章

  1. Python开发——函数【装饰器、高阶函数、函数嵌套、闭包】

    装饰器 装饰器本质就是函数,为其他函数添加附加功能. 原则: 不修改被修饰函数的源代码 不修改被修饰函数的调用方法 装饰器知识储备:装饰器 = 高阶函数 + 函数嵌套 + 闭包 案例:求函数运行时间! ...

  2. 洗礼灵魂,修炼python(20)--自定义函数(1)—基础概念

    作为开发,那么我们前面学的那些知识其实够了,但是不够精简,也不好维护,比如需要打印斐波那契数列: 而当我们需要再次打印斐波那契数列,又要把这段代码加上,是不是很烦,有没有方法可以解决,当然可以,那就是 ...

  3. 洗礼灵魂,修炼python(24)--自定义函数(5)—匿名函数lambda

    在这个互联网时代,大家都喜欢匿名,匿名上网,匿名登录,匿名操作等等,都不喜欢实名对吧?(虽然说现在实名制已经快到来,题外话,扯远了),当然python里也有个不喜欢实名的,它的功效优点特殊,说强大吧? ...

  4. 洗礼灵魂,修炼python(5)--python操作符,内置函数

    前面提到了BIF(内置函数)这个概念,什么是内置函数,就是python已经定义好的函数,不需要人为再自己定义,直接拿来就可以用的函数,那么都有哪些BIF呢? 可以在交互式界面(IDLE)输入这段代码, ...

  5. 洗礼灵魂,修炼python(85)-- 知识拾遗篇 —— 深度剖析让人幽怨的编码

    编码 这篇博文的主题是,编码问题,老生常谈的问题了对吧?从我这一套的文章来看,前面已经提到好多次编码问题了,的确这个确实很重要,这可是难道了很多能人异士的,当你以为你学懂了,在研究爬虫时你发现你错了, ...

  6. 洗礼灵魂,修炼python(69)--爬虫篇—番外篇之feedparser模块

    feedparser模块 1.简介 feedparser是一个Python的Feed解析库,可以处理RSS ,CDF,Atom .使用它我们可从任何 RSS 或 Atom 订阅源得到标题.链接和文章的 ...

  7. 洗礼灵魂,修炼python(40)--面向对象编程(10)—定制魔法方法+time模块

    定制魔法方法 1.什么是定制魔法方法 首先定制是什么意思呢?其实就是自定义了,根据我们想要的要求来自定义.而在python中,其实那些所谓的内置函数,内置方法,内置属性之类的其实也是自定义出来的,不过 ...

  8. 洗礼灵魂,修炼python(6)--活起来的代码+列表

    活起来的用法: 使用input内置函数 注意python2中和python3中,input函数是不太一样的,python2中,input用户传入什么类型就是什么类型而python3中,不管传入什么类型 ...

  9. 洗礼灵魂,修炼python(29)--装饰器(1)—>利用经典案例解析装饰器概念

    前提必备 不急着进入正题,在前面函数作用域那一章介绍了闭包,全局变量局部变量,这里再看几个简单的闭包案例: 1):不带参数 注意: 1.这里的name属性是每个函数都有的,可以反馈函数名 2.temp ...

随机推荐

  1. jQuery 点击显示再次点击隐藏

    <html> <head> <script type="text/javascript" src="/jquery/jquery.js&qu ...

  2. Android WebView常见问题及解决方案汇总

    Android WebView常见问题解决方案汇总: 就目前而言,如何应对版本的频繁更新呢,又如何灵活多变地展示我们的界面呢,这又涉及到了web app与native app之间孰优孰劣的争论. 于是 ...

  3. 晒自己做的一个管理系统(清新风格)EasyUI

    最近项目结束了,现在也要自己总结一下自己的成果了,总结会加深自己对项目的印象的.这里我就先晒一些作品图片了,希望大家看了会赞美一个! 项目虽然结束了,但是接下来的这个项目可就不是我一个人可以搞定的了, ...

  4. VS2015操作Oracle数据需要做那些设置?

    1>在oracle网上下载:ODP.NET 2> 要根据自己的oracle 数据32bit/64bit,选择下载. 3> 根据提示配置tnsnames.ora文件. # alias ...

  5. ArcGIS网络分析之Silverlight客户端最近设施点分析&lpar;四&rpar;

    原文:ArcGIS网络分析之Silverlight客户端最近设施点分析(四) 在上一篇中说了如何实现最近路径分析,本篇将讨论如何实现最近设施点分析. 最近设施点分析实际上和路径分析有些相识,实现的过程 ...

  6. css伪类的组合用法

    利用伪类组合,可以用css代替js以达到目的,少些一下js .textarea:empty:before { display: block; content: '请输入'; color: #ababa ...

  7. Vue学习笔记六:v-model 数据双向绑定

    目录 v-model简介和适用范围 新建HTML 所见即所得 v-model模拟简易计算器 v-model简介和适用范围 Vue的一大特点之一就是数据的双向绑定,v-model就是实现这个功能的指令, ...

  8. leetcode — flatten-binary-tree-to-linked-list

    import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Source : https://o ...

  9. 16款优秀的Vue UI组件库推荐

    16款优秀的Vue UI组件库推荐 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可.在公司的Web前端项目开发中,多个项目采用基 ...

  10. Oracle RAC管理及维护命令详解

    Oracle Clusterware的命令集可以分为以下4种: 节点层:osnodes 网络层:oifcfg 集群层:crsctl, ocrcheck,ocrdump,ocrconfig 应用层:sr ...