首页 > 解决方案 > 可以将 python 类声明为与另一个类具有相同的 __init__() 签名(包括默认值)?

问题描述

考虑以下包装器:

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()

标签: pythonwrapperfactoryintrospectioninspect

解决方案


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

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'))

推荐阅读