• Python 基础之面向对象之八步理解装饰器


    装饰器:在不改变原有代码的情况下,为该原函数扩展新功能
    特征:返回新函数,替换旧函数
    语法:@ 语法糖

    1.装饰器原型

    #1:

    def kuozhan(func):
        def newfunc():
            print("吃饭前,无精打采")
            func()
            print("吃饭后,精神百倍")
        return newfunc
    def func():
        print("我是个吃货")
    #手动的 把新函数 赋值 旧函数
    func = kuozhan(func)
    func()

    2.装饰器 @

    #2:

    print("=====2=====")
    def kuozhan(func):
        def newfunc():
            print("吃饭前,无精打采")
            func()
            print("吃饭后,精神百倍")
        return newfunc
    @kuozhan
    def func():
        print("我是个吃货")
    func()
    print("=================")
    步骤解析:
    第一步:先把下面的func当成参数传递给kuozhan
    第二步:把返回的新函数重新赋值给func
    * 谁跟在@ 这个装饰器的下面,就会自动把谁当成参数传递
    func = kuozhan(func)

    3.互相嵌套的装饰器函数

    #3:
    def kuozhan1(func):
        def newfunc():
            print("吃饭前前,化化妆1")
            func()
            print("吃饭后,补补妆2")
        return newfunc
    def kuozhan2(func):
        def newfunc():
            print("吃饭前,洗洗手3")
            func()
            print("吃饭后,簌簌口4")
        return newfunc
    @kuozhan2
    @kuozhan1
    def func():
        print("我是一个白富美5")
    func()  #3 1 5 2 4

    4.带有参数的装饰器

    原函数在扩展之前是几个参数,那么扩展之后也相应有几个参数

    #4:
    def kuozhan(func):
        def newfunc(who,where):
            print("开饭前,安安静静")
            func(who,where)
            print("开饭后,热热闹闹")
        return newfunc

    @kuozhan
    def func(who,where):
        print("{}进{}吃饭".format(who,where))

    func("one","食堂")

     

    5.带有参数返回值的装饰器

    '''通过装饰器改造之后,原函数返回什么,新函数返回什么'''
    print("=================")
    #5:

    def kuozhan(func):
        def newfunc(*args, **kwargs):
            print("留下之前")
            res = func(*args, **kwargs)
            print("留下之后")
            return res

        return newfunc

    @kuozhan
    def func(*args, **kwargs):
        print(args)
        for i in args:
            print("藏东西的地点:", i)
        dic = {'p1': "one", "p2": "two"}
        '''

    #法一:for循环再将元素加入列表得到:
        lst = []
        for k,v in dic.items():
            #如果k在dic这个字典里,说明这个字典存在这个键,然后我就通过键取值
            if k in dic:
            lst.append("{}留下了黄金{}".format(dic[k],v))

        '''

    #法二:推导式方法得出:
        lst = ["{}留下了黄金{}".format(dic[k], v) for k, v in kwargs.items() if k in dic]
        return lst
    res = func("电影院", "游泳池", p1="15克", p2="150克")
    print("=================")
    print(res)
    print("=================")

    回忆以前的知识点:
    *  ** 的魔术方法(函数调用处)
    #:

    def func(a,b,c):
        print(a,b,c)

    func(*[1,2,3])

    def func(a=1,b=2,c=3,*,d=4):
        print(a,b,c)

    func(**{"a":3,"b":4,"c":5,"d":6})

    6.用装饰器修饰原函数

    #6:

    class MyClass():

        def __call__(self,func):
            #pass
            return self.kuozhan2(func)
        def kuozhan1(func):
            def newfunc():
                print("酒店前,饥肠辘辘")
                func()
                print("酒店后,酒足饭饱")
            return newfunc
        def kuozhan2(self,func):
            def newfunc():
                print("酒店前,茶饭不思")
                func()
                print("酒店后,大肚偏偏")
            return newfunc
    #方法一
    @MyClass.kuozhan1
    def func():
        print("吃饭进行时...  ....")
    func()
    #方法二:
    @MyClass()
    def func():
        print("吃饭进行时... ...")
    func()


    #代码解析:
    先把 @ 符号右边的值算出来,在通过 @ 符号把下面的函数当成参数进行传递
    @MyClass() 就相当于 @obj
    func当成参数传递给obj => obj(func)
    obj 当成一个函数再进行调用,自动触发__call__魔术方法
    return newfunc
    func = newfunc
    func() 就相当于 newfunc()

    7.带有参数的函数装饰器

    #7:

    def outer(num):
        def kuozhan(func):
            def newfunc1(self):
                print("人前,老实巴交")
                func(self)
                print("人后,张牙舞爪")

            def newfunc2(self):
                print("人前,衣冠楚楚")
                func(self)
                print("人后,衣冠禽兽")

            if num == 1:
                return newfunc1
            elif num == 2:
                return newfunc2
            elif num == 3:
                return "今天天气好晴朗哦"
        return kuozhan

    class MyClass():
        @outer(1)
        def func1(self):
            print("走一步")
        @outer(2)
        def func2(self):
            print("再走一步")
        @outer(3)
        def func3(self):
            print("换个角度想想")
    print("=================")
    obj = MyClass()
    obj.func1()
    print("=================")
    obj.func2()
    print("=================")
    print(obj.func3)

    #代码解析:
    outer(1)  => 返回kuozhan 函数
    @kuozhan
    func1

    @符号开始发挥作用
    func1当成参数进行传递,传给kuozhan中的func进行接收
    obj.func1 = newfunc1
    obj.func1() <====>newfunc1

    @outer(3) => 返回kuozhan 函数
    @kuozhan
    func3
    @符号开始发挥作用
    func3当成参数进行传递,传给kuozhan中的func进行接收
    obj.func3 = "今天天气好晴朗哦"
    print(该值) [因为函数名可以作为变量使用]

    8.带有参数的类装饰器

    如果传递的参数是1 ,我就为该类,添加成员属性和方法
    如果传递的参数是2,我就把该类当中的run方法变成属性
    #8:
    class KuoZhan():
        ad = "高档餐厅,欢迎您来,欢迎您再来"
        def __init__(self,num):
            self.num = num

        def __call__(self,cls):
            if self.num == 1:
                return self.kuozhan1(cls) #newfunc 返回
            elif self.num == 2:
                return self.kuozhan2(cls)

        def money(self):
            print("收费标准,最低消费每人500")

        def kuozhan1(self,cls):
            def newfunc():
                #添加成员属性
                cls.ad = KuoZhan.ad
                #添加成员方法
                cls.money = KuoZhan.money
                return cls()
            return newfunc
        def kuozhan2(self,cls):
            def newfunc():
                #先判断run方法是否在cls当中
                if "run" in cls.__dict__:
                    #调用一个类中得run方法拿到返回值"亢龙有悔"
                    res = cls.run()
                    #成员属性run从方法变成属性,值替换了
                    cls.run = res #把"亢龙有悔" 进行替换赋值给run成员属性
                return cls()
            return newfunc

    @KuoZhan(1) # @obj = > obj(MyClass)
    class MyClass():
        def run():
            return "亢龙有悔"
    obj = MyClass()
    print(obj.ad)
    obj.money()

    """

    #代码解析:
    KanZhan(1) => obj 自动触发init方法 ,存储num => self.num = num
    @obj
    @符发挥作用把MyClass 当成一个参数传递给obj => obj(MyClass)
    触发__call__ 魔术方法,最后将newfunc进行返回
    MyClass = newfunc 以前是类 现在是函数
    obj = MyClass <========> newfunc()
    obj = cls() #cls() 是一个对象,是以前MyClass 这个类的对象
    """
    @KuoZhan(2)
    class MyClass():
        def run():
            return "亢龙有悔"

    obj = MyClass()
    print(obj.run)
    print("=====================================")
    #外面全局的abc 与函数内部局部的 abc 两者不发生冲突,彼此独立
    class abc():
        a = 19
    def func(cls):
        cls.b = 20
        return cls
    obj2 = func(abc)
    print(abc().a)
    abc = 68970
    print(abc)
    print(obj2.b)
    print(obj2.a)

     

     

  • 相关阅读:
    ntopng网络流量实时监控
    LVS初始使用步骤
    Pycharm快捷方式
    Python之路,Day9, 进程、线程、协程篇
    Python之路,Day7
    Python 之路 Day5
    Python之路,Day6
    Python之路,Day3
    Python之路,Day2
    Python之路,Day1
  • 原文地址:https://www.cnblogs.com/hszstudypy/p/10925623.html
Copyright © 2020-2023  润新知