"Private" Member Variables

  • Thread starter Scott Brady Drummonds
  • Start date
S

Scott Brady Drummonds

Hi, everyone,

I'm still learning Python as I develop a medium-sized project. From my
previous experience with C++, I've burnt into my mind the notion of
information hiding. I'm having trouble understanding to what extent I
should follow this policy in my Python code so I thought I'd ask the group.

I read from a previous post that to attain a private-like status of member
variables, I should prefix the variable name with two underscores ("__").
This does work, but in another post someone asked me if this was really
necessary. Given that the very nature of the language precludes any
compile-time type dependencies I'm wondering if there is any benefit to
naming variables with leading underscores and providing accessor functions
like this:
class C:
...
def value(self):
return self.__value
...

The problems that arise from directly relying on the member variable in C++
(compile-time type dependency, as I said above) don't exist in Python. So
why provide an accessor at all? Why not just allow direct reading and
writing of the member variable? Is there something here I'm missing?

What are your thoughts? How much privacy should I build into my code?
Should I be using variables beginning with "__" and accessors? Or is that
simply not necessary (or normal) in Python code?

Thanks,
Scott
 
S

Steve Menard

Scott said:
Hi, everyone,

I'm still learning Python as I develop a medium-sized project. From my
previous experience with C++, I've burnt into my mind the notion of
information hiding. I'm having trouble understanding to what extent I
should follow this policy in my Python code so I thought I'd ask the group.

I read from a previous post that to attain a private-like status of member
variables, I should prefix the variable name with two underscores ("__").
This does work, but in another post someone asked me if this was really
necessary. Given that the very nature of the language precludes any
compile-time type dependencies I'm wondering if there is any benefit to
naming variables with leading underscores and providing accessor functions
like this:
class C:
...
def value(self):
return self.__value
...

The problems that arise from directly relying on the member variable in C++
(compile-time type dependency, as I said above) don't exist in Python. So
why provide an accessor at all? Why not just allow direct reading and
writing of the member variable? Is there something here I'm missing?

What are your thoughts? How much privacy should I build into my code?
Should I be using variables beginning with "__" and accessors? Or is that
simply not necessary (or normal) in Python code?

Thanks,
Scott

I see no problem with exposing the attribute directly, if that attribute
may be freely modified without verification. The main problem with doing
this in C++ and other languages, is that changing to a calculated value
down the road would break existing code.

In python, if an attribute suddenly needs to be validated at assignment
time, of has to be calculated at "get" time, you can make it a property.
Client code won;t see the difference.

However, for the sake of consistency, I would make all get/set accessed
that cannot be direct into properties.

Steve
 
M

Matteo Dell'Amico

Scott said:
What are your thoughts? How much privacy should I build into my code?
Should I be using variables beginning with "__" and accessors? Or is that
simply not necessary (or normal) in Python code?

The motto here is "we are all consenting adults". If the class users
need to access a variable, then why not make it directly available?

If you later notice that you'd need an accessor method, since the value
of the "variable" has got to be precomputed, then use properties[1]. For
instance:

class Rectangle(object):
def __init__(self, b, h):
self.b, self.h = b, h
def get_area(self):
return self.b * self.h
area = property(get_area)

In this case the property is read-only, but you can also put a setter if
you need it.

[1] You need new-style classes for properties, so make sure you inherit
from object or one of its descendants.
 
D

Dave Brueck

Scott said:
I'm still learning Python as I develop a medium-sized project. From my
previous experience with C++, I've burnt into my mind the notion of
information hiding. I'm having trouble understanding to what extent I
should follow this policy in my Python code so I thought I'd ask the group.

Holy cow, Scott! Congratulations - many people come to Python from other
languages and are completely unable or unwilling to believe that Python's
approach to information hiding isn't broken. Many of them, upon seeing that it
is more relaxed than C++ even postulate that Python doesn't support
object-oriented programming (which is funny, but annoying).

