函数名的用法,闭包函数与装饰器

函数的多种用法与装饰器

global与nonlocal

1. global用在局部名称空间直接修改全局名称空间中的数据
x = 111
def func():
    global x  # 修改全局名称空间x值
    x = 222
func()
print(x) # 222
------------------------------------------------------------------------------------
2. nonlocal 内层局部名称空间修改外层局部名称空间数据

def func():
    x = 222
    def func1():
        nonlocal x  # 修改外部名称空间x值
        x = 444

    func1()
    print(x) # 444
func()

函数名的多种用法

什么是函数名

函数名其实就是绑定的一块内存空间,只不过内存空间里是一串代码,我们在调用函数名的时候就会执行该名绑定的代码

多种用法

1. 可以当做变量名赋值
def func():
    print('变量名赋值用法')
res = func  # 变量名res 也绑定func的内存地址 (一段代码)
print(res)  # 打印res  结果是function func 已经指向函数func
res()  # res就等于函数func 调用res() = 调用函数func() 
执行func函数体代码,打印 '变量名赋值用法'
------------------------------------------------------------------------------------
2.可以当做函数的参数
def func():   # 1 定义函数func
    print('from func')  # 6 打印
def func1(a):  # 2 定义函数func1
    print(a)  # 4 此时a指向函数func 的内存地址(func的代码)
    a()  # 5 调用b变量名a() = 调用函数 func()
func1(func)  # 3 调用函数func1并传函数func 与a绑定  
----------------------------------------------------------------------------------
3.可以当做函数的返回值
def func():  # 1 定义函数func
    print('哈哈哈') # 9 打印哈哈哈
def func1():  # 2 定义函数func1
    print('嘿嘿嘿')  # 4 打印嘿嘿嘿
    return func  # 5 返回函数func 给func 1
res = func1()  # 3 有赋值符号先看右边,调用函数func1  # 6 res接收函数func返回值
print(res) # 7 打印res绑定的内存地址 function func
res()  # 8 调用res() = 调用函数func()
----------------------------------------------------------------------------------
4.可以当做容器使用
def register():  # 定义函数
    print('注册功能')
def login():	# 定义函数	
    print('登录功能')
def check_all():  # 定义函数
    print('查找功能')
def revamp():  # 定义函数
    print('修改功能')
def remove():  # 定义函数
    print('删除功能')
# 创建一个字典,用编号对应函数功能
func_dict = {
    '1': register,
    '2': login,
    '3': check_all,
    '4': revamp,
    '5': remove
}  
#  循环功能
while True:
    # 打印功能供用户选择
    print("""
        1.注册功能
        2.登录功能
        3.查找功能
        4.修改功能
        5,删除功能
        """)  
    # 获取用户选择
    choice = input('请输入想要执行的功能编号').strip()
    # 判断用户输入的编号是否在字典里
    if choice in func_dict:
        # 在的情况下,执行num 绑定字典中该编号的函数并调用
        num = func_dict.get(choice)()
    else:
        # 不在的情况打印没有此功能
        print('功能不存在')

闭包函数

  闭包函数要领
定义在函数内部的函数,并且用到了外部函数名称空间的名字。
代码:
def f1():  # 1 定义函数f1 
    x = '我在外部' # 3 x = 我在外部
    def f2():  # 4 定义函数 f 2
        print(x)  # 6 打印变量名x   我在外部
    f2()  # 5 调用函数f2
f1()  # 2 调用函数f1
-----------------------------------------------------------------------------------
用法1:另外一种给函数体代码传参的方式
def f1(name, home):  # 1 定义函数 f1 设置形参 name home
    print(f"""
        姓名:{name}  
        住址:{home}
        """)  # 3 格式化打印 引用name home 数据值
