dotancohen
dotancohen

Reputation: 31471

Prevent object from being created in Python constructor

How des one properly reject the creation of an object in a Python constructor? Consider an object:

class Triangle:
    def __init__(self, a, b, c):
        sides = [a, b, c]
        sides.sort()
        if sides[0]+sides[1] < sides[2]:
            return None
        self._a = a
        self._b = b
        self._c = c

If the sides are not logical for a triangle, I would like to reject the creation of a Triangle object. Returning None does not prevent the creation of the Triangle object, and returning False throws an exception. What is the proper way to handle this? Should I throw some type of exception when the wrong parameters are given?

Upvotes: 5

Views: 4897

Answers (2)

Joe
Joe

Reputation: 6757

Either raise an exception

class Triangle:
    def __init__(self, a, b, c):
        sides = [a, b, c]
        sides.sort()
        if sides[0]+sides[1] < sides[2]:
            raise ValueError('invalid triangle!')
        self._a = a
        self._b = b
        self._c = c

or use an assert (which raises an exception itself)

class Triangle:
    def __init__(self, a, b, c):
        sides = [a, b, c]
        sides.sort()
        assert sides[0]+sides[1] >= sides[2]
        self._a = a
        self._b = b
        self._c = c

Which one is more appropriate depends on if throwing on invalid values is supposed to be part of your API (first version), or only to help find programmer errors (second version, as asserts will be skipped if you pass the -O "optimized" flag to the python interpreter).

Upvotes: 11

Sylvain Leroux
Sylvain Leroux

Reputation: 51990

Returning a value (even None) from a constructor is not allowed

As you suggested, should raise an exception.

class Triangle:
    def __init__(self, a, b, c):
        sides = [a, b, c]
        sides.sort()
        if sides[0]+sides[1] < sides[2]:
            raise ValueError()
        self._a = a
        self._b = b
        self._c = c

Upvotes: 2

Related Questions