我试图设计一个包装器,它可以接受类(不是对象)的名称,并在类的每个实例中插入一个字典。下面是我在包装现有函数时如何实现这一点的片段。
def insert_fn_into_class(cls):
"""Decorator function that consumes a function and inserts it into the cls class."""
def decorator(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
return func(*args, **kwargs)
setattr(cls, f'prefix_{func.__name__}', wrapper)
return decorator
如何使用类似的模板来修饰字典并将其插入cls类。既然字典是不可调用的,那么如何设计这样的包装器呢?
更新
感谢您对此的建设性反馈。
一位堆栈溢出用户正确地指出,我未能解释为什么要这样做。所以说:
-
我正在尝试构建一个框架,它实际上可以使用一堆用户定义的函数并扩展现有的类。所以我有一节课
A
,以及用户定义的函数
f_1
,
f_2
…
f_n
我想把它注入课堂
一
这样类的一个实例
obj_a = A()
可以调用以下函数
obj_a.f_1()
. 我使用了一个类似于上面代码片段的decorator函数来实现这一点。
-
现在,每个用户定义的函数都有一些重复的代码,如果基类的所有实例
一
可以访问用户定义的词典。我实现这一点的思路是尝试修改现有的包装函数,将其添加到类中。然而,我知道字典是不可调用的,因此,这个问题。
我希望这足够详细。
更新2
看来还有进一步细化的余地。下面是一个例子,说明我前面描述的各种组件是什么样子的。
module_a.py
class BaseClass():
def __init__(self):
...
def base_class_method(self):
...
def run(self):
getattr(self, 'prefix_user_fn_1')()
def extend(cls=BaseClass):
def decorator(func):
def wrapper(self, *args, **kwargs):
return func(*args, **kwargs)
setattr(cls, f'prefix_{func.__name__}', wrapper)
return decorator
user_defined_functions.py
from module_a import BaseClass, extend
@extend()
def user_fn_1():
dict_ = {'a':'b', 'c':'d'}
...
@extend()
def user_fn_2():
dict_ = {'my':'dict', 'c':'d'}
...
main.py
from module_a import BaseClass
b = BaseClass()
b.run()
每个用户函数都包含一个常用字典的子集。为了利用这一点,我认为如果这可以作为动态注入的基类属性的一部分来访问,那将是很方便的。
modified_user_defined_functions.py
# THIS WILL NOT WORK FOR OBVIOUS REASONS
from module_a import BaseClass, extend, common_config, insert_config_into_class
# @common_config ?? Is this even a good idea?
dict_ = {'my':'dict', 'a':'b', 'c':'d'}
insert_config_into_class(BaseClass, dict_)
@extend()
def user_fn_1(self):
print(self.dict_)
# do something with self.dict_
...
若要合并此项,我可能必须将run方法更改为
BaseClass
像这样:
modified_module_a.py
...
class BaseClass():
...
def run(self):
getattr(self, 'prefix_user_fn_1')(self)
更新3-潜在解决方案
def shared_config(data, cls=BaseClass):
setattr(cls, 'SHARED_DICT', data)
这个解决方案是可行的,但也在一定程度上回答了我的问题,我想我可以说,当一个简单的函数可能实现这一点时,我可能通过为此编写一个decorator来过度设计我的解决方案。
然而,最初问题的一个方面仍然存在——这是一个好办法吗?