f1('tank', 'china')  # 2 调用函数f1 传 实参给 形参按位置绑定
-----------------------------------------------------------------------------------
用法2:闭包函数
def f1(name, home):  # 1 定义函数f1 设置形参 name home
    def f2():  # 3 f2函数
        print(f"""	
            姓名:{name}
            国籍:{home}
            """)  # 7 打印
    return f2	# 4 返回函数 f2 给 f1
res = f1('jack', 'usa')	# 2 先看右侧 调用f1并给给函数传参
# 5 f1 返回值 f2 与 res 绑定
res()  # 6 调用f2
res = f1('tony', 'england')  # 修改实参 同上
res()

装饰器

装饰器简介

装饰器概念:
在不改变被装饰对象原代码和原调用方式的情况下,给被装饰对象增加新功能。
本质:
其实就是结合了函数参数,名称空间,函数多种用法,闭包函数组合到一起的结果
"""
对修改封闭,对扩展开发
"""
------------------------------------------------------------------------------------
储备知识,时间相关操作
import time
time.sleep(3)
print('时间太长了 厕所该堵了')
循环用法:
count = 1 # 计时器
# 循环之前获取时间戳, 时间戳:1970年 00:00:00 距离现在过了多少秒
star_time = time.time()
while count < 100000:  # 计数器小于10000次时
    count += 1   # 计数器+1
    end_time = time.time()  # 获取结束时间
    print('本次上厕所消耗时间', end_time-star_time)  

装饰器推导流程

需求计算index函数运行时间
'''直接在index前后添加时间代码'''
import time
star_time = time.time() 
def index():
    time.sleep(2)  # 停下两秒
    print('from index')
def home():
    time.sleep(3)  # 停下3 秒
    print('form home')
index()
end_time = time.time() 
print('此次消耗', end_time - star_time)  # 两秒
'''我们可能在很多地方调用index不可能每调用一次就要写一次'''
------------------------------------------------------------------------------------
''' 这里我们就能联想到 函数的意义:相同的代码在不同的地方反复执行'''
'''使用函数方法,如果函数产生多个形参的话,并不能兼容,而且和装饰器不符合,调用方法不符'''
def get_time(xxx):  # 1定义函数 
    stat_time = time.time()  # 3 获取时间戳
    xxx()  # 4 调用xxx() 此时xxx和函数index绑定等于调用 index() 
    # 5 回到函数index里执行函数体代码
    end_time = time.time()  # 6 获取结束时间
    print('耗时', end_time - stat_time)  # 7 结束时间-开始时间 = 耗时
get_time(index)  # 2 给函数传参  变量名xxx 指向 函数index 内存空间
get_time(home)  # 同上
-----------------------------------------------------------------------------------
'''使用 闭包函数方法'''
def outer(xxx):  # 1定义函数outer 设置形参
    def get_time():  # 3定义函数  
        stat_time = time.time()  # 7获取时间戳
        xxx()  # 8此时xxx绑定函数index 回去执行函数index的代码
        end_time = time.time()  # 9 获取结束时间
        print('耗时', end_time - stat_time)  # 10 打印
    return get_time  # 4 get_time返回值给 res
res = outer(index)  # 2先看右边xxx 绑定index  # 5 res接收返回值函数get_time
res()  # 6 调用res此时res= get_time
res1 = outer(home)  # 同上
res1()
'''此时我们看这段代码还是和装饰器不符,调用方式被改变 '''       
------------------------------------------------------------------------------------
'''直接用使用和函数名一样的变量名'''
def outer(xxx):  # 1定义函数outer 设置形参
    def get_time():  # 3定义函数
        stat_time = time.time()  # 7获取时间戳
        xxx()  # 8此时xxx绑定函数index 回去执行函数index的代码
        end_time = time.time()  # 9 获取结束时间
        print('耗时', end_time - stat_time)  # 10 打印
    return get_time  # 4 get_time返回值给变量名index
index = outer(index)  # 2先看右边xxx 绑定index  #5变量名index接收返回值函数get_time
index()  # 6 调用index()此时index() = get_time()
home = outer(home)
home()
'''此时虽然调用方法符合装饰器了,但是如果函数有参数呢'''
------------------------------------------------------------------------------------
'''有参数使用方法'''
import time
def index(a, b):
    time.sleep(2)
    print('from index', a, b)
