By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,327 Members | 2,661 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,327 IT Pros & Developers. It's quick & easy.

OOP techniques in Python

P: n/a
I've been thinking if there's a point in applying some specific OOP
techniques in Python as we do in other languages.

i.e. we usually define private properties and provide public functions
to access them, in the form of:
get { ... } set { ... }

Should we do the same in Python:

self.__privateAttr = 'some val'

def getPrivateAttr(self):
return self.__privateAttr

Or there's no point in doing so?

Some other techniques come to mind, but I think that Python tends to
allow the programmer to access stuff he wants even though he shouldn't
or in the form of a dict or list, rather than a method to do so.

Apr 27 '06 #1
Share this Question
Share on Google+
16 Replies


P: n/a
Panos Laganakos wrote:
i.e. we usually define private properties and provide public functions
to access them, in the form of:
get { ... } set { ... }

Should we do the same in Python:

self.__privateAttr = 'some val'

def getPrivateAttr(self):
return self.__privateAttr

Or there's no point in doing so?

If you want to do more than just setting an attribute or returning it then
define a property, but if you just want to save the value there is no point
using a property. In some other languages you cannot change an attribute
into a property without changing the interface to the class, so in those
languages you need to make everything a property just in case you ever need
it to be a property in the future.

In Python, when you need it to become a property you can change it without
breaking anything, so there is no need to obfuscate it prematurely.
Apr 27 '06 #2

P: n/a
Panos Laganakos wrote:
we usually define private properties and provide public functions
to access them, in the form of:
get { ... } set { ... }

Should we do the same in Python:

self.__privateAttr = 'some val'

def getPrivateAttr(self):
return self.__privateAttr

Or there's no point in doing so?


There is no point in doing so. You should use plain attributes whenever
possible (that is, whenever you're really just doing a get or a set,
with no computation). The only reason to use getters and setters is so
that you can change the implementation later if you need to. But python
allows you to do this with properties:
class C(object): .... def __init__(self, x):
.... self.x = x
.... C(42).x 42 class C(object): .... def _get_x(self):
.... return self._x * 2
.... def _set_x(self, value):
.... self._x = value / 2
.... x = property(_get_x, _set_x)
.... def __init__(self, x):
.... self.x = x
.... C(42).x

42

Which should not be interpreted as saying you should start writing a
bunch of properties now. ;) Instead, only introduce a property when you
find that something must remain an attribute (presumably for backwards
compatibility reasons) but for whatever reason it now needs some
additional computation.

STeVe
Apr 27 '06 #3

P: n/a
Why is that ? to me it makes sense when I see self.__m_var that I'm dealing
with a member variable taht derived classes will not see/access.

Philippe


Steven Bethard wrote:
Panos Laganakos wrote:
we usually define private properties and provide public functions
to access them, in the form of:
get { ... } set { ... }

Should we do the same in Python:

self.__privateAttr = 'some val'

def getPrivateAttr(self):
return self.__privateAttr

Or there's no point in doing so?


There is no point in doing so. You should use plain attributes whenever
possible (that is, whenever you're really just doing a get or a set,
with no computation). The only reason to use getters and setters is so
that you can change the implementation later if you need to. But python
allows you to do this with properties:
>>> class C(object): ... def __init__(self, x):
... self.x = x
... >>> C(42).x 42 >>> class C(object): ... def _get_x(self):
... return self._x * 2
... def _set_x(self, value):
... self._x = value / 2
... x = property(_get_x, _set_x)
... def __init__(self, x):
... self.x = x
... >>> C(42).x

42

Which should not be interpreted as saying you should start writing a
bunch of properties now. ;) Instead, only introduce a property when you
find that something must remain an attribute (presumably for backwards
compatibility reasons) but for whatever reason it now needs some
additional computation.

STeVe


Apr 27 '06 #4

P: n/a
[Please don't top-post]

Steven Bethard wrote:
Panos Laganakos wrote:
we usually define private properties and provide public functions
to access them, in the form of:
get { ... } set { ... }

Should we do the same in Python:

self.__privateAttr = 'some val'

def getPrivateAttr(self):
return self.__privateAttr

Or there's no point in doing so?
There is no point in doing so. You should use plain attributes
whenever possible (that is, whenever you're really just doing a get or
a set, with no computation). The only reason to use getters and
setters is so that you can change the implementation later if you need
to. But python allows you to do this with properties:

[snip] Which should not be interpreted as saying you should start writing a
bunch of properties now. ;) Instead, only introduce a property when
you find that something must remain an attribute (presumably for
backwards compatibility reasons) but for whatever reason it now needs
some additional computation.
Philippe Martin top-posted: Why is that ? to me it makes sense when I see self.__m_var that I'm dealing
with a member variable taht derived classes will not see/access.


