Best way to set/get an object property

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Mon Aug 25 05:31:14 EDT 2008


On Sun, 24 Aug 2008 23:56:27 -0700, Hussein B wrote:

> On Aug 24, 7:12 pm, Steven D'Aprano <st... at REMOVE-THIS-
> cybersource.com.au> wrote:

>> >> I noted that Python encourage the usage of: -- obj.prop = data
>> >> x = obj.prop
>> >> --
>> >> to set/get an object's property value. What if I want to run some
>> >> logic upon setting/getting a property? What is Python preferred
>> >> method to do so (using the new feature 'property')? I don't think
>> >> __getattr__ and __setattr__ are practical (I have to code the
>> >> property name into them).
...
>> I think the actual answer to his question is that properties are the
>> preferred way to "run some logic upon setting/getting" an attribute,
>> that is, to implement getters and setters.
>>
>> Hussein, the Java habit of writing setters and getters for everything
>> isn't considered good practice in Python, but if you need them, that's
>> exactly what the property() function is for.
>>
>> --
>> Steven
> 
> Thank you Steven :)
> --
> public class JClass {
>   private int answer; // property
> }
> --
> class PyClass(object):
>   doc __init__(self):
>     self.answer = None
> --
> AFAIUY (understand you), what it is called a property in Java, it is
> called an attribute in Python?
> Why Python encourages direct access to object's attributes?  aren't
> setters/getters considered vital in OOP (encapsulation)?
> Thank you all for your time and help.


Hussein, first let me ask you to please stop using "--" as a separator 
around code. Many News clients, including mine, expect -- on a line by 
itself to mean "everything from here on is the writer's signature", and 
consequently that makes it harder to reply correctly to your posts. I had 
to manually copy and paste your text in order to quote it. Perhaps you 
could use === or +++ or ***  as a separator?


Now, back to your actual question... 

I'm not a Java coder, so the following should be read as my opinion. 
Python attributes are equivalent to Java _public_ properties, not 
private. If you can write:

public class JClass {
   public int answer;
}

then that would be more or less equivalent to Python's

class PyClass(object):
    def __init__(self):
        self.answer = None


Yes, Python does encourage direct access to an object's attributes. The 
Python philosophy is "we're all adults here". If coders wish to shoot 
themselves in the foot by accessing clearly marked private attributes, 
then the language can't stop them and shouldn't try. It's easy to bypass 
such private/public protection in C++, and harder, but still possible, in 
Java.

The Python development team is certainly aware that such a tactic 
introduces some costs, by reducing encapsulation, but it also has many 
benefits (e.g. less boilerplate getter/setter methods, faster development 
time). It is their belief that such costs are worth paying in order to 
get the benefits. That's the philosophy of the language. Python is not 
trying to be Java, and Java should not try to be Python.

Python does not enforce private attributes. By convention attributes 
starting with a single underscore are considered "private -- don't touch 
unless you know what you're doing". Attributes starting with a double 
underscore are "really private", and Python mangles the name to (almost) 
enforce it.

Example:

def Parrot(object):
    colour = 'red'  # public, free to use
    _windspan = 15  # semi-private, use it at your own risk
    __species = 'Norwegian Blue'  # mangled to _Parrot__species


But it's quite rare to see double-underscore "really private" attributes 
in Python code. It is considered to go against the spirit of the language.

I'm told that in Java it is quite difficult to change a class from using 
public attributes to getters/setters, and therefore many Java developers 
prefer to use getters/setters right from the beginning. But in Python it 
is very easy to change from a bare attribute to a computed property 
without messing up calling code. So there's no advantage to writing 
something like this:

class Foo(object):
    def __init__(self):
        self.__x = None  # private attribute
    def setx(self, x):  # setter
        self.__x = x
    def getx(self):  # getter
        return self.__x
    x = property(getx, setx)


That is considered a waste of time in Python circles and is strongly 
discouraged.

You should read "Python Is Not Java" and "Java Is Not Python Either":

http://dirtsimple.org/2004/12/python-is-not-java.html

http://dirtsimple.org/2004/12/java-is-not-python-either.html




-- 
Steven



More information about the Python-list mailing list