zoukankan      html  css  js  c++  java
  • Python函数2

    一、命名空间:

    什么是命名空间:

      --> Python代码在执行的过程中从上到下顺序执行,

      --> 从python解释器开始执行之后,就在内存中开辟了一个空间。

      --> 每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。

      --> 但是,当遇到函数的时候,Python解释器只是将函数名称读入内存,并且知道这个函数已经存在了,此时,函数内部的变量和逻辑关系解释器根本就不关心,并没有执行函数内部的代码

      --> 等到执行函数的调用的时候,Python解释器才会在内存中再开辟一块儿空间,来存储函数里面的代码内容,这个时候,才会关注函数内部有哪些变量。函数内部的变量存储在新开辟的空间中,只能供函数内部使用,等函数执行完毕,这块儿内存空间中所有内容都会被清空。

      --> 我们给这个“存放名字与值的关系”的空间起了一个名字——叫做命名空间

    命名空间分为三种:全局命名空间,局部命名空间,内置命名空间。

    1.首先先说下内置命名空间:里面包含了Python解释器为我们提供的一些名字。比如:input,print,list,tuple等等。我们直接拿过来用就可以。

    2.全局命名空间:代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间。

    3.局部命名空间:在函数的运行中开辟的临时的空间叫做局部命名空间。

    命名空间的加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

    关于作用域:作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

      全局作用域:包含内置命名空间和全局作用空间,在整个文件的任意位置都能被引用、全局有效

      局部作用域:局部名称空间,只能在局部范围内使用

    关于global关键字

    来看一段代码:

    a = 1
    def func():
        a = 20
    print(a)
    func()
    print(a)

    上面的代码打印结果

    1
    1

    第一个 print(a)在调用函数之前打印 a 的值,打印 1 ,后面调用函数,在函数内部,明明已经修改了 a的值,后面打印 还是打印 1 。其实,第一个  a = 1.这个a 是全局命名空间。在函数内部 a = 20 ,这个a是局部命名空间,如果想在函数内部,对全局变量的值做修改,可以使用关键字 global

    a = 1
    
    def func():
        global a
        a = 20
    
    print(a)
    func()
    print(a)

    这次的打印结果

    1
    20

    二、关于函数的探讨

    先看一段代码:

    def func(): # 定义一个函数
        pass
    
    f = func # 将函数名称赋值给一个变量
    
    print(func) # 打印函数名称
    print(f) # 打印变量 f

    执行结果

    <function func at 0x000000000050C1E0> # 翻译结果:0x000000000050c1e0处的函数func
    <function func at 0x000000000050C1E0>

    从结果中可以看出:函数名称实际上存放的是这个函数的一个内存地址,另外,函数名也可以赋值给一个变量,其实函数名也是一个变量

    既然函数名本质上其实就是一个变量,那么,函数名也就可以作为容器中的一个元素。如:

    def func1():
        pass
    
    def func2():
        pass
    
    def func3():
        pass
    
    list_func = [func1,func2,func3]
    for l_func in list_func:
        print(l_func)

    打印结果

    <function func1 at 0x00000000003DC1E0>
    <function func2 at 0x0000000002718510>
    <function func3 at 0x0000000002718598>

    也可以当做函数的参数以及返回值

    def outer():
        name = 'jack'
        def inner():
            print(name)
        return inner
    
    outer()

    三、闭包:内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数

    来看一段代码

    def outer(x):
        def inner(y):
            return x + y
        print(inner.__closure__)  # 使用__closure__ 判断是否为闭包,如果输出包含cell 则是闭包。如果输出为None 则不是闭包
        return inner
    
    f = outer(9)
    print(type(f)) # 打印f的类型
    print(f.__name__) # 输出 f 的名字

    输出结果

    (<cell at 0x00000000021DB858: int object at 0x000007FEDFC5D520>,)
    <class 'function'>
    inner

    结合这段简单的代码和定义来说明闭包:
    如果在一个内部函数里:inner(y)就是这个内部函数,对外部作用域(但不是在全局作用域)的变量进行引用:x就是被引用的变量(x在外部作用域outer里面,但是不是全局作用域),name这个内部函数就是一个闭包

    使用闭包的注意事项:

    在闭包中,是不能修改外部作用域的变量的值

    def outer():
        a = 0
        def inner():
            a = 1
            print(a)
        print(a)
        inner()
        return inner
    
    outer()

    打印结果

    0
    1

    另外需要注意的一点是:闭包不要引用任何的循环变量,或者后续会发生变化的变量

  • 相关阅读:
    UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
    蓝桥杯 修改数组 (巧用并查集)
    luoguP3242 [HNOI2015]接水果
    CF757F Team Rocket Rises Again
    luoguP2597 [ZJOI2012]灾难
    luoguP4103 [HEOI2014]大工程
    luoguP3233 [HNOI2014]世界树
    luoguP2495 [SDOI2011]消耗战
    CF613D Kingdom and its Cities
    51nod 1584 加权约数和
  • 原文地址:https://www.cnblogs.com/hongyu0518/p/9753845.html
Copyright © 2011-2022 走看看