If the OP uses a private attribute in combination with a getter and a
setter, he's basically still exposing the attribute as public, but
making it harder to get and set. There's no reason to do that. If
you're going to expose a public API to part of the class that just
assigns and returns a value (with no computation), you might as well
make that API an attribute instead of a pair of methods.

STeVe

Apr 27 '06 #5

P: n/a
Panos Laganakos wrote:
I've been thinking if there's a point in applying some specific OOP
techniques in Python as we do in other languages.
Yes - but some of these techniques are somewhat python-specific.
i.e. we usually define private properties and provide public functions
to access them, in the form of:
get { ... } set { ... }

Should we do the same in Python:
No.

Or there's no point in doing so?
Absolutely. Python has descriptors and properties, which allow you to
switch from a direct attribute access to a computed attributes without
breaking the API. In fact, think of public attributes as automatic
getter/setters pairs, that you can customize when needed !-)
Some other techniques come to mind, but I think that Python tends to
allow the programmer to access stuff he wants even though he shouldn't
s/he shouldn't/he knows he's messing with implementation details and
assume the consequences.

FWIW, accessing 'private' attributes in Java or C++ is not a big deal.
or in the form of a dict or list, rather than a method to do so.


Python is *object* oriented - not class-oriented - and doesn't force you
to put everything into a class definition. Now everything in Python is
an object (including functions and classes and modules...). This is a
much less restricted (and IMHO much much more powerful) approach than
what you may learn from Java, C++, C# etc.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Apr 27 '06 #6

P: n/a
Steven Bethard wrote:
[Please don't top-post]

Steven Bethard wrote:
> Panos Laganakos wrote:
>> we usually define private properties and provide public functions
>> to access them, in the form of:
>> get { ... } set { ... }
>>
>> Should we do the same in Python:
>>
>> self.__privateAttr = 'some val'
>>
>> def getPrivateAttr(self):
>> return self.__privateAttr
>>
>> Or there's no point in doing so? >
> There is no point in doing so. You should use plain attributes
> whenever possible (that is, whenever you're really just doing a get or
> a set, with no computation). The only reason to use getters and
> setters is so that you can change the implementation later if you need
> to. But python allows you to do this with properties:

[snip]
> Which should not be interpreted as saying you should start writing a
> bunch of properties now. ;) Instead, only introduce a property when
> you find that something must remain an attribute (presumably for
> backwards compatibility reasons) but for whatever reason it now needs
> some additional computation.


Philippe Martin top-posted:
Why is that ? to me it makes sense when I see self.__m_var that I'm
dealing with a member variable taht derived classes will not see/access.


If the OP uses a private attribute in combination with a getter and a
setter, he's basically still exposing the attribute as public, but
making it harder to get and set. There's no reason to do that. If
you're going to expose a public API to part of the class that just
assigns and returns a value (with no computation), you might as well
make that API an attribute instead of a pair of methods.

STeVe


[Please don't top-post]


OK I won't, is that a general rule? (I've been top posting for quite some
time now and it is the first time I see that warning)

Philippe


--
---------------------------
"Poignée trop essorée, moulin bien rincé"
Pierre Lafouine
---------------------------

Apr 27 '06 #7

P: n/a
Panos Laganakos wrote:
i.e. we usually define private properties and provide public functions
to access them, in the form of:
get { ... } set { ... }

Should we do the same in Python:
Or there's no point in doing so?

Some other techniques come to mind, but I think that Python tends to
allow the programmer to access stuff he wants even though he shouldn't
or in the form of a dict or list, rather than a method to do so.


There's no point. Private access can only be advisory anyway -- there are
ways around it in every language. Convention serves just as well, people
know that touching _foo is done at their own risk. It's not creating extra
hoops to jump through the few times you really do need to touch a private
var.

Others already mentioned how to transparently change attributes to
properties.

If you're worried about enforcing restrictions in your code base, get a lint
checker to flag any expression of the form name._foo where name isn't
'self'. Yes you can still access _foo other ways, but you'll never get
perfect enforcement anyway. Maybe the extra step will make you think
twice, if that's what you want (and it seems to be).

Apr 27 '06 #8

P: n/a
Edward Elliott wrote:
Panos Laganakos wrote:
i.e. we usually define private properties and provide public functions
to access them, in the form of:
get { ... } set { ... }

