函数篇:名称空间、名字查找顺序、作用域、函数对象、嵌套

2022.3.17学习笔记

qCdd4H.jpg

  • 名称空间
  • 名称的查找顺序
  • 作用域
  • 函数对象
  • 函数嵌套

一、名称空间

概念:其实就是存放变量名与变量值绑定关系得地方,可以理解为‘民政局’

1、内置名称空间

python解释器提前给我们定义好的如:

len()
print()
open()
...

存活周期:

python解释器运行---产生

python解释器关闭---销毁

2、全局名称空间

在py文件中编写的代码产生的名字都会存放到全局名称空间,如:

name = 'jason'  # 变量名name存入全局名称空间
def index():  # 变量名index存入全局名称空间
    pass
if True:  
    a = 1  # 变量名a存入全局名称空间
while True:
    b = 2  # 变量名b存入全局名称空间
    print(b)
...

存活周期:

py文件开始运行---产生

py文件运行结束---销毁

3、局部名称空间

函数体代码运行产生的变量名都存在局部名称空间,如:

def index():
    x = 1  # x存入局部名称空间

存活周期:

函数体代码开始运行---产生

函数体代码运行结束---销毁

二、名字的查找顺序

​ 我们知道名称空间是用来存放名字与值绑定关系的地方,那么要查找一个名字,要现在什么名称空间寻找呢,有没有先后顺序?

​ 首先我们需要知道需要查找的名字目前在什么空间!

1、若在局部名称空间

查找顺序:局部名称空间>>>全局名称空间>>>内置名称空间

2、若在全程名称空间

查找顺序:全局名称空间>>>内置名称空间

那么问题来了,如果在三个名称空间都有相同的名字那么会怎么样呢?举个例子:

len = '全局空间的len'
def index():
    len = '局部空间的len'
    print(len)  # 局部空间的len
index()
print(len)  # 全局空间的len

所以还是按照我们查找名字的顺序,先看是在什么空间查找,就优先在什么空间查找。

这里还有一个例子值得推敲,注意看,这时候运行函数,结果如何

qCllUx.jpg

其实是f1调用f2调用f3调用f4,在f4的局部空间中有x,那么直接打印结果为:555

那么如果print(x)和x = 555 调换位置呢,结果是报错,为什么呢,看图:

qC1EdI.jpg

三、作用域

概念:就是名称空间能够作用的范围

内置名称空间:任意阶段均可使用(全局有效)

全局名称空间:任意阶段均可使用(全局有效)

局部名称空间:一般只在局部名称空间有效(局部有效)

注意:后面可以用一些手段打破规则

1、global x

在局部修改全局的数据,表示声明要修改全局的不可变类型数据,可变类型不需要加global关键字

x = 111
def index():
    x = 222  # 相当于在局部名称空间中新建了一个x = 222
那么怎么在局部修改全局的值呢,需要用到glabal关键字
    global x  # 这样接下来就可以修改全局的x了
    x = 222

2、nonlocal x

在局部修改上一层局部的变量值,表示要修改该局部名称空间的上一层局部名称空间的数据,同样是针对不可变类型

def func():
    x = 111
    def index():
        x = 222  # 这里也是相当于新建了一个x = 222,只在index下的局部空间有效
这里就需要用到nonlocal关键字了
		nonlocal x
    	x = 222  # 这样就可以修改外层函数的值了

四、函数名对象(函数名的多种用法)

1、函数名当作变量名赋值

def index():
    print('from function index')
res = index  # 将函数名index赋值给res
print(res)  # 结果为函数名index指向的内存空间
res()  # 赋值后的变量名res也可以通过()调用index函数

2、函数名当作函数的实参

def index():  # 定义一个index函数
    print('from index')
def func(a):  # 定义一个有参函数func
    print('from func')
    print(a)
    a()  # a等待接收一个函数名实参,用以调用
func(index)  # 将上面index函数名作为实参传入func函数

这样的话函数index和func就形成一个联动效应,联合使用

3、函数名当作函数的返回值

def func():
    print('我是func的函数体代码')
    return index
def index():
    print('我是index的函数体代码')
res = func()  # 用res接收func函数的返回值index
print(res)  # 结果是:
                 '''我是func的函数体代码
                    函数名index的内存空间地址'''

4、函数名当作容器类型的元素

def func():
    print('我是func的函数体代码')
l = [1, 2, 3, 4, 5, func]
print(l)  # [1, 2, 3, 4, 5, <function func at 0x000001FF954860D0>]  可见打印出来的是func的内存地址
l[-1]()  # 通过索引取值得到函数func,也可以直接加括号调用函数

五、函数的嵌套

1、嵌套调用

def index():
    print('123')  # 第二步
def func():
    index()  # 第一步
    print('321')  # 第三步
func()  # 123  321  

2、函数定义

可以通过函数套函数的方式来代替之前的多层循环嵌套,如:

def all_func(arg):
    def register():
        print('注册功能')
    def login():
        print('登录功能')
    def delete():
        print('删除功能')
    if arg == '1':
        register()
    elif arg == '2':
        login()
    elif arg == '3':
        delete()
    else:
        print('指令错误')
while True:
    choice = input('输入指令>>>:')
    all_func(choice)

这样我们的思路就会非常清晰,不是吗?

加油!

qCd52n.md.jpg

posted @ 2022-03-17 16:37  马氵寿  阅读(148)  评论(0)    收藏  举报