【问题标题】:Python multiple inheritance of __new__ and __init__ with a string and second class带有字符串和第二类的 __new__ 和 __init__ 的 Python 多重继承
【发布时间】:2013-05-26 10:35:14
【问题描述】:

我正在尝试创建一个继承自 str 类型和第二个类的派生类。这是有问题的,因为str 类型不是简单地调用__init__,而是__new__ 方法,因为它的不变性。我知道要让__init__ 和 super 正常工作,您需要一直使用相同的调用结构。但是以下实现失败:

class base(object):
    def __new__(cls, *args, **kwargs):
        print "NEW  BASE:", cls, args, kwargs
        return super(base, cls).__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        print "INIT BASE", args, kwargs

class foo(base, str):
    def __new__(cls, *args, **kwargs):
        return super(foo, cls).__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        super(foo, self).__init__(*args, **kwargs)

这里foo('cat') 与:

>> NEW  BASE: <class '__main__.foo'> ('cat',) {}
>> INIT BASE ('cat',) {}

但是有一个参数foo('cat', x=3),它失败了:

>> NEW  BASE: <class '__main__.foo'> ('cat',) {'x': 3}
Traceback (most recent call last):
  File "inh.py", line 19, in <module>
    foo('cat', x=3)
  File "inh.py", line 12, in __new__
    return super(foo, cls).__new__(cls, *args, **kwargs)
  File "inh.py", line 4, in __new__
    return super(base, cls).__new__(cls, *args, **kwargs)
TypeError: str() takes at most 1 argument (2 given)

我可以通过将base.__new__ 方法更改为:

def __new__(cls, *args, **kwargs):
    return super(base, cls).__new__(cls)

但现在我改变了调用结构,我觉得这会在以后给我带来麻烦。

如何正确地从字符串和第二个类继承?

【问题讨论】:

    标签: python inheritance multiple-inheritance super abc


    【解决方案1】:

    你不能只做

    def __new__(cls, *args, **kwargs):
        return super(base, cls).__new__(cls)
    

    因为这将导致对 str 的 new 的错误调用(您将不会传递允许的参数

    >>> foo('t')
    NEW  BASE: <class '__main__.foo'> ('t',) {}
    INIT BASE ('t',) {}
    ''
    

    你应该做类似的事情

    def __new__(cls, *args, **kwargs):
        return super(base, cls).__new__(cls, *args[:1])
    

    但是,如果您将base 类用作__new__ 方法接受多个参数的类的mixin,这可能会破坏某些东西。

    作为一个选项,您应该从 str 继承类,但重写 new 方法:

    class CarelessStr(str):
        def __new__(cls, *args, **kwargs):
            return super(CarelessStr, cls).__new__(cls, *args[:1])
    
    class foo(base, CarelessStr):
        def __new__(cls, *args, **kwargs):
            return super(foo, cls).__new__(cls, *args, **kwargs)
    
        def __init__(self, *args, **kwargs):
            super(foo, self).__init__(*args, **kwargs)
    

    【讨论】:

    • 你说得对,我的 new 没有通过第一个参数。但是,您的解决方案似乎有点痛苦,因为它增加了另一层间接性。诚然,它有效,但它被认为是 Python 的方式吗?
    • 我不确定是否有针对所描述任务的通用解决方案。我同意这个解决方案增加了另一层间接性。但在某些情况下,这可能是唯一的选择。
    • 太棒了。我没有想到一个额外的 str 基础!
    猜你喜欢
    • 1970-01-01
    • 2021-11-23
    • 2013-10-18
    • 2021-11-28
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    • 2012-01-31
    相关资源
    最近更新 更多