Search code examples
pythonvariable-assignmentsetattr

How to restrict setting an attribute outside of constructor?


I want to forbid further assignments on some attributes of a class after it was initialized. For instance; no one can explicitly assign any value to 'ssn' (social security number) property after the Person instance 'p' has been initialized. _setattr_ is also being called while assigning the value inside _init_ method, thus it is not what I want. I'd like to restrict only further assignments. How can I achieve that?

class Person(object):
    def __init__(self, name, ssn):
        self.name = name
        self._ssn = ssn

    def __setattr__(self, name, value):
        if name == '_ssn':
            raise AttributeError('Denied.')
        else:
            object.__setattr__(self, name, value)

>> p = Person('Ozgur', '1234')
>> AttributeError: Denied.

Solution

  • The usual way is to use a "private" attribute starting with an underscore, and a read-only property for public access:

    import operator
    
    class Person(object):
        def __init__(self, name, ssn):
            self.name = name
            self._ssn = ssn
        ssn = property(operator.attrgetter("_ssn"))
    

    Note that this does not really hinder anybody to change the attribute _ssn, but the leading _ documents that the attribute is private.