27

If 'explicit is better than implicit', why aren't there explicit access modifiers in Python: Public, Protected, Private, etc.?

I know that the idea is that the programmer should know what to do through a hint - no need to use 'brute force'. But IMO 'Encapsulation' or 'information hiding' isn't just to keep people out, it's a question of organization and structure: your development layers should have self-defining, clearly delimited scopes and borders, just like physical systems do.

Can someone please help me out here with a solid explanation as to why access restrictions are implied rather than explicit in Python, a language that otherwise seems close to perfect?

Edit: So far I have seen 3 proposed answers, and I realized that there are 2 parts to my question:

  1. Why aren't there key words, for example

    private def myFunc(): 
        dostuff....
    

    instead of IMO the ugly and hard to type underscores. But that's not the important point.

  2. More importantly:

    Why are these access modifiers only 'recommendations' or hints and not enforced. It will be hard to change later? It's very simple to change 'protected' to 'public' - and if you have a convoluted inheritance chain that makes it difficult, you have a poor design - your design should be refined rather than relying on a language feature that makes it easy to write poorly structured code.

    When access modifiers are enforced, your code is automatically compartmentalized - you KNOW that certain segments are out of scope so you don't have to deal with them except if and when it's necessary. And, if your design is no good and you find yourself constantly moving things into and out of different scopes, the language can help you to clean up your act.

As much as I love Python, I'm finding this 2nd point to be a serious deficiency. And I have yet to see a good answer for this.

svick
  • 9,999
  • 1
  • 37
  • 51
