Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #104518 > unrolled thread
| Started by | Ben Mezger <me@benmezger.nl> |
|---|---|
| First post | 2016-03-10 10:41 -0300 |
| Last post | 2016-03-13 00:42 +1100 |
| Articles | 6 — 5 participants |
Back to article view | Back to comp.lang.python
Encapsulation in Python Ben Mezger <me@benmezger.nl> - 2016-03-10 10:41 -0300
Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-11 20:28 +1100
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-11 16:45 -0800
Re: Encapsulation in Python dieter <dieter@handshake.de> - 2016-03-12 10:42 +0100
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-12 07:03 -0800
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-13 00:42 +1100
| From | Ben Mezger <me@benmezger.nl> |
|---|---|
| Date | 2016-03-10 10:41 -0300 |
| Subject | Encapsulation in Python |
| Message-ID | <mailman.132.1457617425.15725.python-list@python.org> |
[Multipart message — attachments visible in raw view] — view raw
Hi all,
I've been studying Object Oriented Theory using Java. Theoretically, all
attributes should be private, meaning no one except the methods itself
can access the attribute;
public class Foo {
private int bar;
...
Normally in Java, we would write getters and setters to set/get the
attribute bar. However, in Python, we normally create a class like so;
class Foo(object):
bar = 0
...
And we usually don't write any getters/setters (though they exist in
Python, I have not seen much projects making use of it).
We can easily encapsulate (data hiding) Foo's class using the '_'
(underscore) when creating a new attribute, however, this would require
all attributes to have a underscore.
According to this answer [1], it's acceptable to to expose your
attribute directly (Foo.bar = 0), so I wonder where the encapsulation
happens in Python? If I can access the attribute whenever I want (with
the except of using a underscore), what's the best way to encapsulate a
class in Python? Why aren't most of the projects not using
getters/setters and instead they access the variable directly?
Regards,
Ben Mezger
[1] - http://stackoverflow.com/q/4555932
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2016-03-11 20:28 +1100 |
| Message-ID | <56e28fbe$0$1584$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #104518 |
On Fri, 11 Mar 2016 12:41 am, Ben Mezger wrote:
> Hi all,
>
> I've been studying Object Oriented Theory using Java. Theoretically, all
> attributes should be private, meaning no one except the methods itself
> can access the attribute;
(Note: in the following, when I say "encapsulation", I am actually referring
to *data hiding*.)
That's one theory. Another theory is: no they shouldn't, all attributes
should be public. That most accurately models actual physical objects and
maximises the usefulness of the attribute.
People over-use private, and if you google, you will find many people
asking "how can I access private variables and methods?". You will also
learn that encapsulation is the enemy of test-drive development:
https://jasonmbaker.wordpress.com/2009/01/08/enemies-of-test-driven-development-part-i-encapsulation/
and also of good user-interfaces:
https://ayende.com/blog/4375/encapsulation-is-the-enemy-of-the-user-interface
Some might say that encapsulation is a waste of time:
http://c2.com/cgi/wiki?EncapsulationIsaWasteOfTime
See also:
http://c2.com/cgi/wiki?MethodsShouldBePublic
http://c2.com/cgi/wiki?ForgetAboutWritingAccessors
Python offers a middle ground: where encapsulation is important for safety,
use it, otherwise rely on trust and a gentleman's agreement. We're all
adults here: if you use my internals, that's your choice, and you can live
with the consequences.
In practice this means that internal details of classes written in C are
completely hidden from Python code unless explicitly made public. Why?
Because if the caller messes with the internal data of a C class, they can
cause a segmentation fault, which can execute arbitrary code. This is a
serious problem, and Python has a philosophy of Absolutely No Seg Faults.
It should be impossible to cause the Python interpreter to seg fault or
dump core (except via ctypes, which is special). That means that classes
written in C are hide their internals.
But what about Python classes? You can't cause a seg fault in Python code.
So Python's philosophy is:
- trying to *enforce* private data is a waste of time, people will find a
way around it, even if it is a horrible nasty hack;
- so instead, rely on trust: we mark "private" attributes with a leading
underscore, and trust that users won't abuse them;
- if they do, the consequences are on their head, not ours: you have no
responsibility to users who misuse your private attributes.
Furthermore, are you *sure* that you need private attributes? That will, of
course, depend on the size of the project you are working on. If it is a
small class in a small program, then it is probably a waste of time and
effort: You Ain't Going To Need It.
Python gives you five levels of enforcement of encapsulation:
1. None what so ever. YAGNI, so just use a regular attribute and
don't over-engineer your simple class.
2. Trust the user to obey the naming convention: name the
attribute with a leading underscore to make it private by
convention.
3. If you need to offer a public interface which differs from
your internal implementation, you can use properties or
custom-made descriptors to implement getters and setters
which look like ordinary attribute access. (This often
relies on #2 as well.)
4. The encapsulation offered by closures is even harder to
break, but it applies to functions, not classes.
5. For the strongest level of encapsulation, move your code
into a C extension class.
For most users, 1 through 3 is more than enough.
> public class Foo {
> private int bar;
> ...
>
> Normally in Java, we would write getters and setters to set/get the
> attribute bar. However, in Python, we normally create a class like so;
>
> class Foo(object):
> bar = 0
> ...
No, normally we wouldn't. The above makes bar shared by all instances.
Normally, if you want each instance to get their own value of bar, you
would assign it in the constructor/initialiser:
class Foo(object):
def __init__(self):
self.bar = 0
For ints, this isn't much of a practical difference, but it makes a very big
difference for mutable classes like lists.
> And we usually don't write any getters/setters (though they exist in
> Python, I have not seen much projects making use of it).
Correct. YAGNI: don't use getters/setters until you have proof that you need
it, not just "well my professor tells me I should do this".
As a Java developer, you might sometimes feel that (by Java standards)
Python code is awfully slap-dash and sloppy. That's okay -- by Python
standards, Java code is awfully "bondage and discipline", strict and
pedantic.
See here:
http://dirtsimple.org/2004/12/python-is-not-java.html
http://dirtsimple.org/2004/12/java-is-not-python-either.html
> We can easily encapsulate (data hiding) Foo's class using the '_'
> (underscore) when creating a new attribute, however, this would require
> all attributes to have a underscore.
Well, if you really want them to be private, that's the way to do it. But
why are they all private? Private attributes have both a benefit and a
cost. Are you sure the benefit is worth it?
Sometimes, rather than make each attribute private, it is easier to just
make the whole class private.
> According to this answer [1], it's acceptable to to expose your
> attribute directly (Foo.bar = 0), so I wonder where the encapsulation
> happens in Python? If I can access the attribute whenever I want (with
> the except of using a underscore), what's the best way to encapsulate a
> class in Python? Why aren't most of the projects not using
> getters/setters and instead they access the variable directly?
Despite what your Java teacher may have said, encapsulation is not the most
important thing about classes. A lot will depend on the size of your
project, of course: in an extremely large project, you will see Python code
written a lot more like Java code. But for small projects, not so much.
In fact, a lot of Python code doesn't even use classes.
Stop Writing Classes: http://www.youtube.com/watch?v=o9pEzgHorH0
http://steve-yegge.blogspot.com.au/2006/03/execution-in-kingdom-of-nouns.html
On the other hand, sometimes we should write more classes:
http://lucumr.pocoo.org/2013/2/13/moar-classes/
>
> Regards,
>
> Ben Mezger
>
> [1] - http://stackoverflow.com/q/4555932
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2016-03-11 16:45 -0800 |
| Message-ID | <5e1d2cff-3e92-4efd-9d48-573e365a8577@googlegroups.com> |
| In reply to | #104601 |
On Friday, March 11, 2016 at 3:28:40 AM UTC-6, Steven D'Aprano wrote: > That's one theory. Another theory is: no they shouldn't, all attributes > should be public. That most accurately models actual physical objects and > maximizes the usefulness of the attribute. > > People over-use private, and if you google, you will find many people > asking "how can I access private variables and methods?". If "people" are trying to access private variables, then one, or both, of these has occurred: (1) The interface was poorly written, and/or (2) The user of the interface is hell bent on shooting himself in the foot! > Python offers a middle ground: where encapsulation is important for safety, > use it, otherwise rely on trust and a gentleman's agreement. We're all > adults here: if you use my internals, that's your choice, and you can live > with the consequences. > > In practice this means that internal details of classes written in C are > completely hidden from Python code unless explicitly made public. Why? > Because if the caller messes with the internal data of a C class, they can > cause a segmentation fault, which can execute arbitrary code. This is a > serious problem, and Python has a philosophy of Absolutely No Seg Faults. First you go off blabbing about how all attributes should be public, then you do an about face, and admit that very bad things can happen when internals are exposed. Does anyone else find this argument to be absurd? > It should be impossible to cause the Python interpreter to seg fault or > dump core (except via ctypes, which is special). SPECIAL CASES ARE *NOT* SPECIAL ENOUGH TO BREAK THE RULES! > But what about Python classes? You can't cause a seg fault in Python code. Are you sure about that? Heck, i posted code quite a few years back that "seg faulted like a mutha". Do you want to retract your statement, or will i need to search the archives, and then stuff the link down your big fat mouth? > So Python's philosophy is: > > - trying to *enforce* private data is a waste of time, people will find a > way around it, even if it is a horrible nasty hack; > > - so instead, rely on trust: we mark "private" attributes with a leading > underscore, and trust that users won't abuse them; > > - if they do, the consequences are on their head, not ours: you have no > responsibility to users who misuse your private attributes. I theory, that is a great philosophy, but in practice, it encourages people to be lazy, and they end up writing horrible interfaces. Why spend the time to write a proper interface, when, in the back of your mind, you know you can reach into that public cookie jar *ANYTIME* you want to. It's like when an overweight person goes on a diet, but still has cookies, cakes and ice-cream in the kitchen -- the temptation to be a slob is just too great! Imagine if indention were optional in Python, or if Python allowed braces... Even with all the benefits of indention over braces, quite a few idiots would still use the damn braces! Heck, i knew this one Ruby coder, who was a longtime C coder, and at the end of every line, he religiously placed a semicolon there. And i told him, "dude, you're *NOT* writing C code anymore, so stop putting those damn trailing semicolons in your source!". But the arrogant bassturd refused to stop. So i thought: "Hmm, maybe it's just a bad habit", but no, he freely admitted that he conscientiously placed them in hos source because: "he liked them". There are two main methods that a language can ruin you as a programmer. One method is to encourage you to be a "Lazy Larry", and the other is to mold you into a "habitual Harry". Python has mostly eradicated the "habitual Harry" disease, but it still actively promotes the "lazy Larry" disease. Yes, pure OOP is onerous to the programmer, but it is onerous for a reason. And that *REASON* is to create rigid interfaces! Anytime a standard is handed down, people are going to whine. "WAH, standards are hard!" "WAH, it takes too long!" "WAH, my fingers hurt!" But what these whiners don't realize, is that, either they put in the effort of writing solid interfaces *NOW*, or they will be forced to debug, explain, and repair the awful interfaces *LATER*. In the end, there is no shortcut to excellence. Which brings me back to my motto: "Great interfaces *NEVER* happen by accident --shite happens, interfaces don't!" Yes, creating proper interfaces requires a lot of thought, a lot of testing, and yes, a whoooole lot of typing. But if thinking, and testing, and typing are not your thing, then perhaps you'd be happier smoking marijuana and working as sales associate at your local GAP store.
[toc] | [prev] | [next] | [standalone]
| From | dieter <dieter@handshake.de> |
|---|---|
| Date | 2016-03-12 10:42 +0100 |
| Message-ID | <mailman.29.1457775786.12893.python-list@python.org> |
| In reply to | #104663 |
Rick Johnson <rantingrickjohnson@gmail.com> writes:
> On Friday, March 11, 2016 at 3:28:40 AM UTC-6, Steven D'Aprano wrote:
> ...
> Are you sure about that? Heck, i posted code quite a few
> years back that "seg faulted like a mutha". Do you want to
> retract your statement, or will i need to search the
> archives, and then stuff the link down your big fat mouth?
^^^^^^^^^^^^^^^^^^^^^^^
What happened that you use language like this?
Obviously, you disagree with Steven - but this should not make you so angry
to use agressive language.
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2016-03-12 07:03 -0800 |
| Message-ID | <b559daba-3c05-46dc-96c3-f283ca689f8d@googlegroups.com> |
| In reply to | #104680 |
On Saturday, March 12, 2016 at 3:43:16 AM UTC-6, dieter wrote: > > archives, and then stuff the link down your big fat mouth? > ^^^^^^^^^^^^^^^^^^^^^^^ > > What happened that you use language like this? Obviously, > you disagree with Steven - but this should not make you so > angry to use aggressive language. Yes, i did go too far here, and for that, i do humbly apologize to Steven and all the members of this group. There is no excuse for aggressive, or fowl language here. Steven has a bad habit of playing devils advocate, and he has on many occasions, made contradictory statements. When he does this, it angers me, because i know he's too intelligent to do these things by accident. In fact, all the members of this group are highly intelligent, and that is why i censor my language when I post here. When i am posting in other groups, groups which have set the "intelligence bar" far lower, i don't censor my words at all, because ignorant people don't deserve any decency from me. Intelligence is a rarity in this world, and much less so in many of the Usenet groups out there. Most of which seem to be nothing more than arenas for personal attacks, fowl language, and a contest to see who has the *LEAST* amount of intelligence. Very sad. I come here not only because of Python, but to engage my equals in civil discourse, and to soak up the vast amounts of general knowledge that are shared generously on a daily basis. Python-list an an oasis of intelligence in a sea of ignorance. And as such, demands that we maintain a high level of decency and mutual respect in our posts. I don't always agree with everyone here, and i may never agree with some, but I will always carry a deep respect for each and every member of this fine group.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-03-13 00:42 +1100 |
| Message-ID | <mailman.40.1457790141.12893.python-list@python.org> |
| In reply to | #104663 |
On Sat, Mar 12, 2016 at 8:42 PM, dieter <dieter@handshake.de> wrote: > Rick Johnson <rantingrickjohnson@gmail.com> writes: >> On Friday, March 11, 2016 at 3:28:40 AM UTC-6, Steven D'Aprano wrote: >> ... >> Are you sure about that? Heck, i posted code quite a few >> years back that "seg faulted like a mutha". Do you want to >> retract your statement, or will i need to search the >> archives, and then stuff the link down your big fat mouth? > ^^^^^^^^^^^^^^^^^^^^^^^ > > What happened that you use language like this? > > Obviously, you disagree with Steven - but this should not make you so angry > to use agressive language. You're responding to someone who calls himself "Ranting Rick". Don't bother expecting courtesy or civility. He's a resident troll, tolerated because he does make good points now and then, but generally ignored because of his irksome style. ChrisA
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web