首页 > 其他分享 >装饰器

装饰器

时间:2023-12-11 14:36:46浏览次数:24  
标签:return res inner func print 装饰 def

今日习题

*函数的四种定义方式
*函数的调用方式
*函数的参数类型
*函数的形参类型都有哪些
*函数实参传参都能如何传参
*名称空间是什么,有哪些
*作用域是什么,都有哪些
*什么是闭包函数

#【一】函数的四种定义方式
#【1】无参无返回值的函数
def index():
    res = 1 + 1
    print(res)
index()
#【2】有参无返回值的函数
def index(x):
    print(x)
index(1)
#【3】有参有返回值
def index(x):
    return x
res = index(1)
print(res)
#【4】多个参数多个返回值
def add(x, y):
    return x + y, x * y
res_one,res_two = add(2,9)
print(res_one)
print(res_two)

res = add(4, 9)
print(len(res))
for i in range(0, len(res)):
    res_one = res[i]
    print(res_one)
# 【二】函数的调用方式
def add(x, y):
    return x + y
def multy(a, b,func=None):
    # a 是 整数 int 类型
    # a 是一个函数的地址 a() ---> 返回值
    # func = add
    if not func:
        return a * b
    else:
        res = func(a, b)
        # add(1,9) ---> 10
        # func -- add --->  a + b --> 10 + 8 --> 18
        return func(a, b) * a
# 【1】直接代用
add(4, 7)
# 【2】间接调用
res = add
res(4,7)
# 【3】函数作为参数
print(multy(add(1,9),8))
print(multy(add(1,9),8,func=add))
# 【三】函数的参数类型
# 【1】形参 --- 在定义函数时,后面携带的参数名就叫形参
# 如果我们想让其他人就传指定的类型的话,可以做一个弱声明
def add(x: int, y):
    print(x )
    print(y )
add('a',9)
# 可变长参数
def add(*args,**kwargs):
	print(args) # (1, 2, 3, 4, 5)
	print(kwargs) # {'name': 'dream', 'age': 18}
add(1,2,3,4,5,name='dream',age=18)
# 命名关键字参数
def add(name,age,*,sex,height):
    print()

# 默认参数 -- 不是命名关键字的时候,默认参数必须放在位置参数的后边
def add(name='dream',age,sex,height):
    print()
# 默认参数 -- 如果是命名关键字参数,我的默认参数就可以不区分位置
def add(name,age,*,sex='男',height):
    print()
# 【2】实参
def add(x,y):
    print(x)
# 实参可以是任意类型
# 实参还可以是表达式 add(2+2)
# 实参还可以是函数的返回值
# 实参还可以是函数的地址

# 实参的传参方式
# 按位置传参数
add(8)
# 按关键字传参
add(x=8)
# 注意:关键字传参的时候,位置参数一定要在关键字参数前面
add(7,y=9)
# 【四】名称空间是什么,有哪些
# 定义变量名和变量值 ,变量名其实就是指向变量值的引用
# 【1】内建名称空间:随着Python解释器的启动而自动加载的名称空间 : print(max())
# 【2】全局名称空间(内建 + 我们自己定义的):我们自己在文件中定义的变量名/函数名/类名 ...
# 【3】局部名称空间:定义在函数内部/定义在类内部加载出来的名称空间

# 内建
print(max([1,2,3]))
# 全局
num = 1
# 局部
def add():
    print(num)
add()
# 局部可以使用全局的变量
# 全局不能使用局部的变量
# 【五】作用域是什么,都有哪些
# 【1】内置 -- 内建
# 【2】全局作用域
# 【3】局部作用域
# 【4】嵌套作用域
num = 2
print(num)
def outer():
    # 局部修改全局变量需要 在函数内容 用 global 声明全局变量
	global num
	print(num)
	num += 1
	print(num)
	outer()
print(num)

num = 2
def outer():
    # 局部修改全局变量需要 在函数内容 用 global 声明全局变量
	global num
    num_inner = 99
    def inner():
        nonlocal num_inner
        num_inner += 99
    inner()
    print(num_inner)
    num += 1
outer()
print(num)