Vector
  • 3,180
  • 3
  • 22
  • 25
  • possible duplicate of [Access specifiers in Python:](http://programmers.stackexchange.com/questions/91783/access-specifiers-in-python)... which was closed as not being constructive. – Frank Shearar Jul 11 '11 at 08:09
  • 2
    @Frank this is a re-ask of that question to attempt to be more constructive. I've gone ahead and deleted the original question. –  Jul 11 '11 at 09:45
  • @Mark Trapp: Ah OK. Thanks for the clarification. I can't see how to rescind my vote-to-close. – Frank Shearar Jul 11 '11 at 10:13
  • @Frank It will age away on its own. – Adam Lear Jul 11 '11 at 12:53
  • the problem with `private def whatever` is, that `class x: def whatever(self): pass` is a shortcut for `class x: pass; x.whatever = lambda self: pass`, so basically, you would need a private modificator for assignment – keppla Jul 12 '11 at 06:23
  • @keppla That just means that the implementation is questionable, it doesn't mean it's the way it should be. – Basic Oct 23 '13 at 21:39
  • It's more than just the implementation: objects can be modified at runtime, so a PPP-notation for methods is not sufficient – keppla Oct 28 '13 at 13:36

4 Answers4

22

"Explicit is better than implicit" is only one of the maxims in Python's design philosophy. "Simple is better than complex" is there too. And, although it's not in the Zen of Python, "We're all consenting adults here" is another.

That second rule is perhaps the most important here. When I design a class, I have some idea of how it's going to be used. But I can't possibly predict all possible uses. It may be that some future use of my code requires access to the variables I've thought of as private. Why should I make it hard - or even impossible - to access these, if a future programmer (or even a future me) needs them? The best thing to do is to mark them with a warning - as Joonas notes, a single underscore prefix is the standard - that they are internal, and might change; but forbidding access altogether seems unnecessary.

Daniel Roseman
  • 772
  • 3
  • 9
  • 1
    "Simple is better than complex" and "We're all consenting adults here" are why Smalltalk doesn't have access modifiers. Putting a method in the "private" category is a hint that you should think thrice before using it, and no more. – Frank Shearar Jul 11 '11 at 17:38
  • @Frank: "Putting a method in the "private" category is a hint that you should think thrice before using it, and no more" To me, it simply means I don't have to worry about it when I'm not dealing with it. – Vector Jul 11 '11 at 18:45
  • @Daniel - I think you've got it right - it's just that I prefer a different sort of development style. – Vector Jul 14 '11 at 01:56
  • 9
    There is a good reason why forbid access to private members: because it may break class invariants. If you can't write private members, then you can't be sure your class behaves correctly. – svick May 05 '12 at 10:32
  • 8
    "Why should I make it hard - or even impossible - to access these, if a future programmer (or even a future me) needs them?" Because one of the basic principle of design is the separation between interface (what a piece of code provides) and implementation (how it provides it). Encapsulation serves to reduce the complexity of the code by reducing the dependencies between different parts of the code. So, public and private are used exactly for the purpose of keeping the code simpler by allowing to see only what is needed. – Giorgio May 05 '12 at 18:04
  • 4
    Cannot diagree more. Access modifiers promote two of probably the best understood concepts to curtail complexity in big software: Encapsulation and Separation of Concerns. Failing to serve neither of the two simply means python is not a good OOP language nor suitable to building big software and there is nothing wrong with that. But justifiying the absence of such features with typical hobbyist arguments like "Why add complexity when it's not needed?" is just wrong. – Daniel Shin May 10 '16 at 08:34
  • @DanielShin: The fact that you disagree with Python's design decisions is irrelevant. OP asked for the rationale behind those decisions, and this answer provides that rationale. – Kevin Jun 28 '17 at 17:39
10

I would suspect the main reason for the missing access modificators is Simplicity

As you say, it's not about keeping people out, its about organisation, so the main point of 'private' is, that it sends a message to the users of your api 'please dont write code that depends on this'.

It's trivial to say 'by convention, _x or __x should not be used outside the class', but in python's dynamic object model, it would be hard to even come up with a notation.

class ActiveRow(object):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

how to note the accessability?

I guess, this was a trade off. If you strictly cannot live with it, I would suggest ruby, which has a similar level of abstraction and dynamicity, but has an object model, that allows for access modification.

S.Lott
  • 45,264
  • 6
  • 90
  • 154
keppla
  • 5,210
  • 24
  • 32
  • 8
    I think this is correct, but IMO, it's terrible. For a language that uses elegance and readability as selling points writing \_\_method\_\_ is pretty heinous-looking and obtuse. – jiggy Jul 11 '11 at 16:21
  • 3
    thats not the convention, `__x__` are 'magic', (i.e. methods that get called for enabling language integration like operator overloading, iterability, etc.). The convention is `_x`. – keppla Jul 11 '11 at 17:21
  • 6
    Sorry, I'm still getting my head around Python. I'm trying so hard to like it, but stuff like this drives a little batty. Especially now that I need to remember the meaning of how many underscores a method has. To OP's point, it seems that explicit modifiers would be more clear. Concision is great, but it can't trump clarity. You spend 10X more effort maintaining code than building it. – jiggy Jul 11 '11 at 18:19
  • 2
    My example wasnt meant to show different counts of underscores, the use of `__init__` was incidental. The example sets some properties of the object, that are not know on compile time, so an explicit access modifier would not help you. – keppla May 07 '12 at 14:00
  • 6
    @jiggy: "I'm trying so hard to like it". I tried for 2 years - then gave up. :-( Appears to be a scripting language that was hacked to behave somewhat like a real OOP language. I can't imagine writing a large, complex app in Python that was well designed and readable. As you said 'You spend 10X more effort maintaining code than building it'. Simple OOP and type safe concepts require crazy hacks and workarounds. – Vector May 03 '13 at 17:26
  • 1
    @Vector It's hands-down the best glue language I've come across so far, but I wouldn't use it build much more than a service which coordinates other, more complex processes. The woeful threading model alone makes it unsuitable. – Basic Feb 18 '15 at 11:29
9

The Python convention is to use an underscore prefix for protected/private members.

This convention, when followed, is effectively same as access modifiers, except 1) you'll see directly from the member's name whether it's public or not, and 2) you can break "encapsulation" if you really want to (this can be justifiable in e.g. testing; in some other languages you would have to use reflection == more code).

Ultimately it's a question of taste, but if you can do the same thing (with a bit more flexibility) without special keywords, the language will be smaller and code will be more concise, which is generally a good thing.

Joonas Pulakka
  • 23,534
  • 9
  • 64
  • 93
  • 2
    " if you can do the same thing (with a bit more flexibility) without special keywords, the language will be smaller and code will be more concise" In my opinion, this is generally not true. (Even if it can be true with the special case of access modifiers) – BenjaminB Jul 11 '11 at 14:28
0

It's probably because Python code tend to fragment into tons of small modules. So when a package is loaded, it can choose what to make available to the user.

Of course, this doesn't completely justify the lack of access modifiers, but it does decrease the chance of making mistakes.

xax
  • 1
  • 1