I'm sure other people will better answer your question, but I just wanted to
say 'thanks' because it's refreshing to hear "This is different, what are some
good practices?" as opposed to "This is different, it must be broken!".
why provide an accessor at all? Why not just allow direct reading and
writing of the member variable? Is there something here I'm missing?

What are your thoughts? How much privacy should I build into my code?
Should I be using variables beginning with "__" and accessors? Or is that
simply not necessary (or normal) in Python code?

IMO the thing that matters most is consistency. For a given class, just make
sure you go all one way or another - all direct access or all accessor
functions. I like the fact that you have the freedom to choose - some classes
are closer to C structures (they are mostly dumb data containers), so it makes
"sense" to access them in that way. Other classes more closely represent the
traditional notion of an object (data + operations on the data), so access
through functions is a cleaner interface and safeguards against fiddling with
class internals that could break things.

-Dave

P.S. The only time I use underscore prefixes is for the direct-access classes.
If I document the class as one in which you should use the accessors instead of
going direct, then I generally don't bother with the underscores.
 
H

Heather Coppersmith

On Fri, 28 May 2004 09:56:43 -0700,

[ information hiding? ]
... Why not just allow direct reading and writing of the member
variable? Is there something here I'm missing?

Why not indeed? No, there's nothing you're missing. Python takes
a "we're all adults here" philosophy. Collections of trivial
getters/setters are just clutter (and, IMHO, mean that your class
is merely encapsulating data rather than functionality; obviously,
though, there are times when that's the Right Thing).

If there's something worth "hiding," write a wrapper function,
document it, and use it. If there's nothing worth hiding, then
don't write a wrapper function, document the members, and just
access the members directly.

You know your application as well as anyone. You'll know (or
learn from experience) when it's time to present an interface to
larger functionality rather than just let the rest of the code
directly at your objects' members.

At worst, you can convert individual members to properties, and
run arbitrary code to access those properties, but explicit is
better than implicit.
What are your thoughts? How much privacy should I build into my
code? Should I be using variables beginning with "__" and
accessors? Or is that simply not necessary (or normal) in
Python code?

Just document your intentions, and stick to your documentation.

Regards,
Heather
 
M

Marcus von Appen

[...]
class C:
...
def value(self):
return self.__value
...

The problems that arise from directly relying on the member variable in C++
(compile-time type dependency, as I said above) don't exist in Python. So
why provide an accessor at all? Why not just allow direct reading and
writing of the member variable? Is there something here I'm missing?

Yes. Imagine a class, which's attributes should only be able to hold a
specific value range, e.g. a triangle, of which the side length should not
exceed 10.
If you would use the class as - let's say a third party developer and this
class does not contain an accessor nor this 'private' indicator (_ or __),
you possibly would not know about that limited value range.

You would simply type in triangle.side = 50.
Now another calculation method using that triangle object could receive
a value overflow, because it cannot calculate with such a 'big' value, but
is limited to 10.

An accessor and private attribute could avoid this:
* You would know, that the author of the class does not want you to modify
the attribute directly.
* The accessor could test the value range at input.
....
etc.pp.

You see: It makes sense for other developers, so they can easily see the
difference between your private attributes, which are not meant to be used
directly and public usable ones.

Another advantage is that your private method and attribute documentations
are not shown using 'pydoc YourClass' ;-).
What are your thoughts? How much privacy should I build into my code?
Should I be using variables beginning with "__" and accessors? Or is that
simply not necessary (or normal) in Python code?

As written above, it can make sense. You have to determine, if it is useful
for you :).

Regards
Marcus
 
D

David Bolen

Marcus von Appen said:
Yes. Imagine a class, which's attributes should only be able to hold a
specific value range, e.g. a triangle, of which the side length should not
exceed 10.
If you would use the class as - let's say a third party developer and this
class does not contain an accessor nor this 'private' indicator (_ or __),
you possibly would not know about that limited value range.

You would simply type in triangle.side = 50.
Now another calculation method using that triangle object could receive
a value overflow, because it cannot calculate with such a 'big' value, but
is limited to 10.

An accessor and private attribute could avoid this:
* You would know, that the author of the class does not want you to modify
the attribute directly.
* The accessor could test the value range at input.
...
etc.pp.

