"""
py裝飾器.py
(functools.wraps(func)裝飾器、functools模塊、@property裝飾器)
裝飾器@(decorator裝飾器 = 高階函數 + 閉包函數)
裝飾器本質上是接受一個函數作爲參數(高階函數行爲),並返回一個函數(閉包函數行爲)。
返回函數即子函數 中定義添加內容後 再返回主函數的參數函數。
從而實現不修改 參數函數的基礎上 在代碼運行期間動態增加功能的方式。
1、#使用:如果裝飾器decorator本身需要傳入參數,那就需要編寫一個返回裝飾器的高階函數(即三層嵌套裝飾器函數)。
2、#使用:functools.wraps(func)裝飾器
#注意:裝飾器裝飾過的函數的原屬性已經改變,因爲裝飾器內部是閉包主函數return返回了子函數。
#解決辦法是 通過給decorator裝飾器主函數內return返回的子函數 加上裝飾器functools.wraps(func) 來糾正被此裝飾器裝飾過的func函數屬性。
3、#深入:import functools
#functools 模塊中主要包含了一些函數裝飾器和便捷的功能函數。
3.1、#使用:@functools.wraps(func)
通過給decorator裝飾器主函數內return返回的子函數 加上裝飾器functools.wraps(func) 來糾正被此裝飾器裝飾過的func函數屬性。
3.2、#使用:functools.partial()用來創建一個偏函數,即把一個函數的某些參數給固定住(即設置默認值),返回一個新函數。
#注意:偏函數實質上是一個 @裝飾器 的原理,即在參數列表裏追加進去 設置默認值的參數。
#如:int2('1000') 實則是運行的 int('1000',base=2)
4、@property(@property裝飾器爲可讀屬性 / 裝飾函數.setter裝飾器爲可寫屬性)
#使用:@property裝飾器 負責把一個方法變成屬性來調用,即:@property裝飾器相當於getter方法可讀屬性。
#注意:@property裝飾器 本身又會創建另一個裝飾器,即:使用:裝飾函數.setter裝飾器 相當於 setter可寫屬性。
"""
################### 裝飾器@(decorator裝飾器 = 高階函數 + 閉包函數)
#裝飾器本質上是接受一個函數作爲參數(高階函數行爲),並返回一個函數(閉包函數行爲)。
#返回函數即子函數 中定義添加內容後 再返回主函數的參數函數。
#從而實現不修改 參數函數的基礎上 在代碼運行期間動態增加功能的方式。
#使用:functools.wraps(func)裝飾器
#注意:裝飾器裝飾過的函數的原屬性已經改變,因爲裝飾器內部是閉包主函數return返回了子函數。
#解決辦法是 通過給decorator裝飾器主函數內return返回的子函數 加上裝飾器functools.wraps(func) 來糾正被此裝飾器裝飾過的func函數屬性。
#深入:import functools 使用:@functools.wraps(func)
#####
#定義一個本身不需要傳入參數的裝飾器 打印日誌的裝飾器decorator
def log(func):
"""接收一個函數作爲參數,稱爲高階函數
返回子函數,稱爲閉包函數"""
def wrapper(*args,**kw):
"""返回主函數的參數函數,從而達到不修改參數函數的基礎上 動態增加print功能"""
print('開始調用函數:%s()' %func.__name__)
"""動態增加print功能後,繼續調用原函數()執行"""
return func(*args,**kw)
return wrapper
"""使用:@decorator放到 func函數定義前,相當於執行了 func=decorator(func),重新賦值定義了一個同名新函數"""
@log
def now():
print('2019/11/08')
now()
"""等同於不添加裝飾器@log情況下的如下表示:"""
#log(now)()
#now=log(now)
#now()
#####
#使用:如果裝飾器decorator本身需要傳入參數,那就需要編寫一個返回裝飾器的高階函數(即三層嵌套裝飾器函數)。
#定義一個本身需要傳入參數的裝飾 打印日誌的裝飾器
def log(who):
def decorator(func):
def wrapper(*args,**kw):
print('%s開始調用函數:%s()' %(who,func.__name__))
return func(*args,**kw)
return wrapper
return decorator
@log('小王')
def now():
print('2019/11/09')
now()
"""等同於不添加#log('小王')的如下表示:"""
#log('小張')(now)()
#now=log('小張')(now)
#now()
#####
#使用:functools.wraps(func)裝飾器
#注意:裝飾器裝飾過的函數的原屬性已經改變,因爲裝飾器內部是閉包主函數return返回了子函數。
#解決辦法是 通過給decorator裝飾器主函數內return返回的子函數 加上裝飾器functools.wraps(func) 來糾正被此裝飾器裝飾過的func函數屬性。
#深入:import functools
#functools 模塊中主要包含了一些函數裝飾器和便捷的功能函數。
#2.1、使用:@functools.wraps(func)
#通過給decorator裝飾器主函數內return返回的子函數 加上裝飾器functools.wraps(func) 來糾正被此裝飾器裝飾過的func函數屬性。
import functools
def log(func):
# @functools.wraps(func)
def wrapper(*args,**kw):
print('開始調用函數:%s()' %func.__name__)
return func(*args,**kw)
return wrapper
@log
def now():
print('2019/11/09')
now()
print(now.__name__)
#對比添加了 @functools.wraps(func) 裝飾器之後的 now.__name__
import functools
def log(who):
def decorator(func):
"""使用:functools.wraps(func)裝飾器
通過給decorator裝飾器主函數內return返回的子函數 加上裝飾器functools.wraps(func)
來糾正被此裝飾器裝飾過的func函數屬性。
"""
@functools.wraps(func)
def wrapper(*args,**kw):
print('%s \n %s開始調用函數:%s' %('接下來使用了functools.wraps(func)技術',who,func.__name__))
return func(*args,**kw)
return wrapper
return decorator
@log('小劉')
def now():
print('2019/11/10')
now()
now.__name__
#################### @property(@property裝飾器爲可讀屬性 / 裝飾函數.setter裝飾器爲可寫屬性)
#使用:@property裝飾器 負責把一個方法變成屬性來調用,即:@property裝飾器相當於getter方法可讀屬性。
#注意:@property裝飾器 本身又會創建另一個裝飾器,即:使用:裝飾函數.setter裝飾器 相當於 setter可寫屬性。
class Student(object):
"""#使用:@property裝飾器 負責把一個方法變成屬性來調用;
即:@property裝飾器相當於getter方法可讀屬性。"""
@property
def score(self):
return self._score
"""#注意:@property裝飾器 本身又會創建另一個裝飾器;
即:使用:@裝飾函數.setter裝飾器 相當於 setter可寫屬性。"""
@score.setter
def score(self,value):
if not isinstance(value,int):
raise ValueError('成績需要是個整數')
if value<0 or value>100:
raise ValueError('成績需要時0~100')
self._score=value
s=Student()
s.score=100
s.score
#當代碼有了@property裝飾器以後,我們就知道屬性很可能不是直接暴露的,而是通過getter方式讀取 和 setter方法寫入的。
#定義只讀屬性,即:只定義@property裝飾器(getter方法),補丁已setter方法。
#定義可讀可寫屬性,即:定義@property裝飾器 及 @裝飾函數.setter裝飾器
#如:
class Student(object):
"""定義可讀可寫的birth屬性"""
@property
def birth(self):
return self.__birth
@birth.setter
def birth(self,value):
self.__birth=value
"""定義只讀屬性(無@裝飾函數.setter裝飾器)"""
@property
def age(self):
return 2015-self.__birth
py裝飾器(functools.wraps(func)裝飾器、functools模塊、@property裝飾器)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.