# *什么是闭包函数
# 闭包函数就是内嵌函数对外部函数作用域有引用的函数
num = 2
def outer():
    global num
    num_inner = 99
    def inner():
        nonlocal num_inner
        num_inner += 99
    print(num_inner)
    num += 1
    return inner
inner = outer()
print(num)
inner()

【一】什么是装饰器

  • 装饰 代指为被装饰对象添加新的功能, 代指器具/工具,装饰器与被装饰的对象均可以是任意可调用对象。
  • 概括地讲,装饰器的作用就是在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能
  • 装饰器经常用于有切面需求的场景
    • 插入日志、性能测试、事务处理、缓存、权限校验等应用场景
    • 装饰器是解决这类问题的绝佳设计
    • 有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

【二】装饰器的作用

  • 软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。
    • 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
    • 对修改封闭,意味着对象一旦设计完成,就可以独立完成其工作,而不要对其进行修改。
  • 软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃
    • 而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩展的可能性,这就用到了装饰器。

【三】装饰器的分类

  • 函数装饰器分为:无参装饰器和有参装饰两种
  • 二者的实现原理一样,都是’函数嵌套+闭包+函数对象’的组合使用的产物。

【四】装饰器一

# 闭包函数导读
def outer():
	print(f"这是 outer 开始 ")
	def inner():
      print(f"这是 inner ")
      print(f"这是 outer 结束 ")
      return inner

inner = outer()
inner()
import time

def login():
    time.sleep(1)
    ...

def register():
    time.sleep(1)
    ...

# 计算 login 函数的运行时间,如何计算?
# 开始时间
start_time = time.time()
# 调用函数
login()
# 计算 结束时间 - 开始时间 = 总耗时
print(f'总耗时 {time.time() - start_time} s')

# 开始时间
start_time = time.time()
# 调用函数
register()
# 计算 结束时间 - 开始时间 = 总耗时
print(f'总耗时 {time.time() - start_time} s')
login_user_dict = {'username': 'dream', 'is_admin': True}
user_data_dict = {'dream': {'password': 521, 'role': 'admin'},
                  'hope': {'password': 369, 'role': 'normal'}}


def login(username, password):
    if password == user_data_dict[username].get('password'):
        print(f"登陆成功")
        login_user_dict['username'] = username
    if user_data_dict[username].get('role') == 'admin':
        login_user_dict['is_admin'] = True
    else:
        login_user_dict['is_admin'] = False


# def check_admin():
#     if login_user_dict['username'] and login_user_dict['is_admin']:
#         return True
#     else:
#         return False


# def check_admin(func):
#     # 验证我当前是否登录并且是管理员
#     if login_user_dict['username'] and login_user_dict['is_admin']:
#         # W如果是管理员 ,我就正常 执行我传进来的函数地址
#         res = func()
#         print(f'check_admin 内部的 res {res}')
#         return res
#     # 重新校验
#     else:
#         # 重新登录的逻辑
#         return False, '重新登录'


def check_admin(func):
    def inner():
        # 验证我当前是否登录并且是管理员
        if login_user_dict['username'] and login_user_dict['is_admin']:
            # W如果是管理员 ,我就正常 执行我传进来的函数地址
            res = func()
            print(f'check_admin 内部的 res {res}')
            return res
        # 重新校验
        else:
            # 重新登录的逻辑
            return False, '重新登录'

    return inner

# @check_admin
def get_money():
    # 取钱的前提是 : 我已经登陆过并且是管理员 ---> 验证我的登录和我的身份
    return True, f'取了一万块'
# print(get_money())
get_money = check_admin(func=get_money)
get_money()
print(get_money())
def add():
    return 1 + 1
num = 2
def outer(func):
    # print(func) # <function add at 0x0000023305590360>

    def inner():
        if num == 3:
            res = func()
            print(func)
            return res
        else:
            return False
    return inner
add = outer(func=add)
print(add())

【五】无参装饰器模板

# 装饰器模板
def outer():
    def inner():
        ...

    return inner

# 传参数
def add():
    return 1

def outer(func):
    def inner():
        res = func()
        return res
    return inner
add = outer(func=add)
add()
def add():
    return 1
def outer(func):
    def inner():
        '''这里写调用 func 函数之前的逻辑'''
        res = func()
        '''这里写调用 func 函数之后的逻辑'''
        return res
    return inner