Should we do the same in Python:
Or there's no point in doing so?

Some other techniques come to mind, but I think that Python tends to
allow the programmer to access stuff he wants even though he shouldn't
or in the form of a dict or list, rather than a method to do so.


There's no point. Private access can only be advisory anyway -- there are
ways around it in every language. Convention serves just as well, people
know that touching _foo is done at their own risk. It's not creating
extra hoops to jump through the few times you really do need to touch a
private var.

Others already mentioned how to transparently change attributes to
properties.

If you're worried about enforcing restrictions in your code base, get a
lint checker to flag any expression of the form name._foo where name isn't
'self'. Yes you can still access _foo other ways, but you'll never get
perfect enforcement anyway. Maybe the extra step will make you think
twice, if that's what you want (and it seems to be).


--

What then is the point of the double underscore (if any) ?:
In [2]:class test:
.2.: _one_underscore=1
.2.: __two_underscores=2
.2.:

In [3]:t = test()

In [4]:t._one_underscore=2

In [5]:t.__two_underscores=3

In [6]:t.__two_underscores
Out[6]:3

In [7]:dir (test)
Out[7]:['__doc__', '__module__', '_one_underscore',
'_test__two_underscores']

In [8]:test._one_underscore
Out[8]:1

In [9]:test.__two_underscores
---------------------------------------------------------------------------
exceptions.AttributeError Traceback (most recent
call last)

/home/philippe/<ipython console>

AttributeError: class test has no attribute '__two_underscores'

-------------------------
"Poignée trop essorée, moulin bien rincé"
Pierre Lafouine
---------------------------



Apr 27 '06 #9

P: n/a
Philippe Martin wrote:
Steven Bethard wrote:
[Please don't top-post]


OK I won't, is that a general rule? (I've been top posting for quite some
time now and it is the first time I see that warning)


Yes. Other suggestions you might get are not to bottom post, and certainly
not (as you did elsewhere) to post your response as a signature (i.e.
following a line containing only two dashes and a space).

The accepted way to follow up is to trim the post to which you are
responding so as to maintain sufficient context to make the post
intelligible on its own, but not to quote the entire post: most newsreader
programs will help you in this by either warning or indeed refusing to post
responses which have too many quoted lines compared with new content.

It is perfectly reasonable if you are making several points to intersperse
your comments with other quoted sections.

Some newsgroups use a different convention and expect top-posting without
trimming of the quoted posts, but these very much are in the minority.
Apr 27 '06 #10

P: n/a
Philippe Martin wrote:
''

On the other hand, foo.__doc__ and foo.__name__ work fine.

(I was going to quote your post but my reader interprets everything after
the two dashes as your sig and ignores it. And I won't bother to fix it.)

Apr 27 '06 #11

P: n/a
Edward Elliott wrote:
Philippe Martin wrote:
''

On the other hand, foo.__doc__ and foo.__name__ work fine.

(I was going to quote your post but my reader interprets everything after
the two dashes as your sig and ignores it. And I won't bother to fix it.)

I'm not sure I understand what you mean ... I did get a strange new message
from my email client and disabled the signature.
Apr 27 '06 #12

P: n/a
Duncan Booth wrote:
Philippe Martin wrote:
Steven Bethard wrote:
[Please don't top-post]


OK I won't, is that a general rule? (I've been top posting for quite some
time now and it is the first time I see that warning)


Yes. Other suggestions you might get are not to bottom post, and certainly
not (as you did elsewhere) to post your response as a signature (i.e.
following a line containing only two dashes and a space).

The accepted way to follow up is to trim the post to which you are
responding so as to maintain sufficient context to make the post
intelligible on its own, but not to quote the entire post: most newsreader
programs will help you in this by either warning or indeed refusing to
post responses which have too many quoted lines compared with new content.

It is perfectly reasonable if you are making several points to intersperse
your comments with other quoted sections.

Some newsgroups use a different convention and expect top-posting without
trimming of the quoted posts, but these very much are in the minority.


:-) I did try the signature for the first time today, and stopped as I get
weird errors from my client and certainly do not wish to get flame just
because I like a cute message.

My assumption always was:
1) keep all data in the post so new viewers can understand get the full
content, including the initial post

2) write on top because when you open a file, you want the chronological
info on top instead of at the very bottom ... since because of 1) this
could be miles away.

But if the rules are otherwise then I'll just follow them.
Regards,

Philippe


Apr 27 '06 #13

