从str派生的类的构造方法,具有不同的签名

时间:2012-09-22 23:43:44

标签: python string python-2.x

我正在尝试基于str创建一个简单的派生类,并添加了一个实例变量flag。由于我不明白的原因,如果我尝试将标志传递给构造函数,我会收到错误:

>>> class Strvalue(str):
        def __init__(self, content, flag=None):
                str.__init__(self, content)
                self.flag = flag

>>> Strvalue("No problem")
'No problem'

>>> Strvalue("Problem", flag=None)
Traceback (most recent call last):
  File "<pyshell#113>", line 1, in <module>
    Strvalue("Problem", flag=None)
TypeError: str() takes at most 1 argument (2 given)

我已经检查过,在成功的调用中,Strvalue构造函数确实被调用了 - 我没有错误输入__init__或类似的东西。那是怎么回事?

编辑根据this question(和@ Martijn的回答),通过覆盖__new__可以避免问题。问题是为什么这种情况正在发生。

2 个答案:

答案 0 :(得分:1)

在对__new__进行子类化时,您需要使用__init__而不是str,请参阅basic customization

>>> class Strvalue(str):
...     def __new__(cls, content, flag=None):
...         inst = str.__new__(cls, content)
...         inst.flag = flag
...         return inst
... 
>>> Strvalue('foo', True)
'foo'
>>> foo = Strvalue('foo', True)
>>> foo
'foo'
>>> foo.flag
True

您的代码不会覆盖str.__new__,因此使用您的两个参数调用原始str.__new__构造函数,并且它只接受一个。

str个对象是不可变的,它们在__new__中构造一个新实例,然后不再被更改;在调用__init__时,self是一个不可变对象,因此__init__的{​​{1}}没有意义。您仍然可以 定义str方法,但由于您已经拥有__init__,因此实际上没有必要将工作分为两种方法。

答案 1 :(得分:1)

您需要覆盖__new__而不是{或1}} {/ 1}}。