add = outer(func=add)
add()
login_user_dict = {'username': 'dream', 'is_admin': False}

def outer(func):
    def inner():
        '''这里写调用 func 函数之前的逻辑 :必须是登陆过后并且是管理员才能执行 add 函数'''
        if login_user_dict['username'] and login_user_dict['is_admin']:
            res = func()
            '''这里写调用 func 函数之后的逻辑'''
            return res
        else:
            return False,'必须是管理员并且登陆了'
    return inner

@outer # --- > add = outer(add)
def add():
    return True,f'add函数被执行了'
print(add())
add = outer(func=add)
print(add())
# 装饰器模板
def outer(func):
    def inner():
        '''这里写调用 func 函数之前的逻辑'''
        res = func()
        '''这里写调用 func 函数之后的逻辑'''
        return res

    return inner

【六】装饰器练习

# 看电影
# 用户信息字典 --- 定义用户名 和 年龄
# 大于 18 岁 看电影
# 小于 18 岁  18禁

# 取钱 ---> 登录(装饰器验证登录)
# 看电影 ==》 验证年龄(装饰器验证年龄)
user_data_dict = {'dream': 19, 'hope': 17}


# 装饰器模板
def outer(func):
    def inner():
        '''这里写调用 func 函数之前的逻辑'''
        res = func()
        '''这里写调用 func 函数之后的逻辑'''
        return res

    return inner


def watch():
    ...


def see():
    ...
# 装饰器模板
def outer(func):
    def inner():
        '''这里写调用 func 函数之前的逻辑 直接校验年龄'''
        if user_data_dict['hope'] >= 18:
            res = func()
            '''这里写调用 func 函数之后的逻辑'''
            return res
        else:
            return False, f'18禁'

    return inner


@outer  # watch= outer(watch)
def watch():
    return True, f'看电影'
print(watch())


# watch= outer(watch)
# print(watch())

def see():
    return True, f'看电影'
# see= outer(see)
# print(see())
# 装饰器模板
def outer(func,name):
    def inner():
        '''这里写调用 func 函数之前的逻辑 直接校验年龄'''
        if user_data_dict[name] >= 18:
            res = func()
            '''这里写调用 func 函数之后的逻辑'''
            return res
        else:
            return False, f'18禁'
    return inner
def watch():
    return True, f'看电影'
watch= outer(watch,name='dream')
# print(watch(name='dream'))
print(watch())
user_data_dict = {'dream': 19, 'hope': 17}
# 【2】outer 函数 (watch的内存地址)
def outer(func):
    # 【6】inner(name)  name='dream'
    def inner(name):
        '''这里写调用 func 函数之前的逻辑 直接校验年龄'''
        # 【7】根据字典取值 user_data_dict['dream']
        if user_data_dict[name] >= 18:
            # func ---> watch
            # watch(name=name)
            # 【8】年龄大于 18 =---> 执行 watch的内存地址 --- watch函数
            # 【10】带了上面传进来的name name='dream'
            # 【12】 res  = (True, f'{name} :>>> 看电影')
            res = func(name)
            '''这里写调用 func 函数之后的逻辑'''
            # 【13】把 res 返回出去
            return res
        else:
            return False, f'18禁'

    # 【3】返回了 inner 的内存地址
    return inner
# 看电影 ---> 谁在看电影
# 【9】watch(name) 发现 watch 也需要一个name参数
def watch(name):
    # name 传进来的谁在看电影
    # 【11】name='dream' ---> 返回 True, f'{name} :>>> 看电影'
    return True, f'{name} :>>> 看电影'


# 正常调用函数的逻辑 : watch(name='dream')
# 【1】watch= outer(watch的函数地址)
# 【4】watch = outer(watch) 返回的 inner 的内存地址
watch = outer(watch)
# 【5】指定 watch(name='dream') --- 执行 inner 的内存地址 --- 发现 需要执行 inner(name)
# 【14】 res = (True, f'{name} :>>> 看电影')
print(watch(name='dream'))
# 【15】(True, 'dream :>>> 看电影')



def outer(func):
    def inner(*args,**kwargs):
        if user_data_dict[args[0]] >= 18:
            res = func(args[0])
            return res
        else:
            return False, f'18禁'
    return inner
