函数进阶

一、名称空间

1、什么是名称空间

名称到对象的映射。命名空间是一个字典的实现,键为变量名,值是变量对应的值,各个命名空间是独立没有关系的,一个命名空间中不能有重名,但是不同的命名空间可以重名而没有任何影响

通俗讲:名称空间就是存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢,名称空间正是存放名字x与1绑定关系的地方)

2、名称空间分类

全局名称空间(global):每个模块加载执行时创建的,记录了模块中定义的变量,包括模块中定义的函数、类、其他导入的模块,模块级的变量与常量

局部命名空间(local):每个函数所拥有的命名空间,记录了函数中定义的所有变量,包括函数的入参、内部定义的局部变量

内置命名空间(built-in):任何模块均可以访问,放着内置的函数和异常(比如:input,print,str,list,tuple)

3、名称空间的加载顺序

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

4、名称空间的取值顺序

在局部调用:局部命名空间-->全局命名空间-->内置命名空间

在全局调用:全局命名空间-->内置命名空间

综上所述,在寻找变量时,从小范围,一层一层到大范围去找寻

二、作用域

1、什么是作用域

作用域是针对变量而言,指申明的变量在程序里的可应用范围,或者称为变量的可见性

2、作用域分类

按照生效范围可以分为全局作用域和局部作用域

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

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

3、查看作用域的值

locals()和globals(),他们提供了基于字典的访问局部和全局变量的方式

locals():函数会以字典类型返回当前位置的全部局部变量

globals():函数会以字典类型返回当前位置的全部全局变量

4、关键字(global与nonlocal)

global的作用:

  声明一个全局变量

  在局部作用域想要对全局作用域的全局变量进行修改时,需要用到global(限于字符串,数字)

def func():
    global a
    a=2
    print(a)

func()
print(a)
"""
2
2
"""

注意:对可变数据类型(list,dict,set)可以直接引用,不用通过global

li=[1,2,3]
dic={'a':'b'}
def change():
    li.append('a')
    dic['q']='g'
    print(dic)
    print(li)
change()
print(li)
print(dic)
"""
{'a': 'b', 'q': 'g'}
[1, 2, 3, 'a']
[1, 2, 3, 'a']
{'a': 'b', 'q': 'g'}
"""

nonlocal的作用

  不能修改全局变量

  在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从哪层及以下此变量全部发生改变

def add_b():
    b=42
    def do_global():
        b=10
        print(b)
        def dd_nonlocal():
            nonlocal b
            b+=20
            print(b)
        dd_nonlocal()
        print(b)
    do_global()
    print(b)

add_b()
"""
10
30
30
42
"""

三、函数名的本质

函数名本质上就是函数的内存地址

1、可以被当做值或变量引用

def func():
    pass
print(func)
f=func  #将其传给变量f
print(f)
"""
<function func at 0x00000000005C3E18>
<function func at 0x00000000005C3E18>
"""

2、函数可以被当做容器类型的元素存储

def func1():
    print('func1')
def func2():
    print('func2')
def func3():
    print('func3')
lis=[func1,func2,func3]
lis[0]()
lis[1]()
lis[2]()
"""
func1
func2
func3
"""

3、可以当做函数的参数和返回值

def func1():
    print('func1')
def func(argv):
    argv()
    return argv #func1作为返回值

f=func(func1) #func1作为参数 f() """ func1 func1 """

四、闭包

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包(即:内层函数,对外层函数(非全局)的变量的引用)

example(例子):

def func():
    name='eva'
    def inner():
        print(name)
    return inner

f=func()
f() #eva

1、检测闭包函数的公共属性:closure

如果里层的函数调用__closure__方法输出是一个cell对象,则证明是闭包

def wrapper():
    name='是闭包'
    def inner():
        print(name)#调用外层函数的变量
    inner()
    print(inner.__closure__)
wrapper()
"""
是闭包
(<cell at 0x0000000001C40C48: str object at 0x00000000028657B0>,)
"""

2、带有参数的闭包函数

def wrapper(a):#a是外部传入的参数
    b=10
    def inner(a):
        print(a+b)
        return a+b
    inner(a)
wrapper(10)#20
原文地址:https://www.cnblogs.com/z-x-y/p/9177617.html