Python知识十函数装饰器补充

昨日内容回顾

  • 名称空间作用域

    全局有效
    	内置名称空间 全局名称空间
    局部有效
    	局部名称空间
    
  • 关键字global与nonlocal

    global关键字
    	在局部想要修改全局的不可变类型数据
    nonlocal关键字
    	在局部想要修改局部不可变类型的数据
    
  • 函数对象(函数名)

    # 四种用法
    1.可以当做变量名赋值给其他变量
    2.可以当做函数的参数传入
    3.可以当做函数的返回值(打破了名称空间的顺序  全局可以使用局部)
    4.可以当做容器类型的元素(功能匹配)
    
  • 函数的嵌套调用

    """函数名遇到括号就会立刻调用(执行函数体代码)"""
    # 函数体内部调用其他函数
    	我们在书写代码的时候有很多功能可能提前已经写好了
        那么可以直接反复调用
    
  • 函数的嵌套定义

    # 函数体内部定义其他函数
    	我们可以将很多复杂的操作和代码全部定义到一个新的函数体内
        暴露给用户的只有一个函数名(接口)
    
  • 闭包函数

    闭包函数
    	1.定义在函数内部的函数
        2.内部函数使用了外部函数名称空间中的名字
       
    闭包函数实现了第二种给函数体代码传参的方式
    def register(username):
        print(username)
      
    def outer(username):
        # username = 'jason'
        def register():
            print(username)
        return register
    res = outer('jason')
    res()
    
    # 扩展爬虫知识
    	import requests
        requests.get('网址')  # 并不是所有的网址都可以直接获取
    
  • 装饰器简介

    装饰器
    	在不改变被装饰对象"内部代码"以及"调用方式"的基础上添加新的功能
    原则
    	开放封闭原则
        	对扩展开放
            对修改封闭
    import time
    time.sleep()  # 让程序原地阻塞(睡)指定的秒数
    time.time()  # 时间戳(主要用于时间计算)
    
    """装饰器不是新的知识点 而是函数相关知识的整合"""
    

今日内容概要

  • 装饰器简易版本
  • 装饰器进阶版本
  • 装饰器练习(认证功能)
  • 装饰器固定模板(退路)
  • 装饰器语法糖(简化代码)
  • 有参装饰器
  • 装饰器练习题(三层装饰器)
  • 函数递归
  • 算法之二分法(解决问题的思维逻辑)

今日内容详细

装饰器简易版本

# 给函数添加统计执行时间的功能

def outer(func):  # func指向的是函数名index
    # func = index
    def get_time():
        start_time = time.time()
        func()
        end_time = time.time()
        print('函数运行时间:%s' % (end_time - start_time))
    return get_time  # 将get_time函数名返回出去
index = outer(index)  # outer(index函数名)
# 左侧的变量名index指代是函数名get_time
index()

解决参数问题

import time
def index():
    time.sleep(3)
    print('亚洲最大的线上赌场开业了 双眼发红光的在线发牌!!!')
def login(name):
    time.sleep(1)
    print('%s正在发牌'%name)
