473,396 Members | 2,011 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

OOP techniques in Python

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
16 1276
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
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
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
[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
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
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
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
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
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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Adam Deutsch | last post by:
I would like to ask some advice about tracking down memory leaks in Python code. We have a python application running on Python 2.0.1 in an embedded Linux environment (kernel version 2.4.7). We...
2
by: dont bother | last post by:
Hey, I was just wondering if python has any support modules for statistical techniques as Bayesian, Markovian Style Models etc. Any hints? Thanks Dont __________________________________
5
by: Humpty Dumpty | last post by:
Hello, I've been using python for about 3 months now. Prior to that I did C++ for over 5 years. I'm wondering if my debugging techniques are too C++ oriented. E.g., it took me about 9 hrs of...
25
by: JW | last post by:
I'm putting together a bulletin board system for a community that allows folks to put up for sale postings, notices, etc. These notices usually include the posters' email addresses. A similar...
15
by: christopher diggins | last post by:
I have written an article on how to do Aspect Oriented Programming in vanilla C++ (i.e. without language extensions or other tools such as AspectC++). The article is available at...
2
by: Martin | last post by:
I already know some techniques for writing small footprint software, but now I need to really squeeze the software I'm writing into a small space (embedded software). Is there a good web page...
19
by: JoeC | last post by:
I have seen many books that teack coding for C++. What are ways to improve my techniques for writing larger programs. I have written many demo programs learning some aspects of code wether it be...
5
by: Adekoba | last post by:
I have some questions... Say we have a package "food" food/ __init__.py ham.py cheese.py Is it possible to have a file named "food.py" in the package and have non-referential imports work?...
0
by: Matthew Fitzgibbons | last post by:
I'm by no means a testing expert, but I'll take a crack at it. Casey McGinty wrote: I've never run into this. Rule of thumb: always separate software from hardware. Write mock classes or...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.