Coding exception classes, I came across this error:
TypeError: object.__new__(A) is not safe, use Exception.__new__()
There's a similar question posted here:
TypeError: object.__new__(int) is not safe, use int.__new__(). So __new__
was deprecated for the following reason:
[Python-Dev] __new__
deprecation
Guido van Rossum
"The message means just what it says. :-) There's no point in calling
object.__new__()
with more than a class parameter, and any code that did so was just dumping those args into a black hole."
But the warning in 3.3 that I get "is not safe" is scary. I try to understand the implication of using object.__new__
, let's consider this example:
>>> class A(Exception):
... def __new__(cls, *args):
... return object.__new__(A)
...
>>> A()
TypeError: object.__new__(A) is not safe, use Exception.__new__()
Fails miserably. Another Example:
>>> class A(object):
... def __new__(cls, *args):
... return object.__new__(A)
...
>>>
>>> A()
<__main__.A object at 0x0000000002F2E278>
works fine. Although, object
is a builtin class just like Exception
with respect to their roles, they share the trait of being builtin-classes. Now with Exception
, the first example raises TypeError
, but with object
, it does not?
(a) What are the downsides of using object.__new__
that made Python to raise the error (TypeError:...is not safe...
) in the first Example?
(b) What sort of checking Python performs before to calling __new__
? Or: What is the condition that makes Python raise the error in the first example?
__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 .
__new__ is the first step of instance creation. It's called first, and is responsible for returning a new instance of your class. In contrast, __init__ doesn't return anything; it's only responsible for initializing the instance after it's been created.
__new__ is a static method, not a class method.
__new__ returns a instance of class. __init__ receives the instances of the class returned by __new__ . Use __init__ to initilize value.
There is no problem in calling object.__new__
, but there is a problem in not calling Exception.__new__
.
Exception
class was designed in such way that it is crucial that its __new__
must be called, so it complains if that is not done.
There was a question why this happens only with built-in classes. Python in fact does it with every class which is programmed to do that.
Here is a simplified poor-mans implementation of the same mechanism in a custom class:
class A(object):
def __new__(cls):
rtn = object.__new__(cls)
rtn.new_called = True
return rtn
def __init__(self):
assert getattr(self,'new_called',False), \
"object.__new__ is unsafe, use A.__new__"
class B(A):
def __new__(cls):
return object.__new__(cls)
And now:
>>> A()
<__main__.A object at 0x00000000025CFF98>
>>> B()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __init__
AssertionError: object.__new__ is unsafe, use A.__new__
As a side note, this example from the question actually has two errors:
>>> class A(Exception):
... def __new__(cls, *args):
... return object.__new__(A)
The first is that __new__
is called on object
, thus ignoring Exception.__new__
.
The other, just as severe is that A
is passed to __new__
instead of cls
, which hinders all classes inherited from A
.
See this example:
class A(object):
def __new__(cls):
return object.__new__(A) # The same erroneous line, without Exception
class B(A):
pass
And now B()
does not create an instance of B
:
>>> B()
<__main__.A object at 0x00000000025D30B8>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With