Except that Python doesn't make you use accessors to gain this
behavior. If in fact you have such a class, and yet you still want to
be able to permit users to use it in the above manner, simply make the
"side" attribute into a property (which function as accessors but
hidden behind normal attribute access syntax), and you get full
control when someone tries to assign something to do, at which point
you can validate the input all you want.

In terms of knowing that a class enforces such rules, that's something
I would expect documented by the class, regardless of implementation.

And the great thing is you can initially start out with a normal
non-property attribute, and convert it to a property at some point in
the future if you need to, without affecting any existing users of the
code (well, unless their prior use is later considered invalid, but
that would be true if you changed the rules checked by an accessor as
well).

-- David
 
I

Isaac To

Scott> The problems that arise from directly relying on the member
Scott> variable in C++ (compile-time type dependency, as I said above)
Scott> don't exist in Python. So why provide an accessor at all? Why
Scott> not just allow direct reading and writing of the member variable?
Scott> Is there something here I'm missing?

Scott> What are your thoughts? How much privacy should I build into my
Scott> code? Should I be using variables beginning with "__" and
Scott> accessors? Or is that simply not necessary (or normal) in Python
Scott> code?

The "__" convention is not about hiding, which, as others has noted, need
not exist anyway. See an example first:
.... def value(self):
.... return self.__value
.... def setvalue(self, val):
.... self.__value = val
.... Traceback (most recent call last):
File said:
dir(c) ['_C__value', '__doc__', '__module__', 'setvalue', 'value']
c._C__value 5
c._C__value = 10
c.value()
10

Now it should be clear that the outside can still access the __value within
c, although it has to be named a bit differently: _C__value. So the "__"
doesn't prevent others from accessing the field.

"__" is important for classes that simultaneously are (1) changing, and (2)
inherited by someone else. It solves a namespace issue. Suppose you are
write a class C, give it to your friend, who derive another class D from it.
In the process of deriving, your friend needs to add a collection of fields
into C. Of course, he reads the documentation of C and, like the above, the
dir() of it to see what field names to avoid. He thus derives a correct
class D from C.

But you know nothing about it. In particular, you don't know what fields
are used by your friend. You continue modify your class to improve it, and
in doing so you need to create additional private fields. Being private,
you don't document them. Then you give the class to your friend, who read
the documentation, see nothing intrusive, and use it as a plug-in
replacement of D. Unluckily, your friend won't know that the fields of your
new C actually clash with the fields of D, and when the class is in use it
gives strange behaviour, giving them a hard time debugging.

A simple technique would resolve the issue: use a naming scheme that says
"this is field f of class C". So you would name the field like "C_f"
instead of "f". But when the class name and the field name are long, this
is not an attractive solution. The "__" trick give you best of both worlds:
you avoid name clashing, and at the same time you don't need to write long
names. And as a further benefit it is fully standardized, so you don't need
to worry that the third programmer would use a different naming convention.

Regards,
Isaac.
 
A

Alan Gauld

necessary. Given that the very nature of the language precludes any
compile-time type dependencies I'm wondering if there is any benefit to
naming variables with leading underscores and providing accessor functions
like this:
class C:
...
def value(self):
return self.__value
...

There is very rarely any good reason to provide getXXX/setXXX
type accessor functions, even in C++ (JavaBeans are something
of an exception because tools need them). The whole point of
information *hiding* is that external objects can't access your
internal data, they access behaviours. Exposing your data via
accessor functions is still exposing it (albeit with control over
read/write access). But why does another object need your data?
you own it so you should manage it, if something needs doing you
should do it - via a behaviour. Indeed, there is a school of
thought in OOD that says member data is *only* there to support
the published behaviour.

Now you may want behaviour that returns a bit of data (like bank
account balance) but even in that case, conceptually the balance
could be a calculated value. But if you really must display your
internal data to the world the best way is as a property IMHO.
why provide an accessor at all? Why not just allow direct reading and
writing of the member variable? Is there something here I'm missing?

