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


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

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

    函数作用域

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

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

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

    3.包含关系:

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

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

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

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

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

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

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

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

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

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

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

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

    例:

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

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

     

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

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

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

     

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

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

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

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

    例:

    注意:

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

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

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

    再看一个例子:

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

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

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

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

  • 相关阅读:
    ASP.NET动态加载用户控件的页面生成过程
    简单的flash与asp.net通信(LoadVars类)
    转 推荐两本FLASH RIA应用开发方面的书籍
    关于代码加密解密保护
    转 利用 SharpZipLib方便地压缩和解压缩文件
    在C#中应用哈希表(Hashtable)
    C#中解析并运行一个本地命令行
    About Windows Live Writer
    安装sql server 2008,提示要删除SQL Server 2005 Express 工具,可我根本没装
    [转] C#中的null
  • 原文地址:https://www.cnblogs.com/Eeyhan/p/7644623.html
Copyright © 2020-2023  润新知