def outer(func):  # func指向的是函数名login
    # func = login
    def get_time(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        end_time = time.time()
        print('函数运行时间:%s' % (end_time - start_time))
    return get_time  # 将get_time函数名返回出去
login = outer(login)
login('jason')
index = outer(index)
index()

解决返回值问题

import time
def index():
    time.sleep(3)
    print('亚洲最大的线上赌场开业了 双眼发红光的在线发牌!!!')
    return 'from index'
def login(name):
    time.sleep(1)
    print('%s正在发牌'%name)
    return 'from login'
def outer(func):  # func指向的是函数名login
    # func = login
    def get_time(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)  # 接收被装饰函数的返回值
        end_time = time.time()
        print('函数运行时间:%s' % (end_time - start_time))
        return res  # 执行完get_time之后返回被装饰函数执行之后的返回值
    return get_time  # 将get_time函数名返回出去
# index = outer(index)
# res = index()
# print(res)
login = outer(login)
res1 = login('jason')
print(res1)

装饰器 (认证登录功能)

# 今天只需要掌握简单版本(每个都校验用户名和密码)
# 记录用户状态的版本多花时间去练
import time
def index():
    time.sleep(1)
    print('百万大奖等你来拿 赶快加入我们吧!!!')
def home():
    time.sleep(1)
    print('学学学 一天到晚就是学 卷死你们这些家伙')
def register():
    time.sleep(1)
    print('注册功能')
# 给index函数添加认证功能
"""
在调用index之前需要用户输入用户名和密码
    正确才可以调用
    错误直接拒绝
"""
# 定义一个用于记录用户是否登录的数据
is_login = {'is_login':False}


def login_auth(func):
    def auth(*args,**kwargs):
        # 1.1 先判断用户是否已经登录
        if is_login.get('is_login'):
            # 3.正常执行函数index
            res = func(*args, **kwargs)
            return res
        # 1.先获取用户的用户名和密码
        username = input('username>>>:').strip()
        password = input('password>>>:').strip()
        # 2.校验用户名和密码是否正确
        if username == 'jason' and password == '123':
            # 3.正常执行函数index
            res = func(*args,**kwargs)
            # 4.将记录用户登录状态的数据修改
            is_login['is_login'] = True
            return res
        else:
            print('用户名或密码错误 无法执行函数')
    return auth
index = login_auth(index)
index()
home = login_auth(home)
home()
register = login_auth(register)
register()

装饰器固定模板**********************************

def index():  # 被修饰函数

def outer(func):
    def inner(*args, **kwargs):
        # print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        # print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner

index = outer(index)  # 创建修饰联系语句
index()

语法糖固定模板**********************************

def outer(func):
    def inner(*args, **kwargs):
        # print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        # print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner

@outer
def index():  # 被修饰函数
index()

装饰器语法糖

def outer(func):
    def inner(*args, **kwargs):
        print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner
@outer  # index = outer(index)
def index(*args, **kwargs):
    print('from index')
@outer  # home = outer(home)
def home():
    print('from home')

"""
装饰器语法糖是写规范
    语法糖必须紧贴在被装饰对象的上方
装饰器语法糖内部原理
    会自动将下面紧贴着的被装饰对象名字当做参数传给装饰器函数调用
"""

双层语法糖

# 统计函数运行时间
import time
def get_time(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)  # 执行被装饰的函数
        end_time = time.time()
        print('函数执行时间:%s'%(end_time-start_time))
        return res  # 将被装饰函数执行之后的返回值返回
    return inner
# 校验用户登录装饰
def login_auth(func):
    def inner(*args, **kwargs):
        # 1.先获取用户的用户名和密码
        username = input('username>>>:').strip()
        password = input('password>>>:').strip()
        # 2.校验用户名和密码是否正确
        if username == 'jason' and password == '123':
            res = func(*args, **kwargs)  # 执行被装饰的函数
            return res  # 将被装饰函数执行之后的返回值返回
        print('用户名或密码错误 无权限执行')
    return inner
@login_auth
@get_time
def index():
    time.sleep(1)
    print('from index')
index()

装饰器修复技术

from functools import wraps
def outer(func):
    @wraps(func)  # 修复技术就是为了让被装饰对象更加不容易被察觉装饰了
    def inner(*args, **kwargs):
        print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner


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

def home():
    """这是一个home函数"""
    print('from home')
# help(index)
# help(home)
# print(index)
# help(len)

练习题

# 判断七句print执行顺序
def outter1(func1):
    print('加载了outter1')
    def wrapper1(*args, **kwargs):
        print('执行了wrapper1')
        res1 = func1(*args, **kwargs)
        return res1
    return wrapper1

def outter2(func2):
    print('加载了outter2')
    def wrapper2(*args, **kwargs):
        print('执行了wrapper2')
        res2 = func2(*args, **kwargs)
        return res2
    return wrapper2

def outter3(func3):
    print('加载了outter3')
    def wrapper3(*args, **kwargs):
        print('执行了wrapper3')
        res3 = func3(*args, **kwargs)
        return res3
    return wrapper3


@outter1
@outter2
@outter3
def index():
    print('from index')

有参装饰器

def outer(source_data):
    # source_data = 'file'
    def login_auth(func):
        def auth(*args,**kwargs):
            # 2.校验用户名和密码是否正确
            # 数据的校验方式可以切换多种
            if source_data == 'file':
                # 从文件中获取用户数据并比对
                print('file文件获取')
            elif source_data == 'MySQL':
                # 从MySQL数据库中获取数据比对
                print('MySQL数据库获取')
            elif source_data == 'postgreSQL':
                # 从postgreSQL数据库中获取数据对比
                print('postgreSQL数据库获取')
            else:
                print('用户名或密码错误 无法执行函数')
        return auth
    return login_auth

@outer('file')
def index():
    print('from index')
@outer('MySQL')
def home():
    print('from home')

index()
home()

作业

1.整理今日内容及博客
2.自我梳理课上所有装饰器执行流程
3.尝试练习认证装饰器(反复认证、记录认证)
4.预习明日内容
	https://blog.sholdboyedu.com/?p=3406

补充
image

image

posted @ 2021-11-17 22:42  弑悟  阅读(8)  评论(0)    收藏  举报