精品专区-精品自拍9-精品自拍三级乱伦-精品自拍视频-精品自拍视频曝光-精品自拍小视频

網站建設資訊

NEWS

網站建設資訊

Python中怎么利用類實現一個裝飾器-創新互聯

Python中怎么利用類實現一個裝飾器,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

成都創新互聯服務項目包括寶塔網站建設、寶塔網站制作、寶塔網頁制作以及寶塔網絡營銷策劃等。多年來,我們專注于互聯網行業,利用自身積累的技術優勢、行業經驗、深度合作伙伴關系等,向廣大中小型企業、政府機構等提供互聯網行業的解決方案,寶塔網站推廣取得了明顯的社會效益與經濟效益。目前,我們服務的客戶以成都為中心已經輻射到寶塔省份的部分城市,未來相信會繼續擴大服務區域并繼續獲得客戶的支持與信任!

1、用類寫裝飾器

下面用常見的寫法實現了一個緩存裝飾器。

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是一個語法糖,相當于func = cache(func),如果這里的cache不是一個函數,而是一個類又會怎樣呢?定義一個類class Cache, 那么調用func = Cache(func)會得到一個對象,這時返回的func其實是Cache的對象。定義__call__方法可以將類的實例變成可調用對象,可以像調用函數一樣調用對象。然后在__call__方法里調用原本的func函數就能實現裝飾器了。所以Cache類也能當作裝飾器使用,并且能以@Cache的形式使用。

接下來把cache函數改寫為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

再看看緩存結果,效果一樣。

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

2、裝飾類的方法

裝飾器不止能裝飾函數,也經常用來裝飾類的方法,但是我發現用類寫的裝飾器不能直接用在裝飾類的方法上。(有點繞…)

先看看函數寫的裝飾器如何裝飾類的方法。

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類會報錯,這個錯誤的原因是area被裝飾后變成了類的一個屬性,而不是方法。

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>

回頭再來看看沒有裝飾器的情況,Python在實例化對象后把函數變成了方法。

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

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

Rectangle.area
# 
r = Rectangle(2, 3)
r.area
# 

因此解決辦法很簡單,要用類寫的裝飾器來裝飾類的方法,只需要把可調用對象包裝成函數就行。

# 定義一個簡單的裝飾器,什么也不做,僅僅是把可調用對象包裝成函數
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

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注創新互聯行業資訊頻道,感謝您對創新互聯的支持。


新聞標題:Python中怎么利用類實現一個裝飾器-創新互聯
文章地址:http://m.jcarcd.cn/article/cesshp.html
主站蜘蛛池模板: 91综合在线 | 国产精品亚洲αv | 韩日一区二区三区 | 强伦中文字幕在线 | 日韩中文字幕a加勒 | 精品日韩成人欧美 | 精品日本亚洲专区 | 午夜一区二区免费看 | 欧美中文字幕 | 成人高清网站 | 天美传媒 | 人人揉揉揉揉揉日日 | 91青青青 | 成人动漫视频在线 | 国产亚洲精品福利片 | 欧美日韩欧美 | 国产一区在线视频 | 国产亚洲精品综 | 青青草精品在线视 | 国产迷姦播 | 日韩一本之道一 | 国产午夜福利精品一 | 成人一级免费激情网 | 日本在线不卡视频 | 国产精品自在拍 | 国产欧美一区二区 | 日产a一a区二区 | 日韩大乳免费视频 | 成人午夜在线视频 | 精品欧美一区二区视 | 精品国产一区二区 | 成人激情视频在线 | 国产福利在线观看永 | 国产女主播在线观看 | 日本天堂视 | aⅴ人片女在线观看 | 成人午夜在线小视频 | 国产精品第八页 | 国产欧美精品国产 | 福利在线91 | 日本高清精品一区 |