最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python類中的裝飾器在當(dāng)前類中的聲明與調(diào)用詳解

 更新時(shí)間:2020年04月15日 09:23:49   作者:天外歸云  
這篇文章主要介紹了Python類中的裝飾器在當(dāng)前類中的聲明與調(diào)用詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧

我的Python環(huán)境:3.7

在Python類里聲明一個(gè)裝飾器,并在這個(gè)類里調(diào)用這個(gè)裝飾器。

代碼如下:

class Test():
  xx = False

  def __init__(self):
    pass

  def test(func):
    def wrapper(self, *args, **kwargs):
      print(self.xx)
      return func(self, *args, **kwargs)
      
    return wrapper

  @test
  def test_a(self,a,b):
    print(f'ok,{a} ')

注意:

1. 其中裝飾器test是在類Test中聲明并在其方法test_a中調(diào)用

2. 裝飾器test內(nèi)層wrapper函數(shù)的首參數(shù)是self

補(bǔ)充知識(shí):python-類內(nèi)函數(shù)的全局裝飾器

有時(shí),比如寫RF的測試庫的時(shí)候,很多方法都寫在一個(gè)類里。我們又可能需要一個(gè)通用的裝飾器,比如,要給某個(gè)底層類的方法打樁,查看入?yún)⒑统鰠?,用以理解業(yè)務(wù);或者要hold住所有的執(zhí)行錯(cuò)誤,打印堆棧又不想程序退出或用例直接失敗

比如捕捉錯(cuò)誤的裝飾器

import traceback
from functools import wraps


def trier(soft=False):
  '''
  :param bool soft: 為True時(shí),打印報(bào)錯(cuò)堆棧并忽略異常。默認(rèn)False,打印報(bào)錯(cuò)堆棧并拋出異常
  :return:
  如果要給類方法、靜態(tài)方法裝飾,則該裝飾器必須處于比@staticmethod裝飾器更內(nèi)一層才行
  '''
  def realTrier(func):
    '''
    :param function func:
    :return:
    '''
    @wraps(func) # 保留__name__ __doc__ __module__
    def innerfunc(*args, **kwargs):
      try:
        return func(*args, **kwargs)
      except Exception, e:
        try:
          print(traceback.format_exc())
        except:
          print e
        if not soft:
          raise
    return innerfunc
  return realTrier


或者參數(shù)跟蹤的裝飾器

def tracer(func):
 def infunc(*args, **kwargs):
 print func.__name__, args, kwargs
 res=infunc(*args, **kwargs)
 print func.__name__, res
 return res

這類裝飾器經(jīng)常會(huì)給類里的每個(gè)函數(shù)都使用

每次都裝飾的話,也挺麻煩

python里可以給類寫個(gè)裝飾器,所以可以輸入一個(gè)類,返回一個(gè)新類,這個(gè)新類擁有原來類里的所有方法,但所有方法都被裝飾

使用元類,可以做到這一點(diǎn)。

目前可以批量裝飾普通方法、靜態(tài)方法、類方法、屬性,暫不支持__init__和__del__之類的特殊方法,以免出現(xiàn)意外的問題。

目前類B使用了全局裝飾器,假如類B繼承自類A,類C繼承自類B

則類B、類C內(nèi)的所有方法都被全局裝飾(全局裝飾可以被繼承)

且類B繼承自類A的所有方法也會(huì)被全局裝飾

但這種裝飾不會(huì)影響到類A,調(diào)用類A下的方法時(shí),所有方法都不被裝飾

經(jīng)過多次嘗試,最后的實(shí)現(xiàn)代碼如下

# clswrapper.py
def skipper(func):
  '''
  :param function func:
  :return:
  '''
  func.__funskip__=True
  return func


def classWrapper(commonDecoratorFunc):
  def innerMata(inClass):
    def collect_attrib(key, value, new_attrs):
      if hasattr(value, '__funskip__'):
        new_attrs[key] = value
        return
      if hasattr(value, '__func__') or isinstance(value, types.FunctionType):
        if isinstance(value, staticmethod):
          new_attrs[key] = staticmethod(commonDecoratorFunc(value.__func__))
          return
        elif isinstance(value, classmethod):
          new_attrs[key] = classmethod(commonDecoratorFunc(value.__func__))
          return
        elif not key.startswith('__'):
          new_attrs[key] = commonDecoratorFunc(value)
          return
      else:
        if isinstance(value, property):
          # 當(dāng)對property類進(jìn)行重組的時(shí)候,我們強(qiáng)制裝飾了property類的fget fset和fdel方法。但是,不是每個(gè)propery都有這三個(gè)方法,有些是None,強(qiáng)制裝飾會(huì)報(bào)錯(cuò),所以我們這里要考慮提前返回None
          propertyWrapper = property(fget=commonDecoratorFunc(value.fget) if value.fget else None,
                        fset=commonDecoratorFunc(value.fset) if value.fset else None,
                        fdel=commonDecoratorFunc(value.fdel) if value.fdel else None,
                        doc=value.__doc__)
          new_attrs[key] = propertyWrapper
          return
      new_attrs[key] = value

    class Meta(type):
      @classmethod
      def options(cls, bases, attrs):
        new_attrs = {}
        for key, value in attrs.items():
          collect_attrib(key, value, new_attrs)
        for base in bases:
          for mbase in base.mro():
            for key, value in mbase.__dict__.items():
              if key not in new_attrs:
                collect_attrib(key, value, new_attrs)
        return new_attrs

      def __new__(cls, name, bases, attrs):
        new_attrs = cls.options(bases, attrs)
        return super(Meta, cls).__new__(cls, name, bases, new_attrs)
    return six.add_metaclass(Meta)(inClass)
  return innerMata

