zoukankan      html  css  js  c++  java
  • python 笔记(名称空间、内置函数、闭包、装饰器)

    一.名称空间、作用域、取值顺序等。

      1.(1)名称空间:当程序开始运行时,代码自上而下开始依次执行,他会将变量与值的对应关系存储在一个空间中,这个空间就叫名称空间,命名空间,全局名称空间,当程序遇到函数时,他会将函数名存在内存中,函数体莫不关心。当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),函数外面访问不到临时空间的内容,随着函数的执行完毕,临时名称空间会释放掉,向这个临时开辟的空间叫临时名名称空间,也叫局部名称空间。

      (2)python 中名称空间分三种:
          内置名称空间。
          全局名称空间。
          局部名称空间。

      (3)作用域:全局作用域:
             内置名称空间。
             全局名称空间。
         (4)局部作用域
             局部名称空间。

         (5)加载顺序:
            内置名称空间 ---> 全局名称空间(当程序执行时) ---> 局部名称空间(当函数调用时)
         (6)取值顺序:单向不可逆
             局部名称空间(当函数调用时) -->全局名称空间(当程序执行时) -->内置名称空间

      (7).函数的嵌套操作:也就是说函数里面可以在定义多个函数嵌套起来使用,示例如下:

         

    二.内置函数

      1.内置函数的两个关键词:

      globals() 返回一个字典,字典里面的内容是全局作用域的内容。
      locals():返回一个字典,当前位置 的所有变量。

      代码示例如下:

      

      可以看到:无论在哪个位置,globals()打印出来的都是全局作用域的内容,而locals()就不一样,在函数里边,locals()打印的是函数里边的局部变量,而在函数外边则打印出来的是当前位置的全局变量。

      案例二代码:

      

      这里的答案就相当明显了:global()未打印出,因为当前没有全局变量,而locals打印出了当前位置的局部变量:name1和age1

    三.全局变量和局部变量的使用:

      这里先重复上一个概念:取值顺序:单向不可逆
         局部名称空间(当函数调用时) -->全局名称空间(当程序执行时) -->内置名称空间

      这里有两个关键词:global和nonlocal

       (1).global:引用并改变一个全局变量,在局部作用域声明一个全局变量:

      先看这样一个例子:

      

       

      这样看程序是报错的,而报错原因是因为在函数里边并没有定义count变量,count = 1只是定义的一个全局变量,在函数里边并不能调用的到,但如果我们想用呢?这里就用到了global这个关键字:

       

      这样,代码就能正常执行啦,global 的作用就是引用并改变一个全局变量,在局部作用域声明一个全局变量。

      当然也可以在局部变量里声明变量,让它当做全局变量来使用:

      

      (2)nonlocal:不能操作全局变量,从那层引用就从那层开始改变:

      

      取值:引用而不是改变
          取值是从小到大取值 LEGB
            想改变上层空间的变量 要用到global nonlocal

     (3).对于可变的数据类型,dict、list、set不能使用global/nonlocal参数。

      

      如果默认参数是一个可变的数据类型,那么他在内存中永远是一个

      

    四.函数名的应用。

      (1).打印函数名:

      

     (2).函数名可以作为容器类数据的元素:

      

      (3).函数名可以作为函数的参数传递进来:

      

      (4).函数名可以作为函数的返回值:

      

    五.闭包:

      (1).闭包:内层函数对外层函数非全局变量的引用,就叫做闭包

      

      这里的inner函数就是内层函数,调用的name变量就是对外层函数非全局变量的引用。

      这里有一个.__closure__方法就是判断是不是闭包,如果打印出cell之类的信息就是闭包,如下:

      

      如果 python 解释器遇到了闭包,他有一个机制,这个闭包不会随着函数的结束而释放。

    六.装饰器:

      (1).什么是装饰器,装饰器本质就是闭包,就是在不影响原函数功能的前提下,增加一些额外的功能,如打印日志,执行输出的一些功能,接下来一步步引入装饰器的概念:

      有这样的这一个需求:假设要测试一个函数的执行效率(即运行这个函数需要多长时间),我们首先想到的应该是这个样子:

       版1:

      

      这个时候你可能会发现这样程序不具有模块化,要将测试函数用函数封装起来更好一点:

      版2:

      

      这个时候又有问题了,假设有1000个测试函数,那我岂不是要写1000个timer函数,太冗余了,何不把测试函数当成一个参数传递进来呢,这就会更便捷一点:

      版3:将测试函数以参数的形式传递进来

      

      这个时候又有问题了,试想:我每测试一个函数就要按照这样的格式去写,那是不是就改变了我原有函数的执行方式了呢?这样不好,再次进行改版:

      版4:尽量不要改变原来函数的执行方式

      

      这样虽然大致满足了我的需求,但是调用的时候还是多传递了一个参数进来,这样不太好,有没有一种方法,不改变他的调用方式呢?继续改版

      版5:不改变原来函数的运行方式:

      

      这个时候就基本满足我们的要求啦,也没有改变原有函数的调用方式,但每次调用前我们总要先执行 fun = timer(fun)函数,太麻烦啦,python里边提供一个@符号也就是语法糖的概念代替这一句话:

      版6:引入语法糖:

      

      这样程序及基本算完事啦,还有一个问题,试想如果人家要测试的函数有参数怎么办?你总不能再次给人家开发一个timer吧,这里我们还需要加上参数

      版7:加入参数

      

      现在参数加进去了,但如果要有返回值该怎么办呢?简单,定义一个参数接收并返回就行了,继续改。。。

      版8:加入返回值:

      

      到这里就是一个完整的装饰器啦,既不需要改变原来函数的调用方式,也具有传递参数、返回值的功能!

      装饰器的格式:

      

      

  • 相关阅读:
    面向接口程序设计思想实践
    Block Chain Learning Notes
    ECMAScript 6.0
    Etcd Learning Notes
    Travis CI Build Continuous Integration
    Markdown Learning Notes
    SPRING MICROSERVICES IN ACTION
    Java Interview Questions Summary
    Node.js Learning Notes
    Apache Thrift Learning Notes
  • 原文地址:https://www.cnblogs.com/moranlei/p/9172547.html
Copyright © 2011-2022 走看看