pythonoopprivate-members

Accessing private variables when there's a getter/setter for them


I have a question about righteous way of programming in Python... Maybe there can be several different opinions, but here it goes:

Let's say I have a class with a couple of private attributes and that I have implemented two getters/setters (not overloading __getattr__ and __setattr__, but in a more “Java-tistic” style):

class MyClass:

    def __init__(self):   
        self.__private1 = "Whatever1"

    def setPrivate1(self, private1):
        if isinstance(private1, str) and (private1.startswith("private")):
            self.__private1 = private1
        else:
            raise AttributeError("Kaputt")

    def getPrivate1(self):
        return self.__private1

Now let's say a few lines below, in another method of the same class, I need to re-set the value of that “__private1”. Since it's the same class, I still have direct access to the private attribute self.__private1.

My question is: Should I use:

self.setPrivate1("privateBlaBlaBla")

or should I access directly as:

self.__private1 ="privateBlaBlaBla"

since I am the one setting the new value, I know that said value (“privateBlaBlaBla”) is correct (an str() that starts with “private”), so it is not going to leave the system inconsistent. On the other hand, if another programmer takes my code, and needs to change the functionality for the self.__private1 attribute, he will need to go through all the code, and see if the value of __private1 has been manually set somewhere else.

My guess is that the right thing to do is to always using the setPrivate1 method, and only access directly the __private1 variable in the get/set, but I'd like to know the opinion of more experienced Python programmers.


Solution

  • You can't present a classic example of bad Python and then expect people to have opinions on what do to about it. Use getters and setters.

    class MyClass:
        def __init__(self):   
            self._private1 = "Whatever1"
    
        @property
        def private1(self):
            return self._private1
    
        @private1.setter
        def private1(self, value):
            self._private1 = value
    

    A side comment -- using double underscore names can be confusing, because Python actually mangles the name to stop you accessing them from outside the class. This provides no real security, but causes no end of headaches. The easiest way to avoid the headaches is to use single-underscore names, which is basically a universal convention for private. (Ish.)


    If you want an opinion -- use properties =). If you want an opinion on your JavaPython monstrosity, I would use the setter -- after all, you've written it, that's what it's there for! There's no obvious benefit to setting the variable by hand, but there are several drawbacks.