def home(c, d):
    time.sleep(3)
    print('form home', c, d)
def outer(xxx):  # 定义函数outer设置形参
    def get_time(a, b):  # 3定义函数 设置形参
        stat_time = time.time()  # 7获取时间戳
        xxx(a, b) """ 8 此时调用xxx绑定函数index 在局部名称空间里查找变量名a,b  此时a=1,b=2 。回去执行函数index的代码 """
        end_time = time.time()  # 9 获取结束时间
        print('耗时', end_time - stat_time)  # 10 打印
    return get_time  # get_time返回值给变量名index
index = outer(index)  # 2先看右边xxx 绑定index # 5变量名index接收返回值函数get_time
index(1, 2) # 6 调用index(1, 2)此时index(1,2) = get_time(a,b) a=1 b=2
home = outer(home)  # 同上
home(3, 4)
'''此时虽然解决了函数有参数以及有几个参数,但是如果不知道函数有几个参数又或有返回值呢,那么我们就可以使用可变长参数'''
------------------------------------------------------------------------------------
''' 可变长参数使用方法'''
def outer(xxx):  # 1定义函数 设置形参xxx
    def inner(*args, **kwargs):  # 3 定义函数设置形参  
        stat_time = time.time()  # 6 获取时间戳
        res = xxx(*args, **kwargs) """ 7 此时调用xxx绑定函数index 在局部名称空间里查找变量名*args  此时*args=(1,2,)可变长实参在传参时会把数据取出传输给函数。回去执行函数index的代码 """
        end_time = time.time()  # 8获取结束时间
        print('此次耗时', end_time - stat_time)  # 9打印
        return res # 10 返回函数res给res变量名
    return inner  # 4 函数inner绑定变量名index
index = outer(index) # 2 右边 xxx 指向index   5, index绑定函数inner
res = index(1, 2)  """# 6 先看右边调用index(1,2)此时等于函数inner(*args, **kwargs) 形参*args用于接收多余位置参数,结果是元组"""  # 11 变量名res接收函数res
print(res)  # 空 None

装饰器模板(给我背,滚瓜乱熟)

语法:
def outer(func):
    def inner(*args, **kwargs):
        # 执行被装饰对象之前可以做的额外操作
        res = func(*args, **kwargs)
        # 执行被装饰对象之后可以做的额外操作
        return res
    return inner

装饰器语法糖

def outer(func_name):
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner
"""
语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数调用
"""
@outer  # func = outer(func)
def func():
    print('from func')
    return 'func'

@outer  # index = outer(index)
def index():
    print('from index')
    return 'index'

func()
index()

作业

a = [False]


def outer(func_name):
    def inner(*args, **kwargs):
        if a[0]:
            res = func_name(*args, **kwargs)
            return res
        username = input('请输入用户名').strip()
        password = input('请输入密码').strip()
        if username == 'tank' and password == '123':
            print('验证通过')
            res = func_name(*args, **kwargs)
            a[0] = True
            return res
        else:
            print('验证失败')

    return inner


@outer
def register():
    print('注册功能')


@outer
def login():
    print('登录功能')


@outer
def transfer():
    print('转账功能')


@outer
def withdraw():
    print('取钱功能')


func_dict = {
    '1': register,
    '2': login,
    '3': transfer,
    '4': withdraw,
}


while True:
    print("""
       1.注册功能
       2.登录功能
       3.转账功能
       4.取钱功能
       """)
    choice = input('请输入想要执行的功能编号(q)').strip()
    if choice == 'q':
        break
    if choice in func_dict:
        num = func_dict.get(choice)()
    else:
        print('不存在此功能')
posted @ 2022-10-11 19:39  李阿鸡  阅读(138)  评论(0编辑  收藏  举报
Title