31

I want to set up a class that will abort during instance creation based on the value of the the argument passed to the class. I've tried a few things, one of them being raising an error in the __new__ method:

class a():
    def __new__(cls, x):
        if x == True:
            return cls
        else:
            raise ValueError

This is what I was hoping would happen:

>>obj1 = a(True)
>>obj2 = a(False)
ValueError Traceback (most recent call last)

obj1 exists but obj2 doesn't.

Any ideas?

5
  • shouldn't you override __init__(self, ...) instead? Commented Oct 5, 2010 at 21:12
  • @matt b. It's not as semantic if then intent is to stop object creation. It does work though. Commented Oct 5, 2010 at 21:28
  • @AaronMcSmooth: Why would raising an exception in __new__ be preferable to raising one in __init__. The result seems the same to me and __init__ is where all the other initialization code goes. Why shouldn't this go there as well? Commented Oct 5, 2010 at 22:04
  • @Arlaharen. because it's not initilization code. It's conditional construction code. It seems like __init__ should only throw an exception if it runs into trouble initializing the instance. Here, it's an explicit test that's being done. I'm probably just quibbling though. I would say that if you want to do it in the initializer, just try to use whatever x is and let that raise an exception or go through. Commented Oct 5, 2010 at 22:38
  • I really think that the advice one would want to give in general is to treat __init__ as the constructor. If the construction of the object needs to be aborted, for any reason, it works just as well to raise an exception there. Overriding __new__ is very rarely needed and for everyday normal classes I think it should be avoided. Doing so keeps the class implementation simple. Commented Oct 6, 2010 at 14:06

2 Answers 2

23

When you override __new__, dont forget to call to super!

>>> class Test(object):
...     def __new__(cls, x):
...         if x:
...             return super(Test, cls).__new__(cls)
...         else:
...             raise ValueError
... 
>>> obj1 = Test(True)
>>> obj2 = Test(False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __new__
ValueError
>>> obj1
<__main__.Test object at 0xb7738b2c>
>>> obj2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'obj2' is not defined

Simply returning the class does nothing when it was your job to create an instance. This is what the super class's __new__ method does, so take advantage of it.

Sign up to request clarification or add additional context in comments.

1 Comment

If I need x variable too, what should I do?
9

Just raise an exception in the initializer:

class a(object):
    def __init__(self, x):
        if not x:
            raise Exception()

2 Comments

__init__ is not the constructor, it is the initializer. You're thinking of __new__
what's wrong with doing this in the initializer?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.