views:

87

answers:

2

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.

Thank you!

+2  A: 

Neither. In Python, use properties, not getters and setters.

class MyClass:

    def __init__(self):   
        self._private1 = "Whatever1"
    @property
    def private1(self):
        return self._private1
    @private1.setter
    def private1(self, private1):
        if isinstance(private1, str) and (private1.startswith("private")):
            self._private1 = private1
        else:
            raise AttributeError("Kaputt")

Then later on in your code, set the _private1 attribute with

self.private1="privateBlaBlaBla"
unutbu
+4  A: 

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.

katrielalex
+1 Two of those drawback are: (1) you have to type that monstrosity the name gets mangeled into and (2) it might introduce subtle bugs if the setter starts doing important work in the future.
delnan
This is very cool, and it's something I hadn't paid attention to but it doesn't seem to work with python 2.4 (the setter part) even if I extend my class from "object" (works fine with 2.6, though)
BorrajaX
@BorrajaX: In Python2.4, use `private1 = property(getx,setx)`, where `getx` is the getter function and `setx` is the setter. See http://docs.python.org/library/functions.html#property
unutbu
@unutbu: Yeah, I saw why it isn't working so straight forward with 2.4 (http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Properties) But your answers have been very helpful! :-) Thanks a lot! To tell the truth, I hadn't paid much attention to the decorators, but they're really interesting.
BorrajaX