Python 基礎之面向對象之八步理解裝飾器

裝飾器:在不改變原有代碼的狀況下,爲該原函數擴展新功能
特徵:返回新函數,替換舊函數
語法:@ 語法糖app

1.裝飾器原型

#1:函數

def kuozhan(func):
    def newfunc():
        print("吃飯前,無精打彩")
        func()
        print("吃飯後,精神百倍")
    return newfunc
def func():
    print("我是個吃貨")
#手動的 把新函數 賦值 舊函數
func = kuozhan(func)
func()spa

2.裝飾器 @

#2:orm

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.帶有參數的裝飾器

原函數在擴展以前是幾個參數,那麼擴展以後也相應有幾個參數it

#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","食堂")form

 

5.帶有參數返回值的裝飾器

'''經過裝飾器改造以後,原函數返回什麼,新函數返回什麼'''
print("=================")
#5:class

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 = 19def func(cls):    cls.b = 20    return clsobj2 = func(abc)print(abc().a)abc = 68970print(abc)print(obj2.b)print(obj2.a)

相關文章
相關標籤/搜索