其中,skipper提供了一個(gè)后門,被skipper裝飾的函數(shù)會(huì)跳過全局裝飾器

使用方法如下

@classWrapper(trier(soft=True))
class Tree(object):
  @skipper
  def div(self):
    return 1/0
  
  def divsafe(self):
    return 1/0

t=Tree()
print t.divsafe()
print t.div()


執(zhí)行結(jié)果如圖

一個(gè)更完整的示例

from clswrapper那個(gè)文件 import skipper, classWrapper
import traceback
from functools import wraps

'''為簡潔起見,這次我們用的是不帶參數(shù)的trier裝飾器'''
def trier(func):
  @wraps(func)
  def inner(*args, **kwargs):
    try:
      return func(*args, **kwargs)
    except:
      print("EXCEPTION captured at function %s" % func.__name__, file=sys.stderr)
      print(traceback.format_exc().decode("gbk"))
      raise
  return inner

if __name__=="__main__":
  import time
  class mobj(object):
    def five(self):
      w = 1 / 0


  class obj(mobj):

    def __init__(self):
      # print "obj.__init__"
      return

    @classmethod
    def one(self):
      w = 1 / 0
      print('obj.one')


  @classWrapper(trier) # 或者用@classWrapper(argTrier(True))替換,則可以不拋出異常
  class obj1(obj):
    aa = 1

    def __init__(self):
      super(obj1, self).__init__()
      self.var = 1

    @classmethod
    def three(cls):
      w = 1 / 0
      print('obj1.three')

    @staticmethod
    def four():
      w = 1 / 0
      print('obj1.four')

    def two(self):
      w = 1 / 0
      print(self.pro)
      print('obj1.two')

    @property
    def pro(self):
      return self.var

    @pro.setter
    def pro(self, value):
      self.var = value / 0

    @skipper
    def eight(self):
      w=1/0
      return w

  class outerobj(obj1):
    def seven(self):
      return 1/0

  b = obj1()
  a = obj1

  print(b.var)

  try:
    b.two()
  except:
    pass
  try:
    a.three()
  except:
    pass
  try:
    a.four()
  except:
    pass
  try:
    a.one()
  except:
    pass
  try:
    b.five()
  except:
    pass

  try:
    b.pro = 3
  except:
    pass
  print(b.pro)

  print(a.aa)

  c=outerobj()
  try:
    c.five()
  except:
    pass

  try:
    c.seven()
  except:
    pass

  try:
    c.eight()
  except:
    print("c.eight被跳過,所以沒有被里層捕獲,才會(huì)不打堆棧直接走到這里")
 
  print("最后這個(gè)會(huì)真正觸發(fā)異常,因?yàn)閙obj實(shí)例并沒有被裝飾過")
  m=mobj()
  time.sleep(1)
  m.five()

它展示了這個(gè)強(qiáng)大裝飾器能處理的各種情況,執(zhí)行結(jié)果應(yīng)該如下

1
EXCEPTION captured at function two
EXCEPTION captured at function three
Traceback (most recent call last):
EXCEPTION captured at function four
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
EXCEPTION captured at function one
  return func(*args, **kwargs)
EXCEPTION captured at function five
 File "E:/pydev/異常處理裝飾器.py", line 138, in two
  w = 1 / 0
ZeroDivisionError: integer division or modulo by zero

Traceback (most recent call last):
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 129, in three
  w = 1 / 0
ZeroDivisionError: integer division or modulo by zero

Traceback (most recent call last):
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 134, in four
  w = 1 / 0
EXCEPTION captured at function pro
ZeroDivisionError: integer division or modulo by zero

EXCEPTION captured at function five
Traceback (most recent call last):
EXCEPTION captured at function five
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
EXCEPTION captured at function seven
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 115, in one
  w = 1 / 0
ZeroDivisionError: integer division or modulo by zero

Traceback (most recent call last):
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 104, in five
  w = 1 / 0
ZeroDivisionError: integer division or modulo by zero

Traceback (most recent call last):
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 148, in pro
  self.var = value / 0
