python函数装饰器

今日内容概要

  • global与nonlocal
  • 函数名的多种用法
  • 闭包函数
  • 装饰器简介
  • 无参装饰器
  • 有参装饰器
  • 装饰器模板
  • 装饰器语法糖

今日内容详细

global与nonlocal

money = 666

def index()
	global money
    money = 123

index()
print(money)
"""
局部名称空间直接修改全局名称空间中的数据
"""

def index():
    name = 'jason'
    def inner():
        nonlocal name
        name = 'kevin'
    inner()
    print(name)

index() 
'''
内层局部名称空间修改外层局部名称空间中的数据
'''

函数名的多种用法

函数名其实绑定的也是一块内存地址 只不过该地址里面存放的不是数据值而是一段代码 函数名加括号就会找到改代码并执行
1.可以当作变量名复制
	def index():pass
    res = index
    res()
2.可以当作函数的参数
	def index():
        print('from index')
    def func(a):
        print(a)
        a()
    func(index)    
3.可以当作函数的返回值
    def index():
        print('from index')
    def func():
        print('from func')
        return index
    res = index
    print(res)
    res()
    
    def index():
    	print('from index')
	def func():
    	print('from func')
    return func

	res = index
	print(res)
	res()
4.可以当作容器类型(可以存放多个数据的数据类型)的数据
    def register():
        print('注册功能')

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

    def withdraw():
        print('提现功能')

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

    def shopping():
        print('购物功能')

    # 定义功能编号与功能的对应关系
    func_dict = {
        '1': register,
        '2': login,
        '3': withdraw,
        '4': transfer,
        '5': shopping
    }

    while True:
        print("""
        1.注册功能
        2.登录功能
        3.提现功能
        4.转账功能
        5.购物功能
        """)
        choice = input('>>>:').strip()
        if choice in func_dict:
            func_name = func_dict.get(choice)
            func_name()
        else:
            print('该功能编号不存在')
        

闭包函数

"""
定义在函数内部的函数 并且用到了外部函数名称空间中的名字
	1.定义在函数内容
	2.用到外部函数名称空间中的名字
"""
def index():
    name = 'jason'
    def inner():
        print(name)

        
闭包函数实际应用>>>:是另外一种给函数体代码传参的方式!!!
	给函数体代码传参的方式1:代码里面缺上面变量名形参里就补上面变量名
     def register(name,age):
     print(f"""
       姓名:{name}
       年龄:{age}
       """)
	 register('guts','18')
     给函数体代码传参的方式2:闭包函数
        def outer(name, age):
        def register():
            print(f"""
            姓名:{name}
            年龄:{age}
            """)
        return register
        res = outer('guts',22)
        res()
        res = outer('jason',38)
        res()

装饰器简介

1.概念
	在不改变被装饰对象原代码和调用方式的情况下给被装饰的对象添加新的功能
2.本质
	并不是一门新技术 而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3.口诀
	对修改封闭 对扩展开放
4.储备知识
	时间相关操作
    	import time
        print(time.time())  # 时间戳(距离1970-01-01 00:00:00所经历的秒数)
		time.sleep(3)
		print('睡醒了 干饭')

		import time
         count = 0
         start_time = time.time()
         while count < 100:
             print('哈哈哈')
             count += 1
         end_time = time.time()
         print('循环消耗的时间', end_time - start_time)

装饰器推导流程

import time

def index():
    time.sleep(3)
    print('from index')
def home():
    time.sleep(1)
    print('from home')
'''1.直接在调用index函数的前后添加代码'''
start_time = time.time()
index()
end_time = time.time()
print('函数index的执行时间为>>>:',end_time-strat_time)
'''2.index调用的地方较多 代码不可能反复拷贝>>>:相同的代码需要在不同的位置反复执行>>>:函数'''
def get_time():
    strat_time = time.time()
    index()
    end_time = time.time()
    print('函数index的执行时间为>>>:',end_time-start_time)
