One of Python's mottos is "we are all consenting adults". In other words, there's no language-level way to prevent someone from accessing data on an object or a method on an object. Naming conventions are the extent of the protection that you get; tack an underscore on to the front of a method and it's a hint that perhaps you shouldn't call it if you want to be polite.
This is a very practical attitude about the utility of language-level "private" methods, and it has served Python relatively well.
The problem is, this motto makes two assumptions:
The problem is that the first point is not true due to several unfortunate features of Python. For example, if I have a module "foo" that does
from lib import bar
def buz(something):
...
__all__ = ['buz']
and then a user of foo
implements qux
to use foo like this:
from foo import bar
The name bar" is purely an implementation detail of "foo". foo
tried as hard as it could to say that: it set __all__
to say buz
is the only thing you ought to be importing. Every single private implementation detail is exposed like this by default, unless you go out of your way to build special structures where these things are not exposed.
It would be nice to have a nicer default for imports so that wouldn't happen.