代码之家  ›  专栏  ›  技术社区  ›  Ben Blank Jarret Hardie

向多重继承内置类型子类的构造函数添加可选参数?

  •  4
  • Ben Blank Jarret Hardie  · 技术社区  · 14 年前

    我的多重继承能力不强。我试图创建一个超类 __init__ 获取一个可选的命名参数及其子类,这些子类也继承自内置类型。可悲的是,我似乎不知道该怎么做:

    >>> class Super(object):
        name = None
        def __init__(self, *args, name=None, **kwargs):
            self.name = name
            super().__init__(self, *args, **kwargs)
    
    >>> class Sub(Super, int):
        pass
    
    >>> Sub(5)
    5
    
    >>> Sub(5, name="Foo")
    Traceback (most recent call last):
      File "<pyshell#10>", line 1, in <module>
        Sub(5, name="Foo")
    TypeError: 'name' is an invalid keyword argument for this function
    

    super()

    也许有人对多重继承有更深入的了解,可以为我指明正确的方向?

    更新:

    这是我最终的解决方案,基于 Alex's answer .

    它还是有点粗糙(由常宁) __new__ 但只要超类在子类的mro中出现在内置类型和定义之前,它就可以工作

    >>> class Super(object):
        name = None
        def __new__(cls, *args, name=None, **kwargs):
            inner = super().__new__(cls, *args, **kwargs)
            inner.name = name
            return inner
    
    >>> class Sub(Super, int):
        pass
    
    >>> Sub(5)
    5
    
    >>> Sub(5, name="Foo")
    5
    
    >>> _.name
    'Foo'
    
    1 回复  |  直到 7 年前
        1
  •  3
  •   Alex Martelli    14 年前

    您只是不能将任意参数(无论是位置参数还是命名参数)传递给一个同样任意的超类(即“在 mro 不管当前的叶类型是什么,大多数类型和类都不接受任意参数,这也是很好的理由 Zen of Python ,

    Errors should never pass silently.
    Unless explicitly silenced.
    

    在大多数情况下,打电话 int(name='booga') 当然是个错误。

    class Super 为了能够“传递”任意参数,您还必须确保在它之后用作基的所有类都可以处理它——例如, int class Sub 从推卸责任中继承 Super int,必须输入,例如:

    class Int(int):
        def __new__(cls, *a, **k):
            return int.__new__(Int, a[0] if a else 0)
    

    请注意,您必须覆盖 __new__ , __init__ 覆盖后者,但无论如何都不相关): 是不可变的,因此必须将值设置为 __新建__

    现在 ,比如

    >>> class X(Super, Int): pass
    ... 
    >>> X(23, za='zo')
    23
    >>> 
    

    工作。但请注意 X 必须从子类 Int __新建__ -消毒版 内景 ), 内景 __新建__ !-)