我想子类/包装 subprocess.Popen。然而,它有很多争论。据我所知,解决这个问题的常用方法是 1.“咬紧牙关”:
class MyPopen1(subprocess.Popen):
def __init__(self, myarg1, myarg2, bufsize=-1, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=True,
shell=False, cwd=None, env=None, universal_newlines=None,
startupinfo=None, creationflags=0,
restore_signals=True, start_new_session=False,
pass_fds=(), *, user=None, group=None, extra_groups=None,
encoding=None, errors=None, text=None, umask=-1, pipesize=-1,
process_group=None):
arguments = self.handle_custom_arguments(myarg1, myarg2)
super().__init__(arguments, bufsize, executable,
stdin, stdout, stderr,
preexec_fn, close_fds,
shell, cwd, env, universal_newlines,
startupinfo, creationflags,
restore_signals, start_new_session,
pass_fds, user=user, group=group, extra_groups=extra_groups,
encoding=encoding, errors=errors, text=text, umask=umask, pipesize=pipesize,
process_group=process_group)
或 2.使用 *args, **kwargs。
class MyPopen2(subprocess.Popen):
def __init__(self, myarg1, myarg2, *args, **kwargs):
arguments = self.handle_custom_arguments(myarg1, myarg2)
super().__init__(arguments, *args, **kwargs)
第二个写起来容易多了;如果在 3.1x 中向 subprocess.Popen 添加新参数,则不需要维护。缺点是它没有类型,这意味着文本编辑器中没有静态类型检查和函数签名提示。
我们可以用
@functools.wraps(...)
更接近一点,但代价是签名需要与 subprocess.Popen 完全相同,并且它会覆盖 doc 等。我不认为这就是 wraps 的目的.
# Not good solution.
class MyPopen3(subprocess.Popen):
@functools.wraps(subprocess.Popen.__init__)
def __init__(self, myarg1: int, myarg2: str, *args, **kwargs):
"""
:param myarg1: does foo
:param myarg2: does bar
"""
arguments = self.handle_custom_arguments(myarg1, myarg2)
super().__init__(arguments, *args, **kwargs)
理想情况下,我想要一个类型签名,例如...
def __init__(self,
myarg1: int, myarg2: str,
*args: ArgsOf[subprocess.Popen.__init__][1:],
**kwargs: KwargsOf[subprocess.Popen.__init__]):
有什么办法可以达到这样的效果吗?如果没有,在做这样的事情时如何保留类型检查?
您可以使用
Unpack[]
库中的 typing
从 TypedDict
获取类型提示:
from typing import TypedDict, Unpack
class Movie(TypedDict):
name: str
year: int
def foo(**kwargs: Unpack[Movie]) -> None: ..
https://typing.readthedocs.io/en/latest/spec/callables.html#unpack-kwargs
但是考虑到这仍然会让你在一个新对象中显式地布置所有参数,我不确定这会给你带来多大的提升 - 第一种方法可能更方便。