python class 是否可以声明为与另一个 class(包括默认值)具有相同的 __init__() 签名?

Can a python class be declared to have the same __init__() signature as another class (including defaults)?

考虑以下包装器:

class SomeClass:
    def __init__(arg1='default1', arg2='default2'):
        # initialize stuff

    def do_stuff(self):

    
class SomeClassWrapper:
    def __init__(arg1='default1', arg2='default2'):
        self.arg1 = arg1
        self.arg2 = arg2
    
    def doit(self):
        instance = SomeClass(arg1, arg2)
        instance.do_stuff()

SomeClassWrapper 用于延迟 SomeClass 对象的实例化,并在每次需要执行 do_stuff() 时抽象出新实例的创建。

SomeClassWrapper 使用稍后初始化 SomeClass 对象所需的“模板”进行初始化,这些对象的实际初始化列表比示例中的要长得多,并且会随着项目的发展而变化。

我们的目标是通过不必在 SomeClassWrapper.__init__() 中手动重新键入我们在 SomeClass.__init__().

中已有的相同参数列表(包括默认值)来减少错误和维护负担

有没有办法,也许使用 inspect 模块,按照下面的方式做一些事情?

class SomeClassWrapper:
    # syntax to say:
    #  __init__() should be the same as SomeClass.__init__()  
    #  the arguments should be stored in say self.kwargs
    
    def doit(self)
        instance = SomeClass(self.kwargs)
        instance.do_stuff()

您可以将包装器用作您继承自的模板,并根据 class 您需要的包装器创建新的包装器。

class SomeClass:
    def __init__(self, arg1='default1', arg2='default2'):
        # Initialize stuff

    def do_stuff(self):
        # Do stuff


class AnotherClass:
    def __init__(self, hello='a'):
        # Initialize stuff

    def do_stuff(self):
        # Do stuff

    

class BaseClassWrapper:
    instance_class = None

    def __init__(self, *args, **kwargs):
        self.args   = args
        self.kwargs = kwargs
    
    def doit(self):
        instance = self.instance_class(*self.args, **self.kwargs)
        instance.do_stuff()


class SomeClassWrapper(BaseClassWrapper):
    instance_class = SomeClass

class AnotherClassWrapper(BaseClassWrapper):
    instance_class = AnotherClass


wrapper1 = SomeClassWrapper('arg1', arg2='arg2')
wrapper1.doit()

wrapper2 = AnotherClassWrapper('goodbye')
wrapper2.doit()

与其复制参数传递,不如让包装器接受创建对象的零参数可调用对象。

class SomeClass:
    def __init__(arg1='default1', arg2='default2'):
        # initialize stuff

    def do_stuff(self):
        ...

    
class SomeClassWrapper:
    def __init__(self, maker):
        self.maker = maker

    def doit(self):
        instance = self.maker()
        instance.do_stuff()

来电者仍然提供所有详细信息,但方式略有不同

# Old version
# w = SomeClassWrapper('foo', 'bar)

# One option
w = SomeClassWrapper(lambda: SomeClass('foo', 'bar'))

# Another option
from functools import partial
w = SomeClassWrapper(partial(SomeClass, 'foo', 'bar'))