文章目录
名称空间
名称空间就是存放变量名与变量值关系的地方
其可以分为三个种类为
内置名称空间 python解释器已经定义好的
全局名称空间 在py文件中编写的代码运行产生的名字都会存到全局名称空间
局部名称空间 '函数体'代码运行产生的都是局部名称空间
1. 内置名称空间
len() print() open() 这些都被存放在内置名称空间
内置名称空间在python解释器运行时产生,解释器停止时销毁
2. 全局名称空间
name = 'XWenXiang'
def index():
pass
if True:
a = 1
for i in range(10):
pass
while True:
b = 2
上述代码的变量 name,index,a,i,b 都被存放在全局名称空间
全局名称空间在py文件运行时产生,结束运行时销毁
3. 局部名称空间
def index():
name = 'XWenXiang'
''此时函数并没有调用,也就是函数体代码没有运行,所以并没有被存放在名称空间''
index()
name变量名在函数被调用之后,被存放在局部名称空间
名字的查找顺序
名称能被储存在名称空间,也能被查找使用,查找的顺序和当前所在的位置有关。
1. 在局部空间里面查找
len = '我是全局名称空间中的len'
def index():
len = '我是局部名称空间中的len'
print(len)
index() # 调用函数 函数体就会执行 就会产生局部名称空间
print(len)
按照上面的代码会打印哪个空间的内容呢?
(1) 首先我们知道len()函数是python已经定义好的,也就是len变量已经存放在内置名称空间里,而我们现
在也命名了一个叫len的变量存放在全局名称空间中,还有在函数中也创建了一个len变量存放在局部名称空
间里。
(2) 然后调用函数index()产生局部名称空间。
(3) 此时在局部名称空间里面打印len , 输出的结果是, 我是局部名称空间中的len,也就是局部名称空间
里面的len
(4) 在三个名称空间里都有len,且此时在局部名称空间里面的时候,会先寻找到局部名称空间里面的变量名
然后在去全局里面查找,最后在去内置空间里面寻找,如果三个空间都没有找到,会报错。
2. 在全局名称空间里查找
len = '我是全局名称空间中的len'
def index():
len = '我是局部名称空间中的len'
index() # 调用函数 函数体就会执行 就会产生局部名称空间
print(len)
代码和第一种类似,只不过打印的位置在全局名称空间里
(1)此时的输出结果是,我是全局名称空间中的len,也就是在全局名称空间里面的变量len。
(2)我们把第一行代码注销掉的话,会输出 <built-in function len> ,也就是内置名称空间里的len 。
(3)此时是查找不到局部空间里面的变量名的,也就是说在全局名称空间里面时,会先在全局名称空间里面找
,然后再去内置空间查找,找不到程序会报错
3. 局部空间中查找局部空间
x = 1
"""如果函数没有被调用 那么不要去管函数体代码有多复杂 先跳过"""
def f1():
x = 2
def f2():
x = 3
def f3():
x = 4
print(x)
f3()
f2()
f1()
上面的代码类型是函数的嵌套。
(1) 首先我们在全局中定义了x为1,并定义 f1 函数以及调用 f1 函数
(2) 在 f1 的局部名称空间定义了x为2,并定义 f2 函数以及调用 f2 函数
(3) 在 f2 的局部名称空间定义了x为3,并定义 f3 函数以及调用 f3 函数
(4) 在 f3 的局部名称空间定义了x为4,并打印x
(5) 输出的结果是4。
(6) 在局部中调用局部也是从里到外的查找
(7) 为什么在函数后都要调用子函数呢,如果不调用,函数就不执行也就没有局部名称空间产生。
(8) 在函数 f3() 中,命名x=3在打印的后面的话,程序会报错,没有调用函数的时候,代码只检测语法,
而检测语法的时候发现 f3 的局部名称空间有可能有变量x,它就会问f3要,
4. 局部空间并列的情况
第三种是在局部空间互相嵌套的情况下发生的,如果局部空间并列的话,它们互不干涉
def index1():
name = 'jason'
def index2():
age = 18
print(name) # 报错
index1()
index2()
这种情况下程序会报错,因为它们互不干涉。
作用域
作用域就是名称空间能够作用的范围
分为
内置名称空间
程序任意阶段任意位置均可使用(全局有效)
全局名称空间
程序任意阶段任意位置均可使用(全局有效)
局部名称空间
一般情况下只在各自局部名称空间中有效(局部有效)
global与nonlocal关键字
当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal 关键字了
gloabl 关键字
1. 在局部中修改全局
当我们在局部空间定义一个和全局空间里一样的变量名时
x = 1
def index():
x = 2
print(x)
index()
print(x)
此时在函数 index() 中,定义了一个变量x为2,不是修改全局变量的x。
所以第一个打印的结果是 2 ,第二个打印的结果是 1 。
那我们怎么在局部中修改全局呢?就需要用到 gloabl 关键字了。
x = 1
def index():
global x
x = 2
print(x)
index()
print(x)
(1) 首先我们在局部空间中先用关键字 gloabl 来声明,表示是在修改全局中的x,而不是在定义局部的x。
(2) 修改全局x的值
(3) 此时的打印的俩个结果都是 2 ,说明全局的x已经被修改。
nonlocal 关键字
2. 局部嵌套的时候修改
def f1():
x = 1
def f2():
x = 2
print(x)
f2()
print(x)
f1()
在局部嵌套中修改和在局部中修改是一样的,输出的结果分别为 2, 1
而在这种情况要想修改上一个局部空间的变量要用到关键字 nonlocal 。
def f1():
x = 1
def f2():
nonlocal x
x = 2
print(x)
f2()
print(x)
f1()
(1) 和关键字 global 类似, nonlocal 用来声明此时是在修改上一个局部的变量,而不是定义一个新的
变量
(2) 此时输出结果都是 2 .
3. 例外
在局部中修改全局或者在局部中修改局部都有一个例外。
前面所讲的是修改的为不可变类型,也就是字符串,数字等等,而要想修改可变类型就不用关键字就可以直接
修改,下面以局部修改全局列表的情况做一个示例
list_a = [1, 2, 3]
def f1():
list_a.append(5)
print(list_a)
f1()
print(list_a)
(1) 若是修改的对象是可变类型列表,我们在局部中就可以直接用列表的内置方法来修改即可。
函数名的用法
函数名其实可以看做是一个变量,变量能做的它也能
1. 用函数名给变量赋值
1. 用函数名给变量赋值
def index():
print('XWenXiang 真帅')
index_a = index
index_a()
print(index_a)
(1) 首先创建了 index 函数
(2) 将 index 变量赋值给变量 index_a
(3) 调用、打印 index_a
(4) 结果分别为
XWenXiang 真帅
<function index at 0x000002AA666A3E20>
2. 函数名还可以当成函数的实参
2. 函数名还可以当成函数的实参
def index():
print('A')
def index_a(a):
print('B')
print(a)
a()
index_a(index)
(1) 首先创建函数 index 和 index_a
(2) 在函数 index_a 中定义形参,在函数体中打印形参以及执行 a()
(3) 调用函数 index_a 并将函数名 index 当作实参传入
(4) 打印的结果分别是
B
<function index at 0x0000023975943E20>
A
3. 函数名还可以当做函数的返回值
3. 函数名还可以当做函数的返回值
def index():
print('A')
return index_a # 将函数名当做返回值
def index_a():
print('B')
x = index()
print(x)
x()
(1) 定义了俩个函数 index index_a ,其中 index 设定返回值为 index_a ,且不会报错,因为现在
只是定义,只检测语法,不检测对错。
(2) 将函数 index() 的返回值赋予变量 x
(3) 打印 x 调用 x()
(4) 结果为
A
<function index_a at 0x0000026965EFA3B0>
B
(5) 此时的 x 就相当于了 index_a 所以调用 x() 会和 index_a 的函数体输出结果一样
4. 函数名可以作为列表的元素
4. 函数名可以作为容器类型的元素
'''容器类型:内部可以存档多个元素的数据类型>>>:列表、元组、字典'''
def index():
print('A')
list_a = [1, 2, 3, index, index()]
print(list_a)
(1) 定义一个函数 index ,并将其作为元素存储到列表里
(2) 输出列表,结果为
A
[1, 2, 3, <function index at 0x000001D1E3503E20>, None]
(3) 我们可以看到函数名的值为 <function index at 0x000001D1E3503E20>
(4) 至于后面的 None 是因为函数 index() 没有设置返回值
(5) 这种情况下也可以通过列表的方法取值,例如索引。
5. 函数名可以作为字典的元素
5. 函数名可以作为字典的元素,准确是作为字典的值,我们在做管理系统的时候会有很多的功能选择,普通
的方法就是用 if 判断每一种条件,如果将函数名作为值传入字典会简便许多。
def register():
print('注册功能')
def login():
print('登录功能')
def transfer():
print('转账功能')
def withdraw():
print('提现功能')
def check_order():
print('查看账单')
def shopping():
print('购物功能')
def check_account():
print('查看余额')
# 定义一个功能存放区
func_dict = {
'1':register,
'2':login,
'3':transfer,
'4':withdraw,
'5':check_order,
'6':shopping,
'7':check_account
}
while True:
print("""
1.注册功能
2.登录功能
3.转账功能
4.提现功能
5.查看账单
6.购物功能
7.查看余额
""")
choice = input('请输入您想要执行的功能编号>>>:').strip()
if choice in func_dict:
# 获取键对应的值(函数名)
func_name = func_dict.get(choice)
# 执行函数
func_name()
else:
print('功能编号不存在')
(1) 首先先定义功能函数
(2) 在定义字典,用于存放函数名,用字符串中写数字来表示键名,函数名来表示键值
(3) 定义一个循环体,先打印所有功能
(4) 收集用户输入的功能编号
(5) 判断输入的编号是否在字典里面,用成员变量 in 来判断字典的键名
(6) 如果在的话,定义一个变量,用get()方法得到此编号的值也就是键值,并赋值给变量。若不存在打印功
能编号不存在。
(7) 用之前定义的变量加括号的方式调用函数即可
函数的嵌套
函数的嵌套在前面也有写到,其实就是在函数中在加函数
代码示例1
def f1():
print(1)
def f2():
print(2)
def f3():
print(3)
f3()
f2()
f1()
代码示例2
def f1():
print(1)
f2()
def f2():
print(2)
f1()
1. 在代码示例2中,在函数 f1() 中调用了函数 f2() ,定义的时候不会错,因为还没执行,只检测语法,
若是将调用函数 f1() 放在定义函数 f2() 前面就会报错。
代码示例3
def f1():
print(1)
f2()
def f2():
print(2)
f1()
f1()
在代码示例3中,函数 f1() 和 f2() 互相调用了对方函数,这样会报错,就像一个死循环一样。