Python中怎么利用類實(shí)現(xiàn)一個(gè)裝飾器-創(chuàng)新互聯(lián)

Python中怎么利用類實(shí)現(xiàn)一個(gè)裝飾器,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

成都創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括寶塔網(wǎng)站建設(shè)、寶塔網(wǎng)站制作、寶塔網(wǎng)頁(yè)制作以及寶塔網(wǎng)絡(luò)營(yíng)銷策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,寶塔網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到寶塔省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

1、用類寫裝飾器

下面用常見的寫法實(shí)現(xiàn)了一個(gè)緩存裝飾器。

def cache(func):
  data = {}
  def wrapper(*args, **kwargs):
    key = f'{func.__name__}-{str(args)}-{str(kwargs)})'
    if key in data:
      result = data.get(key)
      print('cached')
    else:
      result = func(*args, **kwargs)
      data[key] = result
      print('calculated')
    return result
  return wrapper

看看緩存的效果。

@cache
def rectangle_area(length, width):
  return length * width
rectangle_area(2, 3)
# calculated
# 6
rectangle_area(2, 3)
# cached
# 6

裝飾器的@cache是一個(gè)語(yǔ)法糖,相當(dāng)于func = cache(func),如果這里的cache不是一個(gè)函數(shù),而是一個(gè)類又會(huì)怎樣呢?定義一個(gè)類class Cache, 那么調(diào)用func = Cache(func)會(huì)得到一個(gè)對(duì)象,這時(shí)返回的func其實(shí)是Cache的對(duì)象。定義__call__方法可以將類的實(shí)例變成可調(diào)用對(duì)象,可以像調(diào)用函數(shù)一樣調(diào)用對(duì)象。然后在__call__方法里調(diào)用原本的func函數(shù)就能實(shí)現(xiàn)裝飾器了。所以Cache類也能當(dāng)作裝飾器使用,并且能以@Cache的形式使用。

接下來(lái)把cache函數(shù)改寫為Cache類:

class Cache:
  def __init__(self, func):
    self.func = func
    self.data = {}
  def __call__(self, *args, **kwargs):
    func = self.func
    data = self.data
    key = f'{func.__name__}-{str(args)}-{str(kwargs)})'
    if key in data:
      result = data.get(key)
      print('cached')
    else:
      result = func(*args, **kwargs)
      data[key] = result
      print('calculated')
    return result

再看看緩存結(jié)果,效果一樣。

@Cache
def rectangle_area(length, width):
  return length * width
rectangle_area(2, 3)
# calculated
# 6
rectangle_area(2, 3)
# cached
# 6

2、裝飾類的方法

裝飾器不止能裝飾函數(shù),也經(jīng)常用來(lái)裝飾類的方法,但是我發(fā)現(xiàn)用類寫的裝飾器不能直接用在裝飾類的方法上。(有點(diǎn)繞…)

先看看函數(shù)寫的裝飾器如何裝飾類的方法。

class Rectangle:
  def __init__(self, length, width):
    self.length = length
    self.width = width
  @cache
  def area(self):
    return self.length * self.width
r = Rectangle(2, 3)
r.area()
# calculated
# 6
r.area()
# cached
# 6

但是如果直接換成Cache類會(huì)報(bào)錯(cuò),這個(gè)錯(cuò)誤的原因是area被裝飾后變成了類的一個(gè)屬性,而不是方法。

class Rectangle:
  def __init__(self, length, width):
    self.length = length
    self.width = width
  @Cache
  def area(self):
    return self.length * self.width
r = Rectangle(2, 3)
r.area()
# TypeError: area() missing 1 required positional argument: 'self'
Rectangle.area
# <__main__.Cache object at 0x0000012D8E7A6D30>
r.area
# <__main__.Cache object at 0x0000012D8E7A6D30>

回頭再來(lái)看看沒(méi)有裝飾器的情況,Python在實(shí)例化對(duì)象后把函數(shù)變成了方法。

class Rectangle:
  def __init__(self, length, width):
    self.length = length
    self.width = width

  def area(self):
    return self.length * self.width

Rectangle.area
# <function Rectangle.area at 0x0000012D8E7B28C8>
r = Rectangle(2, 3)
r.area
# <bound method Rectangle.area of <__main__.Rectangle object

因此解決辦法很簡(jiǎn)單,要用類寫的裝飾器來(lái)裝飾類的方法,只需要把可調(diào)用對(duì)象包裝成函數(shù)就行。

# 定義一個(gè)簡(jiǎn)單的裝飾器,什么也不做,僅僅是把可調(diào)用對(duì)象包裝成函數(shù)
def method(call):
  def wrapper(*args, **kwargs):
    return call(*args, **kwargs)
  return wrapper
class Rectangle:
  def __init__(self, length, width):
    self.length = length
    self.width = width
  @method
  @Cache
  def area(self):
    return self.length * self.width
r = Rectangle(2, 3)
r.area()
# calculated
# 6
r.area()
# cached
# 6

或者用@property還能直接把方法變成屬性。

class Rectangle:
  def __init__(self, length, width):
    self.length = length
    self.width = width
  @property
  @Cache
  def area(self):
    return self.length * self.width
r = Rectangle(2, 3)
r.area
# calculated
# 6
r.area
# cached
# 6

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。

本文名稱:Python中怎么利用類實(shí)現(xiàn)一個(gè)裝飾器-創(chuàng)新互聯(lián)
分享地址:http://muchs.cn/article48/cesshp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、App開發(fā)移動(dòng)網(wǎng)站建設(shè)、品牌網(wǎng)站制作、微信公眾號(hào)、搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司