Search code examples
pythonpython-3.xclassinstance

Catch if someone tries to set a class instance's variable directly


Assume that I have a class which requires pre-treatment of an input variable x. Towards this end, I have implemented a function within this class to set the variable (including the pre-treatment). To fool-proof the algorithm, I would like to know whether there is a way to catch attempts of users trying to set x manually, instead of calling the correct function. As a small dummy example, consider the following:

class dummy(): 
    def __init__(self, x):
        # This function initializes the instance
        self.x = x
    
    def adjust_x(self):
        # This function makes some change to x
        self.x += 5
        
    def set_x(self, x):
        # This function initializes x correctly
        self.x = x
        self.adjust_x()
        
instance = dummy(3)
print('Initialized correctly, the value of x is: ' + str(instance.x))

# We can also set x later on, using the correct function
instance.set_x(3)
print('Calling the function to set x, we get: ' + str(instance.x))

# However, if the user would try to set x directly, the variable does not get
# correctly adjusted:
instance.x = 3
print('Direct setting: ' + str(instance.x) + ' (/= 8, because instance.adjust_x() was not called)')

Is there a way to catch someone using instance.x to set x? I'd like to raise an error or a warning in that situation.


Solution

  • In Python, you can restrict the access of an attribute (that's the equivalent of setting the access modifier of a field to private) by prepending a double underscore to the attribute.

    Example

    class Object():
      def __init__(self, name):
        self.__name = name
    

    Trying to access instance.name or instance.__name would raise an AttributeError.

    Note

    As @mkrieger1 pointed out, the double underscores were not meant to prevent access but I find it that it works. More about private variables in Python can be found here.