def watch(name):
    # name='inner 传给 watch 的 name'
    return True, f'{name} :>>> 看电影'
watch = outer(watch)
print(watch('dream'))
# 带参数装饰器模板
def outer(func):
    def inner(*args,**kwargs):
        '''这里写调用 func 函数之前的逻辑 直接校验年龄'''
        res = func(*args,**kwargs)
        '''这里写调用 func 函数之后的逻辑'''
        return res
    return inner
@outer
def add(*args,**kwargs):
    print(args)
    print(kwargs)

add(888,x=999)

标签:return,res,inner,func,print,装饰,def
From: https://www.cnblogs.com/unrealqcc/p/17894315.html

相关文章

  • NestJS 筑基:TypeScript 类和装饰器
    前言先回顾下前文中介绍了哪些内容:使用@nestjs/cli创建和管理Nest应用Hello,World示例代码分析Nest基本概念:模块,控制器,服务常用的装饰器:@Module、@Controller、@Get、@InjectableNest目录结构分析@nest/cli脚手架的命令本文先不继续讲解Nest中的内容,而是打算介绍TypeSc......
  • Python - 【装饰器】详解
    一.概念Python装饰器本质上是一个函数,用于修改其他函数的功能。装饰器可以在不改变函数代码的情况下添加新的功能,使代码更具可读性、可维护性和可重用性。使用装饰器可以把一个函数传递给另一个函数,使其具有新的行为,而无需修改函数本身的代码。二.基本语法@decorator_namedeff......
  • 【python】@property装饰器
    @property介绍:@property是一个内置的装饰器,用于将一个方法变成属性调用。让方法可以像实例属性那样进行访问,这样可以保证对象状态的封装性,同时,将数据的“获取”和“修改”集成到一处处理,提高代码的可读性和可维护性。通过对比,解释@property的意义:classPerson:def__init_......
  • Python装饰器
    一、核心思想在不改变被装饰对象内部代码和原有调用方式的基础之上在添加额外的功能二、装饰器的实现过程根据实际需要,一步一步满足需求,完成对装饰器的理解1、简易版本给index函数添加统计执行时间的功能importtimedefindex():time.sleep(3)print('fromind......
  • 深入探讨 Python 中的装饰器和上下文管理器
    Python作为一门灵活而强大的语言,提供了许多高级特性,其中装饰器(Decorators)和上下文管理器(ContextManagers)是其中两个非常有用的概念。这两个功能性特性提供了对代码结构和行为进行修改和控制的强大工具。它们允许程序员在不修改源代码的情况下,添加、修改或扩展函数或类的功能,帮助......
  • 01 装饰器的使用
    装饰器实现登录验证在一个web项目中,很多接口需要用户必须是登录状态,否则就应该跳转到登录页面,这个可以通过装饰器实现。在实现之前,我们必须弄清除两个问题装饰器执行先后的问题可以看到装饰器在函数被加载的时候就执行了,先执行的最下层的装饰器,再执行的上层的装饰器,这像什么......
  • python 属性装饰器和对应的setter方法,属性的封装和安全性控制
    当我们在类中定义属性时,通常希望能够对属性的读取和写入进行控制,以确保数据的完整性和安全性。属性装饰器和对应的setter方法提供了一种实现属性封装和安全性控制的方法。属性装饰器是Python的一种语法特性,用于修饰类的方法,使其表现为一个属性而不是一个普通的方法。通过使用属性......
  • Python中的装饰器
    一、装饰器的作用装饰器是Python中一种强大的编程工具,它允许我们在不修改原始函数代码的情况下,动态地增加功能或修改函数行为。装饰器提供了一种简洁而优雅的方式来修改、扩展或包装函数,使代码更具可读性和可维护性。装饰器的主要作用包括:添加额外的功能或逻辑,如日志记录、性......
  • python装饰器
    装饰器本质上是一个Python函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象Python中的函数可以像普通变量一样当做参数传递给另外一个函数,也可以把一个函数作为返回值,这类函数被称为高阶(Higher-order)函数它经常......
  • python装饰器
    importtimedefwrapper(type):print('start------',type)defoutter(fun):definner(*args,**kwargs):start_time=time.time()fun(*args,**kwargs)end_time=time.time()print('ru......