成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

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

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

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

1、用類寫裝飾器

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

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

接下來把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)常用來裝飾類的方法,但是我發(fā)現(xià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類會報錯,這個錯誤的原因是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在實例化對象后把函數(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

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

# 定義一個簡單的裝飾器,什么也不做,僅僅是把可調(diào)用對象包裝成函數(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)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。

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

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

廣告

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

成都網(wǎng)站建設(shè)公司
巴南区| 顺昌县| 彩票| 弥勒县| 景宁| 娱乐| 玉溪市| 大方县| 文登市| 瑞安市| 漠河县| 都匀市| 耒阳市| 阿克苏市| 香港| 秦安县| 屏南县| 留坝县| 姜堰市| 冕宁县| 布尔津县| 阿拉善右旗| 灵寿县| 曲阜市| 阿坝| 灌南县| 永新县| 阳原县| 左权县| 新河县| 荃湾区| 略阳县| 吉首市| 响水县| 乌鲁木齐市| 子长县| 贺州市| 夏邑县| 通城县| 武邑县| 青海省|