簡體   English   中英

在 Python 中從子類訪問父類中的裝飾器

[英]Accessing a decorator in a parent class from the child in Python

如何從孩子的基類訪問裝飾器?

我(錯誤地)認為 ffg. 會工作:

class baseclass(object):
    def __init__(self):
        print 'hey this is the base'

    def _deco(func):
        def wrapper(*arg):
            res = func(*arg)
            print 'I\'m a decorator. This is fabulous, but that colour, so last season sweetiedarling'
            return res
        return wrapper

    @_deco
    def basefunc(self):
        print 'I\'m a base function'

這個類工作正常,但后來我創建了一個繼承自這個的子類:

class otherclass(baseclass):
    def __init__(self):
        super(otherclass, self).__init__()
        print 'other class'


    @_deco
    def meh(self):
        print 'I\'m a function'

這甚至無法正確導入,更不用說運行了。 @_deco 未定義。 嘗試 baseclass._deco 會拋出一個未綁定的方法 _deco() 錯誤,這並不奇怪。

任何想法如何做到這一點,我真的很想將裝飾器封裝在類中,但我不喜歡這個想法,我需要在基類和子類中調用它。

class baseclass(object):
    def __init__(self):
        print 'hey this is the base'

    def _deco(func):
        def wrapper(*arg):
            res = func(*arg)
            print 'I\'m a decorator. This is fabulous, but that colour, so last season sweetiedarling'
            return res
        return wrapper

    @_deco
    def basefunc(self):
        print 'I\'m a base function'

    @_deco
    def basefunc2(self):
        print "I'm another base function"

   #no more uses of _deco in this class
    _deco = staticmethod(_deco) 
   # this is the key. it must be executed after all of the uses of _deco in 
   # the base class. this way _deco is some sort weird internal function that 
   # can be called from within the class namespace while said namespace is being 
   # created and a proper static method for subclasses or external callers.


class otherclass(baseclass):
    def __init__(self):
        super(otherclass, self).__init__()
        print 'other class'


    @baseclass._deco
    def meh(self):
        print 'I\'m a function'

還有一種特定於python3的方法可以在子類中使用該裝飾器而不提及父類,完全按照OP的建議。 它需要使用其__prepare__()方法在父類的元類中實現裝飾器(可以在此處找到元類的很好解釋

aaronasterling 的答案是有效且首選的解決方法,我僅將其發布為一個有趣的示例,以幫助其他人了解語言的基礎知識。 僅當沒有其他方法可以實現您的需要時才使用元類!

class metaclass(type):
    @classmethod
    def __prepare__(metacls, name, bases):
        def _deco(func):
            def wrapper(*arg):
                res = func(*arg)
                print('I\'m a decorator. This is fabulous, but that colour, so last season sweetiedarling')
                return res
            return wrapper
        return {"_deco": _deco}

class baseclass(metaclass=metaclass):
    def __init__(self):
        print('hey this is the base')

    @_deco
    def basefunc(self):
        print('I\'m a base function')
        
class otherclass(baseclass):
    def __init__(self):
        super(otherclass, self).__init__()
        print('other class')

    @_deco
    def meh(self):
        print('I\'m a function')

示例代碼在 python3 中運行良好:

>>> obj = otherclass()
hey this is the base
other class
>>> obj.meh()
I'm a function
I'm a decorator. This is fabulous, but that colour, so last season sweetiedarling

關於 __prepare__() 方法的重要說明:

  • 如果存在,它將在執行對象主體之前運行
  • 它的返回值在評估開始時用作類主體的本地命名空間(這樣,裝飾器可以從子主體中獲得,而無需使用父命名空間)
  • 它應該被實現為classmethod()並且應該返回映射對象(即dict
  • 如果不存在,則使用空映射作為初始本地命名空間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM