Why can't I subclass a tuple in python3?

Let the preface to this question say , you should use immutable objects __new__instead of a __init__subclass .

With that said, see the following code:

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

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

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

Why is this happening? What has changed in python3?

+6
source share
2 answers

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__ 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 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.

*/
+5

C- C, () , , python3. python2.7, python3.3, python3.5 python3.6. , , python2.7. , , ...

-, , tuple.__init__ , tuple . __init__ . , - tuple.__init__ , , . , __new__ (, , ).

+1

Source: https://habr.com/ru/post/1665282/


All Articles