Python 如何扩展大型类方法?

Python 如何扩展大型类方法?,python,python-3.x,Python,Python 3.x,如果您想扩展一个类及其相应的\uuuuu init\uuuu方法,有没有办法处理大量参数,包括新参数?例如: class Thing: def __init__(self, arg1, arg2, arg3, arg4): # Initialize class SubThing(Thing): def __init__(self, arg1, arg2, arg3, arg4, ex_arg1, ex_arg2): super().__init

如果您想扩展一个类及其相应的
\uuuuu init\uuuu
方法,有没有办法处理大量参数,包括新参数?例如:

class Thing:
    def __init__(self, arg1, arg2, arg3, arg4):
        # Initialize 

class SubThing(Thing):
    def __init__(self, arg1, arg2, arg3, arg4, ex_arg1, ex_arg2):
        super().__init__(arg1, arg2, arg3, arg4):
        # Do extra initialization 
是否可以缩短子类的
\uuuuu init\uuuu
方法的参数列表?答案,例如不描述如何向init添加参数,或者如何处理额外的关键字参数,例如
\uuuu init\uuuuuuuu(self,arg1,arg房间='卧房',ex_arg1,ex_position=(0,0),ex_arg2)
真的没有很好的方法来做你想要的事情。一般来说,命名所有参数是主要的方法

不过,有一些方法可能会有所帮助。一种是将一些参数绑定到更大的集合中,因此只需将一个项传递给父类,而不是几个项。下面是使用iterable序列来保存
arg1
-
arg4
,但您可能希望使用自定义类(请参阅
csv
模块中的
方言
类,以获取捆绑其他类型的多个参数的类型示例):

另一种方法是使用
*args
和/或
**kwargs
接收要传递的参数。使用positional
*args
相当有限,因为必须在传递的所有参数之前列出子类中关心的参数:

def __init__(self, ex_arg1, ex_arg2, *args):
    super().__init__(*args)
    # ...
调用者需要首先列出
ex_argsN
参数的值,这可能是不自然的。子类越多,情况就越糟

要求所有内容都作为关键字参数传递可能更好,因为调用者可以按看起来最自然的顺序放置关键字参数:

def __init__(self, *, ex_args1, ex_args2, **kwargs):
    super.__init__(self, **kwargs) # passes along the unnamed keyword args
    # ...
这种方法的最大缺点是,调用中的所有参数名称都非常冗长:

st = SubThing(arg1="foo", arg2="bar", arg3="baz", arg4="quux",
              ex_arg1=1, ex_arg2=6.02e23)

您可以执行类似于引用答案的操作,只是删除特定于您的子类的项

class Thing:
    def __init__(self, arg1, arg2, arg3, arg4, kw1=None, kw2=None):
        print('Thing args:',arg1,arg2,arg3,arg4)
        print('Thing kw:',kw1,kw2)

class SubThing(Thing):
    def __init__(self, *args, **kw):
        """SubThing(arg1, arg2, arg3, arg4, arg5, arg6, kw1=None, kw2=None,
        kw3=None, kw4=None)
        """
        if len(args) != 6:
            raise TypeError(
                "SubThing() takes 6 positional arguments but {} were given"
                .format(len(args)))
        arg5, arg6 = args[4:]
        kw3 = kw.pop('kw3', None)
        kw4 = kw.pop('kw4', None)
        super().__init__(*args[:4], **kw)


SubThing(1,2,3,4,5,6,kw1='kw1',kw4='kw4')
print('---- but populating kwargs from positional args stops working ----')
Thing(1,2,3,4, 'kw1', 'kw2')
SubThing(1,2,3,4,5,6,'kw1','kw2')
这导致

Thing args: 1 2 3 4
Thing kw: kw1 None
---- but populating kwargs from positional args stops working ----
Thing args: 1 2 3 4
Thing kw: kw1 kw2
Traceback (most recent call last):
  File "n.py", line 24, in <module>
    SubThing(1,2,3,4,5,6,'kw1','kw2')
  File "n.py", line 14, in __init__
    .format(len(args)))
TypeError: SubThing() takes 6 positional arguments but 8 were given
东西参数:1 2 3 4
东西kw:kw1无
----但是从位置arg填充Kwarg将停止工作----
事物参数:1 2 3 4
东西千瓦:千瓦1千瓦2
回溯(最近一次呼叫最后一次):
文件“n.py”,第24行,在
子项(1,2,3,4,5,6、'kw1'、'kw2')
文件“n.py”,第14行,在_init中__
.格式(len(args)))
TypeError:SubThing()接受6个位置参数,但给出了8个

注意,在第二个示例中,您丢失了一些功能,因为额外的位置参数没有自动填充关键字参数。您可以通过更多的编码来解决这个问题,也可以接受这些限制。很多类都使用了
*args,**kw
忘记了这样做,这样你就有了好的同伴。

简短回答:不,如果不写出你想传递的所有参数,就无法做到这一点。有*args和**kwargs,但我不认为这正是你想要的。
Thing args: 1 2 3 4
Thing kw: kw1 None
---- but populating kwargs from positional args stops working ----
Thing args: 1 2 3 4
Thing kw: kw1 kw2
Traceback (most recent call last):
  File "n.py", line 24, in <module>
    SubThing(1,2,3,4,5,6,'kw1','kw2')
  File "n.py", line 14, in __init__
    .format(len(args)))
TypeError: SubThing() takes 6 positional arguments but 8 were given