使用多个 __init__ 参数子类化元组
问题描述
以下代码有效:
class Foo(tuple):
def __init__(self, b):
super(Foo, self).__init__(tuple(b))
if __name__ == '__main__':
print Foo([3, 4])
$ python play.py
结果:
play.py:4: DeprecationWarning: object.__init__() takes no parameters
super(Foo, self).__init__(tuple(b))
(3, 4)
但不是以下:
class Foo(tuple):
def __init__(self, a, b):
super(Foo, self).__init__(tuple(b))
if __name__ == '__main__':
print Foo(None, [3, 4])
$ python play.py
结果:
Traceback (most recent call last):
File "play.py", line 7, in <module>
print Foo(None, [3, 4])
TypeError: tuple() takes at most 1 argument (2 given)
为什么?
解决方案
因为元组是不可变的,所以你必须重写 __new__
:
Because tuples are immutable, you have to override __new__
instead:
python 文档
object.__new__(cls[, ...])
调用创建一个新的实例类 cls
.__new__()
是一个静态的方法(特殊情况,所以你不需要声明它这样),这需要实例所在的类请求作为它的第一个参数.这剩下的参数是那些通过的到对象构造函数表达式(对班级的呼吁).回报__new__()
的值应该是新的对象实例(通常是一个实例cls
).
Called to create a new instance of
class cls
. __new__()
is a static
method (special-cased so you need not
declare it as such) that takes the
class of which an instance was
requested as its first argument. The
remaining arguments are those passed
to the object constructor expression
(the call to the class). The return
value of __new__()
should be the new
object instance (usually an instance
of cls
).
典型的实现创建一个新的通过调用类的实例超类的 __new__()
方法使用super(currentclass, cls).__new__(cls[, ...])
带有适当的参数和然后修改新创建的在返回之前根据需要实例它.
Typical implementations create a new
instance of the class by invoking the
superclass’s __new__()
method using
super(currentclass, cls).__new__(cls[, ...])
with appropriate arguments and
then modifying the newly-created
instance as necessary before returning
it.
如果 __new__()
返回一个实例cls
,然后是新实例的__init__()
方法将像 __init__(self[, ...])
一样被调用,其中 self 是新实例,其余的参数与传递的相同到 __new__()
.
If __new__()
returns an instance of
cls
, then the new instance’s
__init__()
method will be invoked like __init__(self[, ...])
, where self is the new instance and the remaining
arguments are the same as were passed
to __new__()
.
如果 __new__()
不返回cls
的实例,然后是新的实例的 __init__()
方法不会被调用.
If __new__()
does not return an
instance of cls
, then the new
instance’s __init__()
method will not
be invoked.
__new__()
主要是为了允许不可变类型的子类(比如int
、str
或 tuple
) 来自定义实例创建.这也很常见在自定义元类中被覆盖为了自定义类创建.
__new__()
is intended mainly to allow subclasses of immutable types (like
int
, str
, or tuple
) to customize
instance creation. It is also commonly
overridden in custom metaclasses in
order to customize class creation.
相关文章