Encapsulation in Python

Ian Kelly ian.g.kelly at gmail.com
Fri Mar 11 10:47:15 EST 2016


On Thu, Mar 10, 2016 at 5:45 PM, Rick Johnson
<rantingrickjohnson at gmail.com> wrote:
> Many times, i would have preferred to define my module space
> across multiple files, multiple files that could share state
> without resorting to the yoga-style "import contortions",
> and/or the dreaded "circular import nightmares" that plague
> our community today.

Sounds to me like you're blaming Python for your own poor design.
Possible solutions:

1) Don't do that. If your module is too big for one file, then it's
likely poorly organized and doesn't all belong in one module anyway.

2) Clearly define which module is to be imported first. Then follow
it. When module b is imported, it should import module a. When module
a is imported, it *shouldn't* import module b until it's defined all
of its own members first. If module a depends on anything from module
b at import time, then refactor so it doesn't. This doesn't require
"contortions".

3) Just put all your damn shared state in a class. There's nothing
stopping you from spreading out your class method definitions over
multiple files if you really want to, and it solves your import issue
by allowing everything to be imported before you even begin to set up
the shared state.

>> The vast majority of getters and setters do nothing other
>> than get/set the field they belong to. They exist only to
>> allow the *possibility* of doing something else at some
>> point far in the future.
>
> But you're ignoring the most important aspect of
> getters/setters, and that is, that they expose an interface.
> An interface that must be *EXPLICITLY* created. Good
> interfaces *NEVER* happen by accident.

And you're suggesting that public attributes and properties do not
expose an interface? Rubbish.

>> That's a ton of undesirable boilerplate for little real
>> benefit.
>
> I understand the aversion to boilerplate, but most languages
> have simplified the creation of getters/setters to the point
> that your lament is unfounded. And i would argue that the
> benefits of creating rigid interfaces is the gift that
> keeps on giving.

I don't care how easy they are to *create*. Code is read much more
often than it is written, and excessive boilerplate damages
readability.

>> In Python, OO designers are able to get away with not
>> using getters and setters because we have properties. You
>> can start with an attribute, and if you later want to
>> change the means of getting and setting it, you just
>> replace it with a property. The property lets you add any
>> logic you want, and as far as the outside world is
>> concerned, it still just looks like an attribute.
>
> I used properties quite often when i first began writing
> Python code. Heck, i thought they were the best thing since
> sliced bread. But now, i have come to hate them. I never use
> them in any new code, and when i have free time, i strip
> them out of old code. When i am forced to use an interface
> that was written with properties, i find that learning the
> interface is more difficult
>
>   (1) In a dir listing, one cannot determine which symbols
>   are properties, which are attributes, and which are
>   methods. The beauty of pure OOP encapsulation, is that,
>   *EVERY* exposed symbol is a method. In pure OOP, i don't
>   have to wonder if i'm calling a function with no
>   parameters, or accessing a property, or accessing an
>   attribute, no, i'll know that every access is through a
>   method, therefore, i will append "()" when i know the
>   method takes no arguments. Consistency is very important.

How do you know the method takes no arguments from a dir listing? If
you think the method does take arguments, how do you find out what
those are from a dir listing? If you want to do actual coding with a
class, you're eventually going to have to read something other than
the dir listing, whether everything is a method or not.

>   (2) Properties and attributes encourage vague naming
>   schemes. When i read code, i find the code more
>   comprehensible when the symbols give me clues as to what
>   is going on. So if i read code like: `re.groups`,
>   befuddlement sets in. What is "groups"? A function
>   object? An attribute? "getCapturingGroupCount" would be a
>   better name (but that's semantics)

Actually, it would be wrong. Match.groups doesn't return a count.
Also, it's a method, not an attribute or property, so as an example it
sort of destroys your argument that using methods naturally results in
giving the methods good, meaningful names. These are merely separate
aspects of interface design.

>   In pure OOP,  methods
>   are the only communication meduim, so we're more likely to
>   write "getBlah" and "setBlah", and use verbs for
>   procedural names -- these naming conventions are more
>   comprehensible to the user.

Good names for methods are *descriptive* verb phrases. Good names for
attributes and properties are *descriptive* nouns or noun phrases. Do
you really believe that verbs are somehow inherently easier to
understand?

>   (3) Not all authors correctly utilize leading underscores
>   to differentiate between public and private attributes.
>
>> This all boils down to the fact that code inside a method
>> has no special privilege over external code. If you could
>> hide data so well that external code really couldn't
>> access it, then you wouldn't be able to access it either.
>
> That's a ridiculous statement Ian.

I invite you to demonstrate a counter-example. Show me where a Python
method can hide data such that code external to the class can't find
it.



More information about the Python-list mailing list