【发布时间】:2019-03-26 12:18:46
【问题描述】:
我正在尝试设计一个可以接受类名(不是对象)的包装器,并将字典插入到类的每个实例中。下面是我在包装现有函数时如何实现这一点的 sn-p。
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 类中。既然字典是不可调用的,那么如何设计这样的包装器呢?
更新
感谢您对此提出的建设性反馈。 一位 stack-overflow 用户正确地指出,我没有解释我为什么要这样做。所以这里是:
- 我正在尝试构建一个框架,该框架本质上可以使用一堆用户定义的函数并扩展现有的类。所以我有一个类
A,以及用户定义的函数f_1、f_2、...、f_n,我想将它们注入到A类中,这样这个类obj_a = A()的实例就可以调用这些函数,例如obj_a.f_1()。我已经设法使用类似于上面的代码 sn-p 的装饰器函数来实现这一点。 - 现在,每个用户定义的函数都有一些重复的代码,如果我的基类
A的所有实例都可以访问用户定义的字典,我认为我可以删除这些代码。我实现这一目标的思考过程是尝试修改我现有的包装函数以将其添加到类中。但是,我知道字典不可调用,因此是个问题。
我希望这足够详细。
更新 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()
每个用户函数都包含一个常用字典的子集。为了利用这一点,我认为如果可以将其作为 BaseClass 动态注入的属性的一部分进行访问会很方便。
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_
...
要合并这一点,我可能必须将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)
这个解决方案有效,但在某种程度上回答了我的问题,我想我可以说,当一个简单的函数可能实现这一点时,我可能会通过为此编写一个装饰器来过度设计我的解决方案。
但是,原始问题的一个方面仍然存在 - 这是一个好方法吗?
【问题讨论】:
-
在我看来是一个典型的 XY 问题。不要询问您认为的解决方案是什么(实际上这几乎是不可能的 - 除非专门为此设计,否则一个类对其实例一无所知),请解释您试图用这个“解决方案”解决的真正问题"。
-
如果我没有说清楚,我很抱歉,但代码 sn-p 是我试图接近解决方案的设计。
-
是的,但解决方案是什么?这只是“XY 问题”的定义:你问你认为什么是解决方案,而不是解释真正的问题(“我怎么做 X?”=>“你为什么想要做 X ?” => “因为我需要它来解决 Y” => “啊,好吧 - 但这不是解决 Y 的方法,你想要 W 而不是”。所以如果你期望一个有用的答案,请解释真正的问题。
-
@brunodesthuilliers 谢谢你。我完全同意这一点。我修改了问题以反映对问题的更好构造的描述。
-
这个字典是只读的还是必须是可写的?你可以发布一个示例使用吗? (dict + 几个使用它的“用户定义”函数等)?您的问题现在更有意义,但缺乏认真回答的背景(请记住,我们根本不了解您的项目!)。
标签: python python-3.x python-decorators