Py测开《通过类实现一个通用的装饰器》

2022-03-30 09:16:05 浏览数 (2)

目录

  • 一、通过类实现一个通用的装饰器,既可以装饰函数,也可以装饰类,既可以装饰有参数的,又可以装饰无参数的。
  • 二、请描述__new__、__str__、__repr__、__call__分别在什么情况下会被触发?
  • 三、总结

一、通过类实现一个通用的装饰器,既可以装饰函数,也可以装饰类,既可以装饰有参数的,又可以装饰无参数的。

在装饰的时候把原来这个test_01函数,通过test_01=Decorator(test_01)传进去了。通过这个Decorator类,Decorator(test_01)创建对象,传递的参数会被初始化方法init接收。

直接这样装饰,没有定义init方法,运行看下结果:

代码语言:javascript复制


def single(cls):
    instance={}


    def fun(*args,**kwargs):
        if cls in instance:
            return instance[cls]
        else:
            instance[cls]=cls(*args,**kwargs)
            return instance[cls]
    return fun


@single
class Test:
    pass

# t1=Test()



# @single
# class MyTest:
#     pass



#类实现装饰器

class Decorator:#通过这个类实现装饰器
  def __call__(self, *args, **kwargs):
      print("这个是装饰器里面的功能")





@Decorator#通过这个类Decorator实现装饰器。艾特下这个类,等于在这里做了这个事情:
# test_01=Decorator(test_01)这句代码中Decorator(test_01)是通过这个Decorator类创建了个对象,然后
#让test_01()这个函数接收了。
def test_01():
    print('----原来的功能函数----')

test_01()#调用这个函数,实际上是拿着一个对象在调用,不是调用test_01()函数,
# 也不是调用Decorator类。这个对象是Decorator类创建出来的。
#如果一个类的对象,要想被调用的话,应该定义一个call方法。


报错了。所以需要定义一个init方法:

代码语言:javascript复制


def single(cls):
    instance={}


    def fun(*args,**kwargs):
        if cls in instance:
            return instance[cls]
        else:
            instance[cls]=cls(*args,**kwargs)
            return instance[cls]
    return fun


@single
class Test:
    pass

# t1=Test()



# @single
# class MyTest:
#     pass



#类实现装饰器

class Decorator:#通过这个类实现装饰器
  def __init__(self,func):#init方法需要接收一个参数func,接收的就是被装饰的函数
      pass
  def __call__(self, *args, **kwargs):
      print("这个是装饰器里面的功能")





@Decorator#通过这个类Decorator实现装饰器。艾特下这个类,等于在这里做了这个事情:
# test_01=Decorator(test_01)这句代码中Decorator(test_01)是通过这个Decorator类创建了个对象,然后
#让test_01()这个函数接收了。
def test_01():
    print('----原来的功能函数----')

test_01()#调用这个函数,实际上是拿着一个对象在调用,不是调用test_01()函数,
# 也不是调用Decorator类。这个对象是Decorator类创建出来的。
#如果一个类的对象,要想被调用的话,应该定义一个call方法。

Decorator(test_01)这里创建对象的时候传了个参数,这个参数被func接收了。

test_01()调用这个对象的时候,这个方法:

代码语言:javascript复制

  def __call__(self, *args, **kwargs):
      print("这个是装饰器里面的功能")

其实就是相当于这个装饰器函数了:

代码语言:javascript复制

    def fun(*args,**kwargs):
        if cls in instance:
            return instance[cls]
        else:
            instance[cls]=cls(*args,**kwargs)
            return instance[cls]

做了装饰器要做的事情后,想要调用原来的功能函数,还需要调用这个func,那么这个func在函数下面怎么访问的到呢?

想办法把func保存到实例属性里面。通过self.func=func保存到实例属性里面。直接self.func()就能够拿到了。

这个函数已经完全放到装饰器里面来执行了:

代码语言:javascript复制


def single(cls):
    instance={}


    def fun(*args,**kwargs):
        if cls in instance:
            return instance[cls]
        else:
            instance[cls]=cls(*args,**kwargs)
            return instance[cls]
    return fun


@single
class Test:
    pass

# t1=Test()



# @single
# class MyTest:
#     pass



#类实现装饰器

class Decorator:#通过这个类实现装饰器
  def __init__(self,func):#init方法需要接收一个参数func,接收的就是被装饰的函数
      self.func = func
  def __call__(self, *args, **kwargs):
      print("这个是装饰器里面的功能")
      self.func()
      print('--装饰器--功能2--')


@Decorator#通过这个类Decorator实现装饰器。艾特下这个类,等于在这里做了这个事情:
# test_01=Decorator(test_01)这句代码中Decorator(test_01)是通过这个Decorator类创建了个对象,然后
#让test_01()这个函数接收了。
def test_01():
    print('----原来的功能函数----')

test_01()#调用这个函数,实际上是拿着一个对象在调用,不是调用test_01()函数,
# 也不是调用Decorator类。这个对象是Decorator类创建出来的。
#如果一个类的对象,要想被调用的话,应该定义一个call方法。

二、请描述__new__、__str__、__repr__、__call__分别在什么情况下会被触发?

__new__:调用一个类去创建实例对象的时候,实例对象是__new__出来的。创建出来实例对象,再交给__init__做初始化。

如果__new__方法没有创建出来实例对象,__init__没有对象就没办法做初始化了。

__str__:print打印的时候会触发。format处理一个对象,也会被触发。通过__str__这个内置函数去转换一个对象的时候,也会触发__str__这个方法。

__repr__:在交互环境下直接输入这个repr(对象),也会触发__repr__方法。通过__repr__这个内置函数去处理,也会触发这个方法。

__call__:一个对象被调用的时候,它才会被触发这个__call__方法。

三、总结

首先分清四个方法的用法,接下来写平台一定会用到这些所学的知识。

Jmeter、网络基础、计算机原理、Linux、Mysql的深入学习,文章正在持续缓慢得更新中,想成为一名技术扎实的测试不容易。持续学习,肯钻研,放弃无效社交,不浪费时间很重要。


除标明“图片来自网络”的图片,其它文章中的图片皆为本人所画,计算机知识都一样,如有雷同,纯属巧合。

0 人点赞