在装饰器中从它的名字得到装饰 class?
Get decorated class from its name in the decorator?
我用@bot_thinking
装饰了一些方法,它在functions
属性中存储了关于装饰方法的一些信息。
一条信息是 'class_name',但我的程序需要 class 类型作为变量,例如RandomBot
。我想要这个 class.
下面是一些示例代码:
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 的 accepted answer 来找到正确的 class,因为这个 class 是装饰的,所以它已经导入了注解模块,所以从注解的模块导入注解模块会导致循环导入,python 似乎不允许。
您是否看到了从其名称中获取 class 的方法?
ps:
ps:
更清楚:代码的注释部分需要导入到带注释的 classes(以从其名称中检索 class),这也需要导入注释(以便注释起作用).
问题是当 bot_thinking()
装饰器工厂(和装饰器本身)正在执行时,class 尚未定义。我能想到的唯一解决方法是在 定义 class 之后修补 ,如下图所示:
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>)}
如果您使用描述符 class 而不是函数作为装饰器,您可以做您想做的事,至少在您使用 Python 3.6 或更新版本时是这样。那是因为在描述符协议中添加了一个新方法,__set_name__
。当描述符对象保存为 class 变量时调用它。虽然大多数描述符将使用它来记录它们被保存为的名称,但您可以使用它来获取您所在的 class。
您确实需要让您的装饰器对象包装真正的函数(实现调用和描述符查找方法),而不是能够 return 您正在装饰的未修改函数。这是我对快速而肮脏的实施的尝试。我真的不明白你在用 functions
做什么,所以我可能没有在其中放入正确的数据,但它应该足够接近以传达这个想法(owner
是 class方法存储在).
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
我用@bot_thinking
装饰了一些方法,它在functions
属性中存储了关于装饰方法的一些信息。
一条信息是 'class_name',但我的程序需要 class 类型作为变量,例如RandomBot
。我想要这个 class.
下面是一些示例代码:
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 的 accepted answer 来找到正确的 class,因为这个 class 是装饰的,所以它已经导入了注解模块,所以从注解的模块导入注解模块会导致循环导入,python 似乎不允许。
您是否看到了从其名称中获取 class 的方法?
ps: ps: 更清楚:代码的注释部分需要导入到带注释的 classes(以从其名称中检索 class),这也需要导入注释(以便注释起作用).
问题是当 bot_thinking()
装饰器工厂(和装饰器本身)正在执行时,class 尚未定义。我能想到的唯一解决方法是在 定义 class 之后修补 ,如下图所示:
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>)}
如果您使用描述符 class 而不是函数作为装饰器,您可以做您想做的事,至少在您使用 Python 3.6 或更新版本时是这样。那是因为在描述符协议中添加了一个新方法,__set_name__
。当描述符对象保存为 class 变量时调用它。虽然大多数描述符将使用它来记录它们被保存为的名称,但您可以使用它来获取您所在的 class。
您确实需要让您的装饰器对象包装真正的函数(实现调用和描述符查找方法),而不是能够 return 您正在装饰的未修改函数。这是我对快速而肮脏的实施的尝试。我真的不明白你在用 functions
做什么,所以我可能没有在其中放入正确的数据,但它应该足够接近以传达这个想法(owner
是 class方法存储在).
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