There should be very little need to access the data at all if the
class provides the needed set of ehaviours. If you have an
application where objectts are accessing other objects data then
that's usually a sign that the OO Design is broken somewhere.
What are your thoughts? How much privacy should I build into my code?

If there is tight dependency between two values such that if
somebody external changed one (through not appreciating the
interdependency) it would make the other semantically inaccurate
then its a good idea to hide them to protect yourself. But if we
allow a certain amount of trust in our fellow programmers all
other variables can be left exposed and we rely on them to use
the behaviour published via the methods and not to mess with the
innards.

That's my personal approach at least...

OTOH If you are putting your objects out as a library for general
consumption you may take a more conservative view based on the
idea that the less things users can break the less work for you.

Alan G.
Author of the Learn to Program website
http://www.freenetpages.co.uk/hp/alan.gauld
 
H

Hung Jung Lu

Alan Gauld said:
There is very rarely any good reason to provide getXXX/setXXX
type accessor functions, even in C++

Accessor methods are often needed in simple-generic programming in
C++/Java/C#. (With the coming of actual generics in Java/C#,
accessors/properties will be even more common. C++ does get away a
little bit because it has weakly-typed templates.)

There is an asymmetry between data member and function members in
C++/Java/C#. Whereas in Python you have virtual data fields, in
C++/Java/C# you DON'T. You only have virtual functions.

This is a gigantic limitation. In Python, you write a parent class to
access child-class attributes all the time. In fact, you often use
statements like:

if hasattr(self, 'tax'):
self.total_price = self.price + self.tax

in the parent class, where the 'tax' attribute exists only for a
taxable child class.

Similarly, getters/setters are necessary in mix-in classes in Java/C#.
To me, one main reason for getters/setters is the lack of virtual data
fields. You NEED to use accessor methods to emulate virtual data
fields.
Exposing your data via accessor functions is still exposing it
(albeit with control over read/write access).

In C++/Java/C#, very often it's not a matter of choice, but a matter
of need. Without accessor methods, you have no way of writing generic
programs like:

(a) a parent class accessing data fields of a child class
(b) a mix-in class accessing data fields of the main class

(Mix-ins are achieved by containment plus possible delegation, that's
the way how multiple inheritance works in Java/C#).

regards,

Hung Jung
 
F

F. GEIGER

Scott Brady Drummonds said:
Hi, everyone,

I'm still learning Python as I develop a medium-sized project. From my
previous experience with C++, I've burnt into my mind the notion of
information hiding. I'm having trouble understanding to what extent I
should follow this policy in my Python code so I thought I'd ask the group.

I read from a previous post that to attain a private-like status of member
variables, I should prefix the variable name with two underscores ("__").
This does work, but in another post someone asked me if this was really
necessary. Given that the very nature of the language precludes any
compile-time type dependencies I'm wondering if there is any benefit to
naming variables with leading underscores and providing accessor functions
like this:
class C:
...
def value(self):
return self.__value
...

The problems that arise from directly relying on the member variable in C++
(compile-time type dependency, as I said above) don't exist in Python. So
why provide an accessor at all? Why not just allow direct reading and
writing of the member variable? Is there something here I'm missing?

Classes should offer services, not data. This holds for any programming
language. If you remember this while designing your software you will stop
to think of variables and their not/privateness.

Most people who speak of information hiding don't get it right. They end up
def'ing private variables and then they write getters and setters to access
them. This is NOT information hiding, it's the opposite (simple data
containers being an exception, of course).

Now, if you know all this it really doen't matter much if you write
self.whatToSay or
self._whatToSay or
self.__whatToSay

because your call should be
myObj = MyClass("Hello")
myObj.sayIt(Printer())

and NOT
myObj = MyClass()
s = myObj._whatToSay
print s

In Python things concerning even the bad example are somewhat better because
you do not know explicitly what type s is of. In C++ most people show all
the world, that they access a string, no matter if they use a getter or not.
Sure, they def'ed the string as private, but the information is not hidden,
by no means: Everyone knows, it's a string!

HTH
Franz GEIGER
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top