函数小知识

名称空间

名称空间
其实就是存放变量名与变量值绑定关系的地方 类似于民政局、警察局...

名称空间的分类

 

1.内置名称空间
python解释器提前给我们定义好的
len() print() open()
2.全局名称空间

在py文件中编写的代码运行产生的名字都会存到全局名称空间
name = 'jason' # 变量名name存入全局名称空间


def index(): # 函数名index存入全局名称空间 pass

if True: a = 111 # 变量名a存入全局名称空间
for
i in range(10): # 变量名i存入全局名称空间 pass

while True: b = 222 # 变量名b存入全局名称空间

3.局部名称空间

函数体代码运行产生的都是局部名称空间
def index():
    name = 'jason' # name存入局部名称空间

存活周期

1.内置名称空间
python解释器运行 产生
python解释器关闭 销毁
2.全局名称空间
py文件开始运行 产生
py文件运行结束 销毁
3.局部名称空间
函数体代码开始运行 产生
函数体代码运行结束 销毁

 

 

名字的查找顺序

# 想办法让三个名称空间中都有相同的名字
len = '我是全局名称空间中的len'
def index():
    len = '我是局部名称空间中的len'
    print(len)
index()  # 调用函数 函数体就会执行 就会产生局部名称空间
print(len)    #结果:我是局部名称空间中的len


x = 111"""如果函数没有被调用 那么不要去管函数体代码有多复杂 先跳过"""
def f1():  ②
    x = 222def f2():  ⑤
        x = 333def f3():  ⑧
            print(x)  # 检测语法的时候 发现f3的局部名称空间将来会有x 所以查找的时候就跟f3的局部名称空间要(特例 可以忽略)   444,如果f3未来没有就返回333
            x = 444# print(x)  11    #444
        f3()  ⑨
    f2()  ⑥
f1()  ③

(咬死函数先定义后调用的顺序)
'''局部名称空间之间如果不是嵌套关系 那么互不干涉!!!'''
def index1():
    name = 'jason'
def index2():
    age = 18
    print(name)  # 报错
index1()
index2()

 

 在查找名字的时候 一定要先搞清楚自己在哪个空间

1.如果在局部名称空间
局部名称空间 >>> 全局名称空间 >>> 内置名称空间
2.如果在全局名称空间
全局名称空间 >>> 内置名称空间

总结:只能由范围小的向范围大的去找

作用域

 

 作用域就是名称空间能够作用的范围
①内置名称空间
程序任意阶段任意位置均可使用(全局有效)

②全局名称空间
程序任意阶段任意位置均可使用(全局有效)

③局部名称空间
一般情况下只在各自局部名称空间中有效(局部有效)
'''也可以通过一些手段打破规则'''

global与nonlocal关键字

'''gloabl关键字:局部修改全局不可变类型'''
x = 111
 def index():
     # x = 222  # 并不是在修改全局的x 而是在局部名称空间中创建了一个新的x
     # 如果想要在局部名称空间中修改全局名称空间中的名字 那么需要使用关键字申明
     global x     # 申明 修改的是全局x而不是产生新的x
     x = 666
 index()
 print(x)   #666(得到的就是同一个x)


l1 = [111, 222, 333]
def index():
    l1.append(444)
index()
print(l1)
"""
如果想要在局部修改全局的不可变类型
    需要提前加关键字global申明
如果想要在局部修改全局的可变类型
    不需要加关键字global申明
"""
'''nonlocal关键字:函数定义的嵌套,内层函数修改外层函数'''
def index():
    x = 111  # 在index的局部产生一个x=111
    def f1():
         x = 222  # 在f1的局部产生一个x=222 (两个x,一个111,一个222)
         print(x)  #打印内层局部的222
         局部名称空间嵌套 内层修改外层
         nonlocal x
         x = 333   #仅仅只是修改第一个外层函数的x值,由111变为333,不产生新的
        


def index():
    l1 = [11, 22, 33]
    def f1():
        l1.append(44)
    f1()
   print(l1)    #[11, 22, 33,44]
