你可以使用装饰器来达到所需的功能。
def initializer(cls: type):
def argument_wrapper(
*args: Tuple[Any], **kwargs: Dict[str, Any]
) -> Callable[[], 'X']:
def wrapper():
return cls(*args, **kwargs)
return wrapper
return argument_wrapper
@initializer
class X:
def __init__(self, *, some_key: int, foo: int = 10, bar: int = 20) -> None:
self._some_key = some_key
self._foo = foo
self._bar = bar
@property
def key(self) -> int:
return self._some_key
@property
def foo(self) -> int:
return self._foo
@property
def bar(self) -> int:
return self._bar
def __str__(self) -> str:
return f'[Key: {self.key}, Foo: {self.foo}, Bar: {self.bar}]'
然后你可以这样创建一个 defaultdict
:
>>> d = defaultdict(X(some_key=10, foo=15, bar=20))
>>> d['baz']
[Key: 10, Foo: 15, Bar: 20]
>>> d['qux']
[Key: 10, Foo: 15, Bar: 20]
default_factory
将使用指定的参数创建 X
的新实例。
当然,这只有在您知道该类将用于 default_factory
时才有用。否则,为了实例化一个单独的类,您需要执行类似以下操作:
x = X(some_key=10, foo=15)()
这有点丑... 但如果你想避免这种情况,并引入一定程度的复杂性,你也可以向 argument_wrapper
添加一个关键字参数,比如 factory
,以实现通用行为:
def initializer(cls: type):
def argument_wrapper(
*args: Tuple[Any], factory: bool = False, **kwargs: Dict[str, Any]
) -> Callable[[], 'X']:
def wrapper():
return cls(*args, **kwargs)
if factory:
return wrapper
return cls(*args, **kwargs)
return argument_wrapper
然后你可以这样使用该类:
>>> X(some_key=10, foo=15)
[Key: 10, Foo: 15, Bar: 20]
>>> d = defaultdict(X(some_key=15, foo=15, bar=25, factory=True))
>>> d['baz']
[Key: 15, Foo: 15, Bar: 25]
defaultdict
的__missing__()
方法可以被覆盖(自 2.5 版本以来,在任何内置dict
类的子类中都可以)。 - martineau