Python 名称空间以及函数的补充

名称空间

名称空间就是存放变量名与变量值关系的地方

其可以分为三个种类为
	内置名称空间    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()

在局部嵌套中修改和在局部中修改是一样的,输出的结果分别为 21
而在这种情况要想修改上一个局部空间的变量要用到关键字 nonlocaldef 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() 互相调用了对方函数,这样会报错,就像一个死循环一样。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值