2

我遇到了这样一种情况,即子类化 unicode 会导致 Python 3.3 之前的弃用警告和 Python 3.3 上的错误:

# prove that unicode.__init__ accepts parameters
s = unicode('foo')
s.__init__('foo')
unicode.__init__(s, 'foo')

class unicode2(unicode):
    def __init__(self, other):
        super(unicode2, self).__init__(other)

s = unicode2('foo')

class unicode3(unicode):
    def __init__(self, other):
        unicode.__init__(self, other)

s = unicode3('foo')

奇怪的是,警告/错误不会出现在前三行,而是出现在第 8 行和第 14 行。这是 Python 2.7 的输出。

> python -Wd .\init.py
.\init.py:8: DeprecationWarning: object.__init__() takes no parameters
  super(unicode2, self).__init__(other)
.\init.py:14: DeprecationWarning: object.__init__() takes no parameters
  unicode.__init__(self, other)

代码被简化以举例说明问题。在现实世界的应用程序中,我会执行的不仅仅是调用 super __init__

从 unicode 类实现的前三行可以看出,__init__该方法至少接受一个参数。但是,如果我想从子类调用该方法,无论我是否调用,我似乎都无法这样做super()

为什么可以调用unicode.__init__unicode 实例但不能调用 unicode 子类?如果子类化 unicode 类,作者该怎么办?

4

1 回答 1

4

我怀疑这个问题来自unicode不可变的事实。

实例创建后unicode无法修改。因此,任何初始化逻辑都将在__new__方法中(被调用以创建实例),而不是__init__(仅在实例存在后调用)。

不可变类型的子类没有相同的严格要求,因此您可以根据需要做一些事情unicode2.__init__,但调用unicode.__init__是不必要的(而且可能不会做您认为它会做的事情)。

更好的解决方案可能是用您自己的__new__方法执行您的自定义逻辑:

class unicode2(unicode):
    def __new__(cls, value):
        # optionally do stuff to value here
        self = super(unicode2, cls).__new__(cls, value)
        # optionally do stuff to self here
        return self

You can make your class immutable too, if you want, by giving it a __setattr__ method that always raises an exception (you might also want to give the class a __slots__ property to save memory by omitting the per-instance __dict__).

于 2013-02-09T01:28:23.520 回答