ZeroDivisionError: integer division or modulo by zero

1
1
Traceback (most recent call last):
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 104, in five
  w = 1 / 0
ZeroDivisionError: integer division or modulo by zero

Traceback (most recent call last):
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 104, in five
  w = 1 / 0
ZeroDivisionError: integer division or modulo by zero

Traceback (most recent call last):
 File "E:/pydev/異常處理裝飾器.py", line 37, in inner
  return func(*args, **kwargs)
 File "E:/pydev/異常處理裝飾器.py", line 157, in seven
  return 1/0
ZeroDivisionError: integer division or modulo by zero

c.eight被跳過,所以沒有被里層捕獲,才會(huì)不打堆棧直接走到這里
最后這個(gè)會(huì)真正觸發(fā)異常,因?yàn)閙obj實(shí)例并沒有被裝飾過
Traceback (most recent call last):
 File "E:/pydev/�쳣����װ����.py", line 212, in <module>
  m.five()
 File "E:/pydev/�쳣����װ����.py", line 104, in five
  w = 1 / 0
ZeroDivisionError: integer division or modulo by zero

進(jìn)程已結(jié)束,退出代碼 1

以上這篇Python類中的裝飾器在當(dāng)前類中的聲明與調(diào)用詳解就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Python的SQLAlchemy框架使用入門

    Python的SQLAlchemy框架使用入門

    這篇文章主要介紹了Python的SQLAlchemy框架使用入門,SQLAlchemy框架是Python中用來操作數(shù)據(jù)庫的ORM框架之一,需要的朋友可以參考下
    2015-04-04
  • python openpyxl 帶格式復(fù)制表格的實(shí)現(xiàn)

    python openpyxl 帶格式復(fù)制表格的實(shí)現(xiàn)

    這篇文章主要介紹了python openpyxl 帶格式復(fù)制表格的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Python元組解密不可變的數(shù)據(jù)之美探索

    Python元組解密不可變的數(shù)據(jù)之美探索

    這篇文章主要介紹了Python元組解密:不可變的數(shù)據(jù)之美,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Python獲取列表值的方法小結(jié)

    Python獲取列表值的方法小結(jié)

    在?Python?編程中,列表(list)是一種非常常見且強(qiáng)大的數(shù)據(jù)結(jié)構(gòu),本文將通過簡潔明了的方式,結(jié)合代碼和案例,介紹如何獲取列表中的值,需要的可以了解下
    2024-11-11
  • python定時(shí)器(Timer)用法簡單實(shí)例

    python定時(shí)器(Timer)用法簡單實(shí)例

    這篇文章主要介紹了python定時(shí)器(Timer)用法,以一個(gè)簡單實(shí)例形式分析了定時(shí)器(Timer)實(shí)現(xiàn)延遲調(diào)用的技巧,需要的朋友可以參考下
    2015-06-06
  • 使用pandas的box_plot去除異常值

    使用pandas的box_plot去除異常值

    今天小編就為大家分享一篇使用pandas的box_plot去除異常值,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • selenium+opencv實(shí)現(xiàn)滑塊驗(yàn)證碼的登陸

    selenium+opencv實(shí)現(xiàn)滑塊驗(yàn)證碼的登陸

    很多網(wǎng)站登錄登陸時(shí)都要用到滑塊驗(yàn)證碼,本文主要介紹了selenium+opencv實(shí)現(xiàn)滑塊驗(yàn)證碼的登陸,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • python 的賦值語句和基本輸入輸出詳解

    python 的賦值語句和基本輸入輸出詳解

    這篇文章主要為大家介紹了python 賦值語句和基本輸入輸出,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • 如何用python插入獨(dú)創(chuàng)性聲明

    如何用python插入獨(dú)創(chuàng)性聲明

    這篇文章主要介紹了如何用python插入獨(dú)創(chuàng)性聲明,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • selenium查找網(wǎng)頁出現(xiàn)加載卡頓或失敗的解決方法

    selenium查找網(wǎng)頁出現(xiàn)加載卡頓或失敗的解決方法

    這篇文章主要為大家詳細(xì)介紹了selenium查找網(wǎng)頁時(shí)如何處理網(wǎng)站資源一直加載非??D或者失敗的情況,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-10-10

最新評論

永新县| 贵定县| 陇川县| 崇阳县| 晋城| 万宁市| 静安区| 江津市| 南投县| 遂川县| 通山县| 罗江县| 专栏| 大化| 连云港市| 山丹县| 法库县| 卢氏县| 湖南省| 连城县| 韶关市| 虞城县| 普定县| 洪江市| 淮北市| 高安市| 昭平县| 新龙县| 永州市| 南陵县| 抚顺县| 皋兰县| 昭觉县| 阜宁县| 库尔勒市| 河东区| 耿马| 石渠县| 阿拉善右旗| 岢岚县| 海口市|