为什么我不能在 python3 中子类化元组? [英] Why can't I subclass tuple in python3?

查看:40
本文介绍了为什么我不能在 python3 中子类化元组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们先说这个问题,你应该使用 __new__ 代替 __init__ 用于子类化不可变对象.

Let's preface this question by saying that you should use __new__ instead of __init__ for subclassing immutable objects.

话虽如此,让我们看看以下代码:

With that being said, let's see the following code:

class MyTuple(tuple):
    def __init__(self, *args):
        super(MyTuple, self).__init__(*args)

mytuple = MyTuple([1,2,3])

这适用于python2,但在python3中我得到:

This works in python2, but in python3 I get:

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

为什么会这样?python3有什么变化?

Why does this happen? What changed in python3?

推荐答案

Python 3 改变了 object.__new__object.__init__ 在被覆盖时对参数的反应方式.如果一个类覆盖(或继承覆盖的方法)object.__init__object.__new__object.__init__object.__new__ 如果收到任何多余的参数,将抛出异常.在 Python 2 中,这会产生 DeprecationWarning(默认情况下被禁止).

Python 3 changed how object.__new__ and object.__init__ react to arguments when both are overridden. If a class overrides (or inherits methods that override) both object.__init__ and object.__new__, object.__init__ and object.__new__ will throw an exception if they receive any excess arguments. In Python 2, that would have given a DeprecationWarning (suppressed by default).

tuple 没有自己的 __init__.它继承了 object.__init__,因此您实际上是将一堆参数传递给 object.__init__,而 object.__init__ 不接受这些参数.Python 2 给你一个(被抑制的)警告,而 Python 3 使它成为一个错误.

tuple doesn't have its own __init__. It inherits object.__init__, so you're actually passing a bunch of arguments to object.__init__ that object.__init__ doesn't take. Python 2 was giving you a (suppressed) warning, and Python 3 is making it an error.

代码有一个注释很好地解释了 object.__init__object.__new__ 对额外参数的微妙处理:

The code has a comment that does a good job of explaining object.__init__ and object.__new__'s subtle handling of extra arguments:

/* 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.

*/

这篇关于为什么我不能在 python3 中子类化元组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