三分鐘搞定Python中的裝飾器

2022-08-19 18:24:13 字數 2863 閱讀 6013

python的裝飾器是python的特色高階功能之一,言簡意賅得說,其作用是在不改變其原有函式和類的定義的基礎上,給他們增添新的功能。

裝飾器存在的意義是什麼呢?我們知道,在python中函式可以呼叫,類可以繼承,為何要必須保證不改變函式和類的定義,就使得函式有了新的功能呢?其實很好解釋。

提高**的簡潔程度與封裝性。如果你採用新宣告乙個函式,並呼叫原來函式的思路使得原函式功能增加了,但是一方面使用起來看著不簡潔, 另一方面當另乙個程式設計師使用你的**時再使用這樣的思路,那**巢狀無窮無盡,會讓**變得很亂,說不定改錯了**,動了原函式哪個引數,就會出現發現不了的bug。

我們先來看乙個簡單的例子。

def addworld(func):

def addfun():

return func() + 'world'

return addfun()

@addworld

def printhello():

return 'hello'

print(printhello)

這段**最後執行出來的結果是helloworld。我們發現,只要在原函式頭上加乙個你定義好了的增添功能的模板,以後凡是加上這個,都會增添乙個功能,這提高了開發效率,也看著更加簡潔。

def addnum(func):

def addfun(*args, **kwargs):

ret = func(*args, **kwargs)*2

return ret

return addfun

@addnum

def printsum(a, b):

return (a+b)

i = printsum(7, 7)

print(i)

這是有引數的情況下,裝飾器的使用效果,輸出結果為28。

def addnum1(c):

def addnum(func):

def addfun(*args, **kwargs):

ret = func(*args, **kwargs)*2*c

return ret

return addfun

return addnum

@addnum1(5)

def printsum(a, b):

return (a+b)

i = printsum(7, 7)

print(i)

裝飾器本身也是可以傳參的,在這個程式中,傳入了乙個常數5,最後得出的結果是140。

接下來,我們介紹幾個常用的python內建裝飾器。

property

在繫結屬性時,如果我們直接把屬性暴露出去,雖然寫起來很簡單,但是,沒辦法檢查引數,導致可以把成績隨便改。這樣顯然是不行的,那麼在函式中,我們往往如何提高程式的魯棒性呢?

class student(object):

def get_score(self):

return self._score

def set_score(self, value):

if not isinstance(value, int):

raise valueerror('score must be an integer!')

if value < 0 or value > 100:

raise valueerror('score must between 0 ~ 100!')

self._score = value

s = student()

s.set_score(60)

value = s.get_score()

print(value)

通過呼叫類中的函式從而進一步操作屬性,這樣雖然安全正確卻未免看著複雜,不貼近人類自然的屬性表現。

class student(object):

@property

def score(self):

return self._score

@score.setter

def score(self, value):

if not isinstance(value, int):

raise valueerror('score must be an integer!')

if value < 0 or value > 100:

raise valueerror('score must between 0 ~ 100!')

self._score = value

s = student()

s.score = 80

print(s.score)

而加上乙個@property就可以輕鬆解決這個問題,是不是很奇妙?把乙個getter方法變成屬性,只需要加上@property就可以了,此時,@property本身又建立了另乙個裝飾器@score.setter,負責把乙個setter方法變成屬性賦值,於是,我們就擁有乙個可控的屬性操作。

還可以定義唯讀屬性,只定義getter方法,不定義setter方法就是乙個唯讀屬性。

class student(object):

@property

def birth(self):

return self._birth

@birth.setter

def birth(self, value):

self._birth = value

@property

def age(self):

return 2014 - self._birth

上面的birth是可讀寫屬性,而age就是乙個唯讀屬性,因為age可以根據birth和當前時間計算出來。

本文**於

三分鐘搞定python基礎

庫的匯入和新增 在機器學習和人工智慧為主導的工業4.0時代,python猶如一股龍捲風襲捲著一切。python作為一門解釋性的物件導向的語言雖然在運算速度上有不足,但是相比於程式運算速度,程式專案開發速度更為重要,而且在在這個裝備氪金時代,運算速度的缺憾完全可以拿硬體來補,何況python還支援並行...

三分鐘搞定JS繼承

基本思想 通過改變prototype的指向形成例項和原型之間的原型鏈 instancesub subtype.prototype instancesuper supertype.prototype object.prototype null 子物件的原型是父物件的例項subtype.prototyp...

沉默三分鐘

網上見此真情之文,藉以自表 原文 http www.hecaitou.net p 3018 沉默三分鐘是心祭。那麼多年了,國旗終於為平民而降。那麼多天了,全民哀悼終於實現。與此同時,火炬停止傳遞,因為這不是乙個歡慶的時刻。很多年後回顧2008年,我 也許寧可它從日曆中消失。還沒有哪一年和今年一樣,才...