天天看點

python裝飾器作用和功能_如何了解Python裝飾器?

晚上失眠,怒上知乎答題!

剛好最近我的python專欄裡寫過一篇裝飾器相關的,不說廢話,直接上幹貨!

目錄如下:1、裝飾器是什麼?

2、如何使用裝飾器?

3、内置裝飾器

一、裝飾器是什麼?

裝飾器,顧名思義,就是增強函數或類的功能的一個函數。

這麼說可能有點繞。

舉個例子:如何計算函數的執行時間?

如下,你需要計算 add 函數的執行時間。​​​​​​​

# 函數

def add(a, b):

res = a + b

return res

你可能會這麼寫​​​​​​​

import time

def add(a, b)

start_time = time.time()

res = a + b

exec_time = time.time() - start_time

print("add函數,花費的時間是:{}".format(exec_time))

return res

這個時候,老闆又讓你計算減法函數(sub)的時間。不用裝飾器的話,你又得重複寫一段減法的代碼。

def sub(a, b)

start_time = time.time()

res = a - b

exec_time = time.time() - start_time

print("sub函數,花費的時間是:{}".format(exec_time))

return res

這樣顯得很麻煩,也不靈活,萬一計算時間的代碼有改動,你得每個函數都要改動。

是以,我們需要引入裝飾器。

使用裝飾器之後的代碼是這樣的

import time

# 定義裝飾器

def time_calc(func):

def wrapper(*args, **kargs):

start_time = time.time()

f = func(*args,**kargs)

exec_time = time.time() - start_time

return f

return wrapper

# 使用裝飾器

@time_calc

def add(a, b):

return a + b

@time_calc

def sub(a, b):

return a - b

是不是看起來清爽多了?

裝飾器的作用:增強函數的功能,确切的說,可以裝飾函數,也可以裝飾類。

裝飾器的原理:函數是python的一等公民,函數也是對象。

定義裝飾器

def decorator(func):

def wrapper(*args,**kargs):

# 可以自定義傳入的參數

print(func.__name__)

# 傳回傳入的方法名參數的調用

return func(*args,**kargs)

# 傳回内層函數函數名

return wrapper

二、使用裝飾器

假設decorator是定義好的裝飾器。

方法一:不用文法糖@符号​​​​​​​

# 裝飾器不傳入參數時

f = decorator(函數名)

# 裝飾器傳入參數時

f = (decorator(參數))(函數名)

方法二:采用文法糖@符号​​​​​​​

# 已定義的裝飾器

@decorator

def f():

pass

# 執行被裝飾過的函數

f()

裝飾器可以傳參,也可以不用傳參。

自身不傳入參數的裝飾器(采用兩層函數定義裝飾器)

def login(func):

def wrapper(*args,**kargs):

print('函數名:%s'% func.__name__)

return func(*args,**kargs)

return wrapper

@login

def f():

print('inside decorator!')

f()

# 輸出:

# >> 函數名:f

# >> 函數本身:inside decorator!

自身傳入參數的裝飾器(采用三層函數定義裝飾器)

def login(text):

def decorator(func):

def wrapper(*args,**kargs):

print('%s----%s'%(text, func.__name__))

return func(*args,**kargs)

return wrapper

return decorator

# 等價于 ==> (login(text))(f) ==> 傳回 wrapper

@login('this is a parameter of decorator')

def f():

print('2019-06-13')

# 等價于 ==> (login(text))(f)() ==> 調用 wrapper() 并傳回 f()

f()

# 輸出:

# => this is a parameter of decorator----f

# => 2019-06-13

三、内置裝飾器

常見的内置裝飾器有三種,@property、@staticmethod、@classmethod

@property

把類内方法當成屬性來使用,必須要有傳回值,相當于getter;

假如沒有定義 @func.setter 修飾方法的話,就是隻讀屬性

class Car:

def __init__(self, name, price):

self._name = name

self._price = price

@property

def car_name(self):

return self._name

# car_name可以讀寫的屬性

@car_name.setter

def car_name(self, value):

self._name = value

# car_price是隻讀屬性

@property

def car_price(self):

return str(self._price) + '萬'

benz = Car('benz', 30)

print(benz.car_name) # benz

benz.car_name = "baojun"

print(benz.car_name) # baojun

print(benz.car_price) # 30萬

@staticmethod

靜态方法,不需要表示自身對象的self和自身類的cls參數,就跟使用函數一樣。

@classmethod

類方法,不需要self參數,但第一個參數需要是表示自身類的cls參數。

例子

class Demo(object):

text = "三種方法的比較"

def instance_method(self):

print("調用執行個體方法")

@classmethod

def class_method(cls):

print("調用類方法")

print("在類方法中 通路類屬性 text: {}".format(cls.text))

print("在類方法中 調用執行個體方法 instance_method: {}".format(cls().instance_method()))

@staticmethod

def static_method():

print("調用靜态方法")

print("在靜态方法中 通路類屬性 text: {}".format(Demo.text))

print("在靜态方法中 調用執行個體方法 instance_method: {}".format(Demo().instance_method()))

if __name__ == "__main__":

# 執行個體化對象

d = Demo()

# 對象可以通路 執行個體方法、類方法、靜态方法

# 通過對象通路text屬性

print(d.text)

# 通過對象調用執行個體方法

d.instance_method()

# 通過對象調用類方法

d.class_method()

# 通過對象調用靜态方法

d.static_method()

# 類可以通路類方法、靜态方法

# 通過類通路text屬性

print(Demo.text)

# 通過類調用類方法

Demo.class_method()

# 通過類調用靜态方法

Demo.static_method()

@staticmethod 和 @classmethod 的 差別 和 使用場景:

在上述例子中,我們可以看出,

差別

在定義靜态類方法和類方法時,@staticmethod 裝飾的靜态方法裡面,想要通路類屬性或調用執行個體方法,必須需要把類名寫上;

而@classmethod裝飾的類方法裡面,會傳一個cls參數,代表本類,這樣就能夠避免手寫類名的寫死。

在調用靜态方法和類方法時,實際上寫法都差不多,一般都是通過 類名.靜态方法() 或 類名.類方法()。

也可以用執行個體化對象去調用靜态方法和類方法,但為了和執行個體方法區分,最好還是用類去調用靜态方法和類方法。

使用場景

是以,在定義類的時候,

假如不需要用到與類相關的屬性或方法時,就用靜态方法@staticmethod;

假如需要用到與類相關的屬性或方法,然後又想表明這個方法是整個類通用的,而不是對象特異的,就可以使用類方法@classmethod。

希望看到這個回答的朋友,永遠不要失眠~

另外還有一些之前在github上總結的:測試開發面試資源、複習資料彙總

最後,歡迎加入【程式員知乎交流圈】↓↓↓程式員交流圈 - 知乎​www.zhihu.com

python裝飾器作用和功能_如何了解Python裝飾器?

置頂帖我放了頭條内推連結,歡迎投遞~(北京上海深圳廣州杭州成都武漢都在招)