【问题标题】:Class Factory for classes with constructors that require different set of arguments具有需要不同参数集的构造函数的类的类工厂
【发布时间】:2021-04-23 10:58:04
【问题描述】:

我正在尝试执行一个类工厂(可能在这里使用的术语不正确,不是 100% 确定),其中要通过该工厂实例化的不同类的构造函数可能在其构造函数中具有不同的参数,例如所以:

module.py

class A:
    def __init__(self, a=None):
        pass

    def run(self):
        pass

class B:
    def __init__(self, a=None, b=None):
        pass

    def run(self):
        pass

class C:
    def __init__(self, a=None, b=None, c=None):
        pass

    def run(self):
        pass

我面临的问题是如何为要实例化的不同类处理不同类型的参数。在下面的代码中,如果我使用意外参数实例化该类,我们将得到一个异常。我知道使用 kwargs 可以解决这个问题,但是使用 kwargs 的问题是参数列表变得隐含,因此函数的签名不能完全解释函数需要什么。下面代码中的最后一个示例尝试根据类构造函数的参数过滤传入的参数。我认为这是一个可能的解决方案,但我想知道是否有一种设计模式或技术可以帮助我以 cleaner 的方式实现这一目标?

example.py

import inspect
import module

# Runs OK
runner_class_name = 'C'
runner_class = getattr(module, runner_class_name)
runner_class(a=1, b=2, c=3)


# Runs KO, throws TypeError: "__init__() got an unexpected keyword argument"
runner_class_name = 'A'
runner_class = getattr(module, runner_class_name)
runner_class(a=1, b=2, c=3)


# Runs OK
runner_class_name = 'A'
runner_class = getattr(module, runner_class_name)
constructor = getattr(runner_class, '__init__')
args = inspect.getfullargspec(constructor).args
incomig_args = {'a':1, 'b':2, 'c':3}
safe_args = {k:incomig_args[k] for k in args if k in incomig_args}
runner = runner_class(**safe_args)

感谢您提供的任何见解!

【问题讨论】:

  • **kwargs 并不意味着您不能有其他关键字参数。您可以将**_ 添加到参数中以“吃掉”未使用的参数。

标签: python python-3.x design-patterns


【解决方案1】:

在@Axe319 评论之后,module.py 类将是

class A:
    def __init__(self, a=None, **_):
        pass

    def run(self):
        pass

class B:
    def __init__(self, a=None, b=None, **_):
        pass

    def run(self):
        pass

class C:
    def __init__(self, a=None, b=None, c=None, **_):
        pass

    def run(self):
        pass

然后调用者就会运行正常:


# Runs OK
runner_class_name = 'C'
runner_class = getattr(module, runner_class_name)
runner_class(a=1, b=2, c=3)


# Runs OK
runner_class_name = 'A'
runner_class = getattr(module, runner_class_name)
runner_class(a=1, b=2, c=3)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 2021-02-07
    • 2015-09-10
    • 2013-10-25
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    相关资源
    最近更新 更多