2

MyClass which is defined below accepts a single argument arg.

class MyClass(object):
    def __init__(self, arg):
        super(MyClass, self).__init__()
        if not isinstance(arg, int):
            return None
        else:
            self.arg = arg

If the incoming argument arg is not an integer I would like to return None instead of the instance of MyClass.

a = MyClass(arg='Text Argument')

But even while MyClass constructor __init__ returns None when the arg is not an integer the resulting variable a is still an instance of MyClass:

print a
<__main__.MyClass object at 0x0000000001FDEFD0>

How to make sure the variable a remains None if MyClass is given a non-integer argument?

0

2 Answers 2

5

You should not return None from a constructor, even if it was possible. The result of MyClass() should always be an instance of MyClass or a compatible class; anything else would be Very Surprising And Error Inducing Behaviour™.

You could do this with a custom __new__ method, which creates the actual instance. But again, I would not recommend it.

You should be raising an exception if the object cannot be constructed with the given data:

class MyClass(object):
    def __init__(self, arg):
        super(MyClass, self).__init__()
        if not isinstance(arg, int):
            raise TypeError('arg must be an int')

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

3 Comments

Explicitly returning None is OK (or just return by itself) since that's what will happen by default. You could do it early to exit the __init__() method early, I suppose, but doing so doesn't affect whether the instance gets created or not—just possibly the initial state it's given.
True, that was worded somewhat ambiguously. I meant if the return value would make any difference, you still shouldn't do it.
Regardless of what you meant, my point was that what you're saying isn't accurate: Not only is it possible, there's conceivably a reason to do it knowing full well that it's not going to prevent the instance from being created. Which doesn't appear to be what the OP wishes to accomplish.
2

You generally should not be doing this, but you could if you want to, by overriding your __new__, where the new instance is created:

class MyClass(object):
    def __new__(cls, **kwargs):
        if not isinstance(kwargs['arg'], int):
            return None
        return super(MyClass, cls).__new__(cls, **kwargs)

    def __init__(self, arg):
        super(MyClass, self).__init__()
        self.arg = arg

The __init__ method does not create the instance, it only initializes it, returning None from it is what is expected.

In the case __new__ returns an object that is not an instance (like None in this case), __init__ will not be called.

One of the reasons why you should not use the above is the following:

print isinstance(MyClass(arg='666'), MyClass) #-> False
# waaah!

A lot of things will start to break in your code, and the above is only just one example.

Comments

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.