Correct approach to validate attributes of an instance of class

You can use Python properties to cleanly apply rules to each field separately, and enforce them even when client code tries to change the field:

class Spam(object):
    def __init__(self, description, value):
        self.description = description
        self.value = value

    @property
    def description(self):
        return self._description

    @description.setter
    def description(self, d):
        if not d: raise Exception("description cannot be empty")
        self._description = d

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, v):
        if not (v > 0): raise Exception("value must be greater than zero")
        self._value = v

An exception will be thrown on any attempt to violate the rules, even in the __init__ function, in which case object construction will fail.

UPDATE: Sometime between 2010 and now, I learned about operator.attrgetter:

import operator

class Spam(object):
    def __init__(self, description, value):
        self.description = description
        self.value = value

    description = property(operator.attrgetter('_description'))

    @description.setter
    def description(self, d):
        if not d: raise Exception("description cannot be empty")
        self._description = d

    value = property(operator.attrgetter('_value'))

    @value.setter
    def value(self, v):
        if not (v > 0): raise Exception("value must be greater than zero")
        self._value = v

If you only want to validate the values when the object is created AND passing in invalid values is considered a programming error then I would use assertions:

class Spam(object):
    def __init__(self, description:str, value:int):
        assert description != ""
        assert value > 0
        self.description = description
        self.value = value

This is about as concise as you are going to get, and clearly documents that these are preconditions for creating the object.

Tags:

Python