get_time()
'''3.函数体代码写死了 只能统计index的执行时间 如何才能做到统计更多的函数运行时间 直接传参变换统计的函数'''
def get_time(xxx):
    start_time = time.time()
    xxx()
    end_time = time.time()
    print('函数的执行时间为>>>:', end_time-start_time)
get_time(index)    
get_time(home)
'''4.虽然实现了一定的兼容性 但是并不符合装饰器的特征  第一种传参不写 只能考虑闭包'''
def outer(xxx):
    # xxx = index
    def get_time():
        strat_time = time.time
        xxx()
        end_time = time.time
        print('函数的执行时间为>>>:', end_time-start_time)
    return get_time
res = outer(index)
res()
res1 = outer(home)
res1()
'''5.调用方式还是不对 如何变形>>>:变量名赋值绑定 (******)'''
def outer(xxx):
    def get_time:
        start_time = time.time()
        xxx()
        end_time = time.time()
        print('函数的执行时间为>>>:', end_time-start_time)
    return get_time
index = outer(index)
home = outer(home)
index()
home()
'''6.上述装饰器只能装饰无参函数 兼容性太差'''
def func(a):
	time.sleep(0.1)
    print('form func',a)
    
def func1(a,b):
	time.sleep(0.2)
    print('form func1',a,b)
    
def func2():
	time.sleep(0.3)
    print('form func2')

def outer(xxx):
    def get_time(a,b):
        start_time = time.time()
        xxx(a,b)
        end_time = time.time()
        print('函数的执行时间为>>>:',end_time-start_time)
     return get_time   
func1 = outer(func1)
func1(1, 2)
func = outer(func)
func(1)
func2 = outer(func2)
func2()
'''7.被装饰的函数不知道有没有参数以及有几个参数 如何兼容'''
def func(a):
    time.sleep(0.1)
    print('from func', a)
def func1(a,b):
	time.sleep(0.2)
    print('from func', a, b)
def outer(xxx):
    def get_time(*args, **kwargs):
        start_time = time.time()
        xxx(*args, **kwargs)
        end_time = time.time()
        print('函数的执行时间>>>:', end_time-start_time)
	return get_time
fucn = outer(func)
func(123)
func = outer(func1)
func1(1, 2)
'''8.如果被装饰的函数有返回值'''
import time
def func(a):
    time.sleep(0.1)
    print('from func', a)
    return 'func'
def func1(a,b):
    time.sleep(0.2)
    print('from func1', a, b)
    return 'func1'
def outer(xxx):
    def get_time(*args, **kwargs):
        start_time = time.time()
        res = xxx(*args, **kwargs)
        end_time = time.time()
        print('函数的执行时间>>>:', end_time-start_time)
        return res
    return get_time
func = outer(func)
res = func(123)
print(res)

装饰器模板

# 务必掌握
def outer(func):
    def inner(*gras, **kwgras):
        # 执行被装饰对象之前可以做的额外操作
        res = func(*gras, **kwgras)
        # 执行被装饰对象之后可以做的额外操作
        return res
    return inner

装饰器语法糖

def outer(func_name):
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func(*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()

作业

def outer(func):
    def inner(*args,**kwargs):
        username = input('name:')
        password = input('pwd:')
        if username == 'guts' and password == '123':
            print('用户登录成功')
        else:
            print('用户名或密码错误')
            return
        res = func(*args,**kwargs)
        return res
    return inner

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

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

@outer
def withdraw():
    print('提现功能')

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


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

while True:
    print("""
       1.注册功能
       2.登录功能
       3.提现功能
       4.转账功能
       """)
    choice = input('>>>:').strip()
    if choice in func_dict:
        func_dict.get(choice)()
    else:
        print('功能编号不存在')
posted @ 2022-10-11 21:56  理塘丁真1!5!  阅读(30)  评论(0编辑  收藏  举报