Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does object.__new__ with arguments work fine in Python 2.x and not in Python 3.3+?

Why does the following code work fine in Python 2.x and not in Python 3.3+:

class TestA(object):
    def __new__(cls, e):
        return super(TestA, cls).__new__(TestB, e)

class TestB(TestA):
    def __init__(self, e):
        print(self, e)

TestA(1)

Python 2.7.6 output:

(<__main__.TestB object at 0x7f6303378ad0>, 1)

Python 3.1.5 output:

__main__:3: DeprecationWarning: object.__new__() takes no parameters
<__main__.TestB object at 0x7f2f69db8f10> 1

Python 3.2.3 and 3.2.5 output:

<__main__.TestB object at 0xcda690> 1

Python 3.3.5 and 3.4.1 output:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __new__
TypeError: object() takes no parameters
like image 844
tbicr Avatar asked Jul 01 '14 14:07

tbicr


People also ask

How do you instantiate an object in Python?

In short, Python's instantiation process starts with a call to the class constructor, which triggers the instance creator, . __new__() , to create a new empty object. The process continues with the instance initializer, . __init__() , which takes the constructor's arguments to initialize the newly created object.

What is new method in Python?

__new__ method will be called when an object is created and __init__ method will be called to initialize the object. In the base class object , the __new__ method is defined as a static method which requires to pass a parameter cls .

What does __ class __ mean in Python?

__class__ is an attribute on the object that refers to the class from which the object was created. a. __class__ # Output: <class 'int'> b. __class__ # Output: <class 'float'> After simple data types, let's now understand the type function and __class__ attribute with the help of a user-defined class, Human .

Can objects be passed as arguments Python?

A function can take multiple arguments, these arguments can be objects, variables(of same or different data types) and functions.


2 Answers

object.__new__ has always ignored extra arguments, and has issued a DeprecationWarning at least since Python 2.6.

The reason why you aren't seeing the DeprecationWarning in 2.7 and 3.2 is that since 2.7 and 3.2 DeprecationWarning has been suppressed by default; if you use python -Wd or PYTHONWARNINGS=default then you will see the warning.

In Python 3.3 the DeprecationWarning was converted to an error.

The correct way to write your code (in any version of Python) is to swallow the extra argument in TestA.__new__:

class TestA(object):
    def __new__(cls, e):
        return super(TestA, cls).__new__(TestB)

Since TestB is derived from TestA, the extra argument will be passed to TestB.__init__.

like image 93
ecatmur Avatar answered Sep 21 '22 15:09

ecatmur


You can move the __init__ function to TestA like so:

class TestA(object):
    def __new__(cls, e):
        return super(TestA, cls).__new__(TestA)

    def __init__(self, e):
        print(self, e)

TestA(1)

Notice how TestB is not required.

Notice how the 'e' parameter is omitted from the call to object.__new__. The new function of object class only takes a class as parameter and any additional parameters in the overloaded __new__ function (in this case that of class TestA) is automatically passed to the constructor function (__init__) of the classed passed to object.__new__ (which in this case is also TestA).

like image 27
Dewald Abrie Avatar answered Sep 23 '22 15:09

Dewald Abrie