在使用许多参数扩展函数的同时保留类型/类型检查

问题描述 投票:0回答:1

我想子类/包装 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__]):

有什么办法可以达到这样的效果吗?如果没有,在做这样的事情时如何保留类型检查?

python parameter-passing subclass python-typing type-hinting
1个回答
0
投票

您可以使用

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

但是考虑到这仍然会让你在一个新对象中显式地布置所有参数,我不确定这会给你带来多大的提升 - 第一种方法可能更方便。

© www.soinside.com 2019 - 2024. All rights reserved.