首页 > 其他分享 >装饰器基础二装饰类的装饰器

装饰器基础二装饰类的装饰器

时间:2022-09-28 16:12:23浏览次数:45  
标签:log args 基础 func print 装饰 def

类可以做装饰器,也可以被装饰器装饰,被装饰器装饰,那这个装饰器可以接收一个类,返回一个类

1、装饰类的装饰器-输入类返回类

def add_str(cls):
    def __str__(self):
        return str(self.__dict__)

    cls.__str__ = __str__
    return cls


@add_str
class MyObject:
    def __init__(self, a, b):
        self.a = a
        self.b = b


# 等价形式 MyObject = add_str(MyObject)
o = MyObject(1, 2)
print(type(o))
print(o)

2、先实现普通函数装饰器

def log_func(func):
    def wrapper(*args, **kwargs):
        print('func start!')
        print(f'args: {args}')
        res = func(*args, **kwargs)
        print('func end!')
        return res
    return wrapper


@log_func
def fib(n):
    if n <= 1:
        return 0
    return fib(n - 1) + fib(n - 2)

# print(fib(3))

2.1、普通函数装饰器用类包起来, 直接实例化类调用装饰器

class Decorator:
    def log_func(self, func):
        def wrapper(*args, **kwargs):
            print('func start!')
            print(f'args: {args}')
            res = func(*args, **kwargs)
            print('func end!')
            return res

        return wrapper


d = Decorator()


@d.log_func
def fib(n):
    if n <= 1:
        return 0
    return fib(n - 1) + fib(n - 2)


print(fib(4))

2.2、使用类方法装饰器

class Decorator:
    @classmethod
    def log_func(cls, func):
        def wrapper(*args, **kwargs):
            print('func start!')
            print(f'args: {args}')
            res = func(*args, **kwargs)
            print('func end!')
            return res

        return wrapper


@Decorator.log_func
def fib(n):
    if n <= 1:
        return 0
    return fib(n - 1) + fib(n - 2)


print(fib(4))

2.3、使用静态方法装饰器

class Decorator:
    @staticmethod
    def log_func(func):
        def wrapper(*args, **kwargs):
            print('func start!')
            print(f'args: {args}')
            res = func(*args, **kwargs)
            print('func end!')
            return res

        return wrapper


@Decorator.log_func
def fib(n):
    if n <= 1:
        return 0
    return fib(n - 1) + fib(n - 2)


print(fib(4))

总结:上面实现的是类装饰器给外部函数调用,内部的装饰器函数可以是静态方法,类方法,或者实例方法,那类内部这个装饰器可以给类内部实例方法使用吗?
答案是可以,但是需要像下面这么写。

3、给类方法使用的类装饰器

class Decorator:
    # @staticmethod
    def log_func(func):
        def wrapper(*args, **kwargs):
            print('func start!')
            print(f'args: {args}')
            res = func(*args, **kwargs)
            print('func end!')
            return res

        return wrapper

    @log_func
    def fib(self, n):
        if n <= 1:
            return 0
        return fib(n - 1) + fib(n - 2)


d = Decorator()
print(d.fib(4))
print('结束')

此时装饰器方法不是实例方法,类方法,静态方法,此时他可以说是类辅助函数装饰器,内部调用没有问题。
但是外部调用就出问题了~

# 外部调用
d = Decorator()
@d.log_func
def f():  # 会报TypeError
    pass

外部调用会报TypeError,参数异常。 外部调用时解释器会把类中log_func这个辅助函数当成一个正常实例方法解读,而这个方法中缺少了self,而使用Decorator类的方式外部直接调用则不会报错。此时外部应该使用类直接调用。


@Decorator.log_func
def f():  # 正常输出
    pass

4、哪有没有在类中或外部不管通过实例还是类方法均可调用呢,有的,需要在最后一行加如下代码: log_func = staticmethod(log_func) 或者在函数使用@staticmethod修饰成静态方法

class Decorator:
    # @staticmethod
    def log_func(func):
        def wrapper(*args, **kwargs):
            print('func start!')
            print(f'args: {args}')
            res = func(*args, **kwargs)
            print('func end!')
            return res

        return wrapper

    @log_func
    def fib(self, n):
        if n <= 1:
            return 0
        return fib(n - 1) + fib(n - 2)

    log_func = staticmethod(log_func)


# 内部调用
d = Decorator()
print(d.fib(4))

# 对象实例调用
d = Decorator()

@d.log_func
def f():  # 会报TypeError
    pass

# 类调用
@Decorator.log_func
def g():  # 正常输出
    pass

标签:log,args,基础,func,print,装饰,def
From: https://www.cnblogs.com/hikk/p/16738355.html

相关文章

  • Python学习:property装饰器
    1.property装饰器:装饰器是在不修改被装饰对象源代码以及调用方式的前提下为被装饰对象添加新功能的可调用对象property是一个装饰器,是用来绑定给对象的方法伪造成一个数......
  • python之内置的@property装饰器
    博主写的很详细https://www.cnblogs.com/hls-code/p/14821055.html?ivk_sa=1024320u 一、@property的介绍与使用python的@property是python的一种装饰器,是用来修饰方......
  • OPA基础
    OpenPolicyAgentOpenPolicyAgent(简称OPA)是一款go语言编写的开源通用策略引擎,它通过高级声明式语言rego编写策略代码为应用程序实现细粒度的访问控制机制,可用于为微服......
  • Java入门基础知识
    概念关键字:具有特殊用途的单词。保留字:未使用的关键字(gotoconst)。直接量:不可用作标识符(turefalsenull)。一、JAVA运行机制Java程序的运行必须经过编写、编译、运......
  • 线程基础知识18 线程池
    1什么是线程池线程池其实就是一种多线程处理形式,把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销。2为什么使......
  • Java基础知识练习
    Java基础知识练习1、if语句实现减肥计划:packagecom.itheima;/*使用if语句实现星期计划*///导包importjava.util.Scanner;publicclassTest01{publics......
  • Java面向对象基础
    Java面向对象基础一、类和对象1、什么是对象:万物皆对象,客观存在的事物皆可为对象2、面向对象:关注事物的信息,对事物的属性和行为有一定了解3、什么是类:对生活......
  • python装饰器
    1.1python装饰器装饰器(Decorators)是Python的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短。python的装饰器本质上是一个P......
  • 分布式系统涉及理论基础
    拜占庭将军问题拜占庭将军需要有10只军队但是分散各地,敌国可以同时抵御5只军队同时进攻,因此将军必须找出办法通过通讯兵远程发布指令,让其他将军知道何时进攻,但是10个支军......
  • linux基础命令grep显示前后
    通过grep查找字段后,方便查看前后文本grep-C8'中央仓库在中国的镜像'settings.xml显示指定行的上线8行[root@znjc-ds-zcfwservconf]#grep-C8'中央仓库在中国......