3

我正在尝试创建一个基于 的简单派生类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__或类似的东西。那么发生了什么?

编辑:根据这个问题(和@Martijn 的回答),这个问题也可以通过覆盖来避免__new__。问题是为什么会这样。

4

2 回答 2

2

您需要在子类化时使用__new__而不是,请参阅基本自定义__init__str

>>> 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__forstr没有意义。您仍然可以定义一个__init__方法,但是由于您已经有了__new__,因此实际上没有必要将工作划分为两个方法。

于 2012-09-22T23:49:01.897 回答
1

您需要覆盖__new__而不是(或以及)__init__

于 2012-09-22T23:49:06.453 回答