index()
"""
局部名称空间嵌套的情况下 内层如果想要修改外层
    情况1数据是不可变类型
        需要使用关键字nonlocal
    情况2数据是可变类型
        不需要使用关键字nonlocal
"""

函数名的多种用法

 

 def index():
     print('from function index')
 用法1:函数名可以当做变量名赋值
 print(index)   #打印index函数所在的位置代码
 res = index  # 让res也指向函数体代码
 print(res)  #打印的结果和上面一样 位置不变
 res()  #相当于 index()    结果为from function index

 用法2:函数名还可以当成函数的实参
 def index():
     print('from index')
 def func(a):
     print('from func')
     print(a)
     a()
 func(index)  #把index作为实际参数赋值给a   结果:首先index是index函数所在的位置代码
#依次为 from func ,index的位置代码,from index
                                                                  
 用法3:函数名还可以当做函数的返回值
 def func():
     print('from func')
     return index  # 将函数名当做返回值
 def index():
     print('from index')
 res = func()  # res接收函数名
 print(res)  # 相当于print(func())其实就是func()的return的值,为index,而index表示index函数的位置代码
 res()  # index()

 用法4:函数名可以作为容器类型的元素
'''容器类型:内部可以存档多个元素的数据类型>>>:列表、元组、字典'''
 def index():
     print('from index')
 l1 = [11, 22, 33, 44, index]  #这里index返回的是位置代码
 print(l1)  [11, 22, 33, 44, index函数的位置代码]
 l1[-1]()  #  index()

有了函数之后的简便
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
}
 choice = input('请输入您想要执行的功能编号>>>:').strip()
    if choice in func_dict:
        # 获取键对应的值(函数名)
        func_name = func_dict.get(choice)
        # 执行函数
        func_name()
    else:
        print('功能编号不存在')



之前没有函数时候的不方便,要写很多重复的elif
while True:
    print("""
    1.注册功能
    2.登录功能
    3.转账功能
    4.提现功能
    5.查看账单
    6.购物功能
    7.查看余额
    """)
   choice = input('请输入您想要执行的功能编号>>>:').strip()
     当功能比较多的是 频繁的编写elif很麻烦
    if choice == '1':
         register()
     elif choice == '2':
         login()
     elif choice == '3':
         transfer()
     elif choice == '4':
         withdraw()
     elif choice == '5':
         check_order()
     elif choice == '6':
         shopping()
     else:
         print('请输入正确的功能编号')

 

函数的嵌套

 函数的嵌套调用
 def index():
     func()
     print('from index')
 def func()
     index()
     print('from func')
 func()  #咬死函数先定义后调用,以上函数会一直报错,因为会在func()和index()两个函数之间反复横跳,但是没有结果
"""在学习函数的时候 前期一定要细心 死咬概念  定义调用"""


def my_max(a,b):
    '''返回两个数中的较大值'''
    if a > b:
        return a
    return b   #这里可以写else,也可以不写因为函数执行完return就结束,if里面如果不执行第一个return,就会执行外层的第二个
 print(my_max(100,999)) #999


def many_max(a,b,c,d):
    '''返回四个数中的最大值'''
    res = my_max(a,b)  # 两两先比
    res1 = my_max(res,c)  # ...
    res2 = my_max(res1,d)  # ...
    ...

 

函数的定义

# 函数的定义
def all_func(cmd):
    def register():
        print('注册功能')
    def login():
        print('登录功能')
    def transfer():
        print('转账功能')
    if cmd == '1':
        register()
    elif cmd == '2':
        login()
    elif cmd == '3':
        transfer()
    else:
        print('哈哈哈 偷懒了  没有用刚刚的功能字典')

all_func('1')
all_func('2')
"""
函数的学习会让我们的代码逻辑更加清晰 更加便于维护
总结:把很丑的东西给封装起来了,人们使用的时候更加简单,只会基本操作即可,不需要知道内部丑陋的东西

 

 

 

 

 

posted @ 2023-07-13 00:37  半糖+奶茶  阅读(18)  评论(0)    收藏  举报