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

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

原文地址:https://www.cnblogs.com/hongyu0518/p/9753845.html