P: n/a
Philippe Martin wrote:
I'm not sure I understand what you mean ... I did get a strange new
message from my email client and disabled the signature.


Look again at the post I replied to (great-grandparent of this one). It's
not your sig quote that was the problem.

Apr 27 '06 #14

P: n/a
Thanks for all the useful answers :)

Alot of stuff to take into consideration/chew on. I come up with
similar drawbacks now and then, 'cause some OOP techniques can be made
in Python relatively simpler or plainly different (still simpler
though). Though I am hesitant on how to act on certain occasations, as
I was with this one, luckily I can get to post here and hear all these
cool comments/opinions. :D

Apr 28 '06 #15

P: n/a
Dennis Lee Bieber wrote:
On Thu, 27 Apr 2006 14:32:15 -0500, Philippe Martin
<pm*****@snakecard.com> declaimed the following in comp.lang.python:
What then is the point of the double underscore (if any) ?:


To prevent masking/shadowing of inherited attributes...


Note that it can fail to do this if you accidentally (or purposefully)
name a class the same as a parent or ancestor class:
class Confusion(object): .... def __init__(self):
.... self.__str = 'module 1'
.... def get_module_1_confusion(self):
.... return self.__str
.... module_1_confusion = Confusion
class Confusion(module_1_confusion): .... def __init__(self):
.... self.__str = 'module 2'
.... module_2_confusion = Confusion
module_2_confusion().get_module_1_confusion()

'module 2'

So you still need to at least check that the name of your subclass is
different from the name of all its ancestors. This doesn't come up that
often, but I know a few people have been bitten by it.

STeVe
Apr 28 '06 #16

P: n/a
Thanks,

Did not know that.

Philippe

Dennis Lee Bieber wrote:
On Thu, 27 Apr 2006 14:32:15 -0500, Philippe Martin
<pm*****@snakecard.com> declaimed the following in comp.lang.python:

What then is the point of the double underscore (if any) ?:


To prevent masking/shadowing of inherited attributes...
class A(object): ... def __init__(self):
... self.__WhoMe = "From A"
... print "A : ", dir(self)
... super(A, self).__init__()
... class B(object): ... def __init__(self):
... self.__WhoMe = 42
... print "B : ", dir(self)
... super(B, self).__init__()
... class Confusion(A, B): ... def __init__(self):
... self.__WhoMe = "I'm confuzzled"
... print "Confusion: ", dir(self)
... super(Confusion, self).__init__()
... cab = Confusion() Confusion: ['_Confusion__WhoMe', '__class__', '__delattr__',
'__dict__', '__doc__', '__getattribute__', '__hash__', '__init__',
'__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__str__', '__weakref__']
A : ['_A__WhoMe', '_Confusion__WhoMe', '__class__', '__delattr__',
'__dict__', '__doc__', '__getattribute__', '__hash__', '__init__',
'__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__str__', '__weakref__']
B : ['_A__WhoMe', '_B__WhoMe', '_Confusion__WhoMe', '__class__',
'__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__str__', '__weakref__']
Note that A, B, and Confusion each have "__WhoMe". Also notice how
each __init__ invokes the parent module __init__; each one adds its
__WhoMe to the object without masking those defined in others.

Without the __, you'd have only ONE attribute after all of that; as
shown next...
class A(object): ... def __init__(self):
... self._WhoMe = "From A"
... print "A : ", dir(self)
... super(A, self).__init__()
... class B(object): ... def __init__(self):
... self._WhoMe = 42
... print "B : ", dir(self)
... super(B, self).__init__()
... class Confusion(A, B): ... def __init__(self):
... self._WhoMe = "I'm confuzzled"
... print "Confusion: ", dir(self)
... super(Confusion, self).__init__()
... cab2 = Confusion() Confusion: ['_WhoMe', '__class__', '__delattr__', '__dict__',
'__doc__', '__getattribute__', '__hash__', '__init__', '__module__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__', '__weakref__']
A : ['_WhoMe', '__class__', '__delattr__', '__dict__', '__doc__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
'__weakref__']
B : ['_WhoMe', '__class__', '__delattr__', '__dict__', '__doc__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
'__weakref__']

--
> ================================================== ============ <
> wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
> wu******@dm.net | Bestiaria Support Staff <
> ================================================== ============ <
> Home Page: <http://www.dm.net/~wulfraed/> <
> Overflow Page: <http://wlfraed.home.netcom.com/> <


May 1 '06 #17

This discussion thread is closed

Replies have been disabled for this discussion.