首页 > 编程语言 >python-类作为装饰器的各种情况

python-类作为装饰器的各种情况

时间:2023-06-09 17:45:39浏览次数:32  
标签:__ 各种 ClassDeco python self func print foo 装饰

1.装饰器没有参数:
这时foo不再是之前的函数名而是类ClassDeco的一个对象,并且foo.func=foo,对象名()会触发类ClassDeco的__call__方法:

class ClassDeco:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(f'Running {self.func.__name__}')
        self.func()
        print(f'End {self.func.__name__}')

@ClassDeco  # 等价于 foo = ClassDeco(foo)
def foo():
    print('do something')

foo()

"""
Running foo
do something
End foo
"""

2.装饰器有参数,被装饰函数没有参数
类名作为装饰器名,并且括号内有参数。先执行@后面的代码,类名加()形成一个对象,然后对象()触发类中的__call__方法,并且__call__方法中的func参数就是被装饰的函数名:

class ClassDeco:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __call__(self, func, *args, **kwargs):
        print(f'Running {func.__name__}')
        print(f'Using x + y = {self.x + self.y}')
        return func

@ClassDeco(1, 2)  # 等价于 foo = ClassDeco(1, 2)(foo)
def foo():
    print('do something')
    
foo()

"""
Running foo
Using x + y = 3
do something
"""

3.类装饰器不带参数,被包装对象带参数
类装饰器不带参数,就会直接将被装饰的函数名当做参数传入装饰器类的()中,触发装饰器类的__init__方法。此时的函数名是装饰器类的一个对象,这时的函数如果加括号调用,就会触发装饰器类当中的__call__方法,并且将参数传入到__call__方法当中的形参:

class ClassDeco:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(f'Running {self.func.__name__}')
        self.func(*args, **kwargs)
        print(f'End {self.func.__name__}')


@ClassDeco  # 等价于foo = ClassDeco(foo)
def foo(a, b):
    print('do something')
    print(f'return a + b = {a + b}')

foo(1,2)

"""
Running foo
do something
return a + b = 3
End foo
"""

4.类装饰器带参数且被装饰对象也带参数

from functools import wraps


class ClassDeco:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __call__(self, func, *args, **kwargs):
        print(f'Using x + y = {self.x + self.y}')

        @wraps(func)
        def wrapper(*args, **kwargs):
            print('func',func.__name__)
            func(*args, **kwargs)
            print(f'Ending {func.__name__}')

        return wrapper


@ClassDeco(1, 2)  # (1)
def foo(a, b):
    print('do something')
    print(f'return a + b = {a + b}')

foo(5,8)  # (2)
# 执行结果:
"""
Using x + y = 3
func foo
do something
return a + b = 13
Ending foo
"""

(1) 这行代码相当于:foo = ClassDeco(1,2)(foo),执行过程中ClassDeco(1,2)是先生成一个ClassDeco对象,此时会执行__init__方法。再执行对象(foo),会触发__call__方法,并且会将函数名foo当做参数传入到__call__中,所以会首先执行print(f'Using x + y = {self.x + self.y}'),并且self.x = 1,self.y = 2。此时定义了函数wrapper,并且把wrapper返回给foo,所以此时的foo就是wrapper,但是此时的wrapper并没有执行。
(2) 函数名加括号,此时的函数名是装饰器类ClassDeco中__call__的返回值wrapper,所以函数名加括号就相当于wrapper(5,8)。在wrapper中func(*args,**kwargs)才是真正执行foo(5,8)的代码

标签:__,各种,ClassDeco,python,self,func,print,foo,装饰
From: https://www.cnblogs.com/ERROR404Notfound/p/17469866.html

相关文章

  • Python 用户登录程序
    用户登录程序任务内容1、输入用户名和密码2、认证成功后显示欢迎信息3、输错3次后锁定流程图代码1、主文件importsyslock="lock.txt"logfile="login.txt"login_info=0i=0whilei<3andlogin_info==0:name=input("Pleaseinputyourname......
  • python selenium 模拟实现滑块验证码
    canndy_test.pyimportcv2importnumpyasnpdefmatchImg(imgPath1,imgPath2):imgs=[]#原始图像,用于展示sou_img1=cv2.imread(imgPath1)sou_img2=cv2.imread(imgPath2)#原始图像,灰度#最小阈值100,最大阈值500img1=cv2......
  • Python程序与设计
    2-27在命令行窗口中启动的Python解释器中实现在Python自带的IDLE中实现print("Helloworld")编码规范每个import语句只导入一个模块,尽量避免一次导入多个模块不要在行尾添加分号“:”,也不要用分号将两条命令放在同一行建议每行不超过80个字符使用必要的空行可以增加代码的可读性运算......
  • python3-类的专有方法
    1、介绍专有方法,具有私有方法的特性,即只能在类中被调用,是编程语言所准备的特殊作用的方法。2、方法说明2.1__init__构造方法,在对象创建时被调用。可以在方法中声明对象属性,以及其它初始化操作2.2__del__删除方法,当对象被释放时调用,可以在其中写一些对象结束时操作的代码......
  • python010 控制多台同类型设备
    defauto_find():rm=pyvisa.ResourceManager()devices=rm.list_resources()print(devices)ins_dict={'p1':None,'p2':None,'m1':None,'m2':None}counts={'p1':0,'p2'......
  • python gunicorn详解
    Gunicorn是一个unix上被广泛使用的高性能的PythonWSGIUNIXHTTPServer。和大多数的web框架(flask)兼容,并具有实现简单,轻量级,高性能等特点。 通过Gunicorn来启动flask框架defstart_app_by_system(args,app,options):"""启动配置项:paramargs:参数......
  • Python List
    List数据类型一、创建一个列表用把逗号分隔的不同的数据项使用方括号括起来即可。如下所示:>>>name_list=["root","gm","hlr"]二、访问列表中的值使用下标索引来访问列表中的值,与字符串的索引一样,列表索引从0开始。列表可以进行截取、组合等。>>>name_list['root',......
  • python3 del关键字
    1、介绍python中,del关键字可以用于销毁对象。一方面,可以用于实现业务,比如删除集合的元素。另一方面,可以节约内存资源,提升程序效率。 classStu:def__init__(self):self.name='abc'def__del__(self):print('del')stu_1=Stu()stu_2=S......
  • 山东烟台售楼部小区装饰仿铜不锈钢C形发光景观雕塑厂家
    山东烟台售楼部小区装饰仿铜不锈钢C形发光景观雕塑厂家仿铜不锈钢C形发光景观雕塑一把手形的不锈钢餐叉在优雅的形式中表现的是一种对现代生活的描述,但在深层传达的却是文明冲突的隐喻和象征。园林异形拱门是一件景抽象雕塑,景观不锈钢雕塑的底座设计与景观不锈钢雕塑同等重要,因为底......
  • python基础day22 time和re模块
    time模块(跟时间打交道的模块)表示时间的三种方式1.时间戳:1970年1月1日到现在的秒数2.格式化的时间字符串:2023-01-0111:11:113.结构化时间:它是让计算机看的 导入time模块imporetimetime.time()#时间戳time.sleep(3)#睡眠3秒python中时间日期格式化符号%y......