gon*_*opp 6 python tuples subclass python-3.x
让我们先说这个问题,你应该使用__new__而不是__init__用于子类化不可变对象.
话虽如此,让我们看看以下代码:
class MyTuple(tuple):
def __init__(self, *args):
super(MyTuple, self).__init__(*args)
mytuple = MyTuple([1,2,3])
Run Code Online (Sandbox Code Playgroud)
这适用于python2,但在python3中,我得到:
Traceback (most recent call last):
File "tmp.py", line 5, in <module>
mytuple = MyTuple([1,2,3])
File "tmp.py", line 3, in __init__
super(MyTuple, self).__init__(*args)
TypeError: object.__init__() takes no parameters
Run Code Online (Sandbox Code Playgroud)
为什么会这样?python3有什么变化?
当重写两者时,Python 3改变了对参数的反应object.__new__和object.__init__反应.如果一个类重写(或继承覆盖的方法)object.__init__和object.__new__,object.__init__并且object.__new__如果它们收到任何多余的参数将抛出异常.在Python 2中,这将给出DeprecationWarning(默认情况下被禁止).
tuple没有自己的__init__.它继承了object.__init__,所以你实际上传递了一堆论据object.__init__是object.__init__不走.Python 2给你一个(压制)警告,而Python 3正在使它成为一个错误.
代码有一个注释,可以很好地解释object.__init__和object.__new__微妙处理额外的参数:
/* You may wonder why object.__new__() only complains about arguments
when object.__init__() is not overridden, and vice versa.
Consider the use cases:
1. When neither is overridden, we want to hear complaints about
excess (i.e., any) arguments, since their presence could
indicate there's a bug.
2. When defining an Immutable type, we are likely to override only
__new__(), since __init__() is called too late to initialize an
Immutable object. Since __new__() defines the signature for the
type, it would be a pain to have to override __init__() just to
stop it from complaining about excess arguments.
3. When defining a Mutable type, we are likely to override only
__init__(). So here the converse reasoning applies: we don't
want to have to override __new__() just to stop it from
complaining.
4. When __init__() is overridden, and the subclass __init__() calls
object.__init__(), the latter should complain about excess
arguments; ditto for __new__().
Use cases 2 and 3 make it unattractive to unconditionally check for
excess arguments. The best solution that addresses all four use
cases is as follows: __init__() complains about excess arguments
unless __new__() is overridden and __init__() is not overridden
(IOW, if __init__() is overridden or __new__() is not overridden);
symmetrically, __new__() complains about excess arguments unless
__init__() is overridden and __new__() is not overridden
(IOW, if __new__() is overridden or __init__() is not overridden).
However, for backwards compatibility, this breaks too much code.
Therefore, in 2.6, we'll *warn* about excess arguments when both
methods are overridden; for all other cases we'll use the above
rules.
*/
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
955 次 |
| 最近记录: |