Python类里面的装饰器

296 阅读4分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

装饰器:

原因:python是一个动态语言,因为一切都是对象。是一个脚本语言。

第一个:

首先咱再看遍闭包是啥:
#闭包

def fun1():
    print('fun1')
    def fun2():
        print('fun2')
    return fun2

#fun1()() ===>  fun2()
a = fun1()
a()           #会执行两个函数

然后,咱稍微高级点,看看闭包参数。这种方法比较麻烦,所以下面就引入了装饰器,和这个的功能一模一样,不过简单了许多:

#闭包里面有参数 回调函数

def aa(fun):                         #fun = f1
    print('------------aa')
    def bb():
        fun()                         #fun()   =  f1()
        print('----------bb')
    return bb

def f1():
    print('this is f1')

def f2():
    print('this is f2')

cc = aa(f1)
cc()                 #输出为     ------------aa
                                                                 this is f1
                                                                 ----------bb

最后,就来看看第一种装饰器:

#装饰器 在不改变原有函数的基础上面增加额外的功能
#装饰器

def aa(fun):                         #fun = f1
    print('------------aa')
    def bb():
        fun()                         #fun()   =  f1()
        print('----------bb')
    return bb

#装饰器 被装饰的函数名字(f1)会被当做参数传递给装饰函数(aa)
#代码就是: aa(f1)
#装饰函数(aa)执行完它自己内部的代码之后,会把它的结果返回给
#被装饰的函数(f1)
#代码就是: f1 = aa(f1)
#然后下面又是f1() 就相当于 aa(f1)()

@aa # 就相当于 f1 = aa(f1) 要使用嵌套函数里面的内容 aa(f1)(),就是最后调用的时候f1加个括号
# 而注意函数外部的只要用到装饰器就会执行,而嵌套的内层函数需要调用才会执行,所以
# 用处就是把重要的东西写到嵌套的内层函数,在调用的时候才会执行

def f1():
    print('this is f1')

def f2():
    print('this is f2')

f1()           #输出和上面一个一模一样

第二个:

#类里面的内置装饰器
引入:

class Base:

    def fun(self):
        print('好好学习,天天向上')

b = Base()
b.fun()            # 调用类里面的方法,就会执行类里面的方法fun,打印 好好学习,天天向上

第一个是把类里面的方法变为属性:

class Base:
    name = '寒沙'

    @property         #将方法变为属性  更加简洁
    def fun(self):
        return('好好学习,天天向上')


b = Base()
print(b.name)          #属性的使用不需要加括号;方法的使用才要加括号
print(b.fun)          #现在类里面的方法fun就变成了类的属性
#输出为:
                寒沙
                好好学习,天天向上

第二个是把类里面的方法变为静态方法,让其可以像使用函数一样去使用,而不需要再实例化才能使用:

class Base:

    @staticmethod       #静态方法  方法能够像函数一样的去使用, 比如在类里面,你要写一些闭包什么的就可以在这里面写,相当于扩展了一些功能。
    def fun2():              # 注意:这里已经不需要self   和class类断开联系
        print('过年好,新年好')

    #再来个不加装饰器的
    def func(self):
        print('这是普通方法')

Base.fun2()     # fun2已经变为静态方法,可以像使用函数一样的使用
# 输出为:  过年好,新年好

Base是类名;Base() 就是实例化
Base().func()      # 而没有使用装饰器的方法就需要先实例化,才能去使用
# 输出为:这是普通方法

第三个是类方法

class Base:

    def func(self):
        print('这是普通方法')

    @classmethod
    def fun3(cls):        #没有self   和实例无关,这是类方法  ;   有self的是实例方法,需要先实例化才能使用
        print('cls类方法')
        cls().func()      #cls 代表类本身,即Base这个类

# 类方法的使用,也不用实例化 直接类名点方法
Base.fun3()

第三个:\

类装饰器 必须使用__call__方法

class Base:

    def __init__(self,name):
        self.name = name

    def __call__(self,*args,**kwargs):
        print('this is call')

@Base      # func = Base(func)     被装饰函数(func)当做参数传递给装饰函数(Base)
def func():
    print('this is func')

func()     # 此处的括号就相当于 func() = Base(func)()
           # __call__方法只要实例化就会被调用
#输出为:   this is call

看看高级点的:

class Base:

    def __init__(self,fun):
        self.fun = fun

    def __call__(self,*args,**kwargs):
        self.fun()         #就会打印    this is func
        print('this is call')

    def __str__(self):
        return 'this is str'

@Base      # func = Base(func)  相当于实例化   被装饰函数(func)当做参数传递给装饰函数(Base)
def func():
    print('this is func')

func()     # 此处的括号就相当于 func() = Base(func)()
           # __call__方法只要实例化就会被调用
print(func)        # 打印类的实例,就会调用类里面的__str__方法

#输出为:
this is func
this is call
this is str

拓展一下呗:::
来个装饰器的习题:
测试type和isinstance两个函数,那个速度更加的快\

程序运行速度比较快 只查看上面两个\

函数 运行一次的时间显示不出来效果
可以查看循环一万次的时间

#time.time()  计算目前的时间  时间戳(格林威治时间, 1970.1.1到现在的总秒数)
import time

def funa(fun):
    def funb():
        a = time.time()
        fun()
        b = time.time()
        print('函数运行了%s'%(b-a))
    return funb

@funa
def f1():
    for i in range(100000):
        type(1)
f1()
@funa
def f2():
    for i in range(100000):
         isinstance(1,int)
f2()