【发布时间】:2015-01-21 12:25:19
【问题描述】:
我正在尝试寻找一种优雅的 Python 方式来解决以下问题。我有一个类VideoAnalysisWidget,它创建了一大堆子小部件,例如VideoFileChoiceWidget、RegionWidget 等。我希望VideoAnalysisWidget.__init__ 将任何适当的关键字参数传递给VideoFileChoiceWidget.__init__、RegionWidget.__init__、。 .. 为此,我想使用如下代码:
import inspect
def filterArgs(func, **kwargs):
spec = inspect.getargspec(func)
ks = set(kwargs.keys())
ks.discard('self')
kinc = ks & set(spec.args)
kexc = ks - set(spec.args)
inc = {k: kwargs[k] for k in kinc}
exc = {k: kwargs[k] for k in kexc}
return(inc, exc)
然后,在别处:
def __init__(self, **kwargs):
(fcwArgs, otherArgs) = filterArgs(VideoFileChoiceWidget.__init__, **kwargs)
fcw = VideoFileChoiceWidget(**fcwArgs)
...
以这种方式做事,我的VideoAnalysisWidget 代码不必跟踪VideoFileChoiceWidget 的参数列表。如果我稍后修改 VideoFileChoiceWidget 以获取新参数,则无需更改遥远的 VideoAnalysisWidget 代码。
现在问题来了。如果VideoFileChoiceWidget 仅明确定义了关键字参数,则此方法可以正常工作。 (顺便说一句,我可以不使用除self 之外的任何位置参数来处理这些函数。)但是如果VideoFileChoiceWidget 也有**kwargs 参数怎么办?事实上,它确实如此,因为它是ContainerWidget 的子类,所以我想将任何额外的额外参数传递给它。 (而ContainerWidget 只接受**kwargs。)从根本上说,问题是我的这个解决方案不能嵌套。
一种可能的解决方案是将附加参数列表附加到VideoFileChoiceWidget.__init__,例如:
VideoFileChoiceWidget.__init__._args = ['description', 'visible', 'children']
...然后修改filterArgs 以使用它(如果可用)。但是有没有更好、更 Pythonic 的方式来做到这一点?
【问题讨论】:
-
我不确定这是否是最好的方法,因为使用了
inspect,但在这些情况下,我通常将大量 kwarg 分组到一个类中并传递它。 -
是的,我认为这是一种解决方案。反对它的论点(这可能不是一个好的论点)是它本质上重建了用户代码中内置的 KW arg 传递函数,使一切变得不那么透明。
-
这是我的看法:当参数共享并且对于子类来说太大而无法管理时,正如您在您的案例中所说的那样,不妨这样做以分离关注点。它实际上经常发生。
标签: python optional-arguments keyword-argument