簡體   English   中英

在裝飾器中從其名稱獲取裝飾類?

[英]Get decorated class from its name in the decorator?

我用@bot_thinking裝飾了一些方法,該functions將有關裝飾方法的一些信息存儲在functions屬性中。 其中一條信息是“ class_name”,但是我的程序需要將類類型作為變量,例如RandomBot 我想上這堂課。

這是一些示例代碼:

class DepthPrunedMinimaxAgent(Agent):
    @bot_thinking(associated_name="minimax profondeur")
    def select_move(self, game_state: GameState):

上面是代碼的修飾部分。

裝飾器:

functions = {}

def bot_thinking(associated_name, active=True):
    def _(func):
        if active:
            class_name = func.__qualname__.rsplit('.')[-2]
            import sys
            # class_name_2=getattr(sys.modules[__name__], class_name)
            # module=importlib.import_module('sources.agent')

            functions[associated_name] = (associated_name, class_name,
                                          globals()[class_name], func)
        else:
            functions.pop(associated_name)

    return _

bot_thinking不是真正的裝飾器,而是裝飾器工廠。 func函數中,我得到了class_name ,但是我無法使用@ m.kocikowski 接受的答案來找到正確的類,因為此類已被修飾,因此它已經導入了注釋模塊,因此從的模塊中導入帶注釋的模塊的注釋將導致循環導入,而python似乎不允許這樣做。

您是否看到一種從類名獲取類的方法?

ps:ps:更清楚:代碼的注釋部分需要導入到帶注釋的類(以從其名稱中檢索類),這也需要導入注釋(以使注釋起作用)。

問題是當bot_thinking()裝飾器工廠(和裝飾器本身)正在執行時,尚未定義該類。 我能想到的唯一解決方法是在定義類修補問題,如下所示:

from pprint import pprint, pformat

functions = {}

def bot_thinking(associated_name, active=True):
    def _(func):
        if active:
            class_name = func.__qualname__.split(".")[-2]
            functions[associated_name] = (associated_name, class_name, class_name, func)
        else:
            functions.pop(associated_name, None)

        return func # Decorators must return a callable.

    return _


class Agent: pass
class GameState: pass

class DepthPrunedMinimaxAgent(Agent):
    @bot_thinking(associated_name="minimax profondeur")
    def select_move(self, game_state: GameState):
        pass

# After class is defined, update data put into functions dictionary.
for associated_name, info in functions.items():
    functions[associated_name] = (info[0], info[1], globals()[info[2]], info[3])

pprint(functions)

輸出:

{'minimax profondeur': ('minimax profondeur',
                        'DepthPrunedMinimaxAgent',
                        <class '__main__.DepthPrunedMinimaxAgent'>,
                        <function DepthPrunedMinimaxAgent.select_move at 0x00F158A0>)}

如果使用描述符類而不是函數作為裝飾器,則可以執行所需的操作,至少在使用Python 3.6或更高版本的情況下。 這是因為在描述符協議中添加了一個新方法__set_name__ 當描述符對象另存為類變量時,它將被調用。 盡管大多數描述符將使用它來記錄將其另存為的名稱,但是您可以使用它來獲取您所在的類。

您確實需要使裝飾器對象包裝真實的函數(實現調用和描述符查找方法),而不是能夠返回您正在裝飾的未修改函數。 這是我嘗試快速而骯臟的實現。 我不太了解您在使用functions做什么,因此我可能沒有在其中放入正確的數據,但是它應該足夠接近才能理解這個想法( owner是存儲方法的類)。

functions = {}

def bot_thinking(associated_name, active=True):
    class decorator:
        def __init__(self, func):
            self.func = func

        def __set_name__(self, owner, name):
            if active:
                 functions[associated_name] = (associated_name, owner.__name__,
                                               owner, self.func)
            else:
                 functions.pop(associated_name)

        def __get__(self, obj, owner):
            return self.func.__get__(obj, owner)

        def __call__(self, *args, **kwargs):
            return self.func(*args, **kwargs)

    return decorator

暫無
暫無

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

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