裝飾器之類裝飾器
外部的方法至今都玩過了,現在來思索一下的方法這麼裝飾
類方法修飾器
類的方法唯一的特殊點在於,self內部是可以呼叫的,但是在外部卻是隱藏的,那這個怎麼搞
為求穩妥,先定參修飾一個
實驗過的我不敘述了,但是發現這麼一點def godme(fun): def __godme(self,message): print('before') fun(self,message) print('after') return __godme class Person: def show(self,message): print(message) @godme def say(self,message): print(message) person = Person() person.say('happy') ''' before happy after '''
類當中的方法和普通方法一樣,使用方法一樣,只有物件進行呼叫的時候,第一個引數會預設吧物件例項傳入,然後隱匿
這個相當於__call__和__new__一類的東西吧,同樣的,四則運算在類內部也有對應的方法實現,但是外部符號就可以呼叫
所以修飾類的self不可以省略,外部定義時和內部定義沒有區別,但是物件呼叫會自動隱藏
思考:self都能傳入的話,我是不是能做點什麼?
在外部傳入的 self,也可以呼叫類內部方法,不過就像物件能夠自動填充self一樣,self表示物件例項def godme(fun): def __godme(self,message): self.show('sunny') print('before') fun(self,message) print('after') return __godme class Person: def show(self,message): print(message) @godme def say(self,message): print(message) person = Person() person.say('happy') ''' sunny before happy after '''
物件例項呼叫類內部方法時會自動填充self,並隱藏該引數
那麼,顯式的宣告self之後,其餘的不就隨便定義成收容所了麼,畢竟類內部方法有這麼一個必須存在self入參的這個硬性規定
這就實現了類方法適配修飾器的編寫def godme(fun): def __godme(self,*args,**kwargs): self.show('sunny') print('before') fun(self,*args,**kwargs) print('after') return __godme class Person: def show(self,message): print(message) @godme def say(self,message): print(message) person = Person() person.say('happy') ''' sunny before happy after '''
類修飾器
類同樣可以加上括號進行方法呼叫,也就是說,類也可以看做是一個方法,那麼,為什麼不能進行修飾呢?
def godme(fun):
def __godme(cls,*args,**kwargs):
print('before')
fun(cls,*args,**kwargs)
print('after')
return __godme
@godme
class Person:
def __new__(cls, *args, **kwargs):
print('__new__')
Person(Person)
列印結果before
__new__
after
發現其實除了類函式首個引數必須傳入也沒發現啥不同,類也是就是一個擁有更多複雜動態的方法而已
此外,我們可以真切的感受到了裝飾器自帶的一種深深的惡意了,這是它的優點也恰恰是它致命的弱點,造福也蘊含極大的破壞能力
功能替換:它並沒有讓我們的方法更加的多樣化,而只是把我們原有的功能作為一部分新增進入了一個新的方法裡面,然後返回給原方法的方法名
不過到底要不要新增進入返回的方法裡面,甚至是返不返回一個值,什麼值,這都是具有十足破壞力的
一個簡單的記號,可以輕易的增添功能而不改動原有程式碼,同時,一個簡單的符號也可以徹底摧毀整個程式碼架構
def godme(fun):
def __godme(*args,**kwargs):
print('there are no function')
return __godme
@godme
def test():
print('test')
test() #there are no function
可怕的東西,不過現在除了弄亂自己程式碼這種沒有作用的例項,還沒有接觸到可以造成深遠破壞的程式碼
說到了替換,而且剛好是類名方法呼叫,和建立物件就有些許的關聯了,那不防來個單例裝飾器
def single(fun):
def __single():
return hasattr(fun,'single') and getattr(fun,'single') or setattr(fun,'single',fun()) or getattr(fun,'single')
return __single
@single
class Person:
pass
p1 = Person()
p2 = Person()
print(p1) #<__main__.Person object at 0x02B525D0>
print(p2) #<__main__.Person object at 0x02B525D0>
print(p1 is p2) #True
在這個實現方法裡面,我們仍然是呼叫了它本身的物件生成方法
我們也可以直接外部建立一個字典,當字典中沒有指定類作為的key,就建立物件,並返回
同時在字典內部吧類名作為key,物件作為value,下次呼叫直接查詢,找不到就新增,找到直接返回
這種實現方法,網上有很多
至此,關於裝飾器的各種變種和內涵技巧都講述完畢,有疑問請參考前面幾篇文章,謝謝