In Python, "privacy" depends on "consenting adults'" levels of agreement - you can't force it. A single leading underscore means you're not supposed to access it "from the outside" -- two leading underscores (w/o trailing underscores) carry the message even more forcefully... but, in the end, it still depends on social convention and consensus: Python's introspection is forceful enough that you can't handcuff every other programmer in the world to respect your wishes.
((Btw, though it's a closely held secret, much the same holds for C++: with most compilers, a simple #define private public line before #includeing your .h file is all it takes for wily coders to make hash of your "privacy"...!-))
In Python, "privacy" depends on "consenting adults'" levels of agreement - you can't force it. A single leading underscore means you're not supposed to access it "from the outside" -- two leading underscores (w/o trailing underscores) carry the message even more forcefully... but, in the end, it still depends on social convention and consensus: Python's introspection is forceful enough that you can't handcuff every other programmer in the world to respect your wishes.
((Btw, though it's a closely held secret, much the same holds for C++: with most compilers, a simple #define private public line before #includeing your .h file is all it takes for wily coders to make hash of your "privacy"...!-))
There may be confusion between class privates and module privates.
A module private starts with one underscore
Such a element is not copied along when using the from <module_name> import * form of the import command; it is however imported if using the import <module_name> syntax (see Ben Wilhelm's answer)
Simply remove one underscore from the a.__num of the question's example and it won't show in modules that import a.py using the from a import * syntax.
A class private starts with two underscores (aka dunder i.e. d-ouble under-score)
Such a variable has its name "mangled" to include the classname etc.
It can still be accessed outside of the class logic, through the mangled name.
Although the name mangling can serve as a mild prevention device against unauthorized access, its main purpose is to prevent possible name collisions with class members of the ancestor classes. See Alex Martelli's funny but accurate reference to consenting adults as he describes the convention used in regards to these variables.
>>> class Foo(object):
... __bar = 99
... def PrintBar(self):
... print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar #direct attempt no go
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar() # the class itself of course can access it
99
>>> dir(Foo) # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar #and get to it by its mangled name ! (but I shouldn't!!!)
99
>>>
"private methods" vs method out of class in a python module - Software Engineering Stack Exchange
Do you use private methods/attributes
clean code - What is the rule for making functions private in Python modules? - Software Engineering Stack Exchange
encapsulation - Why are Python's 'private' methods not actually private? - Stack Overflow
This depends on the relation between the task of those methods and the purpose of the object.
If your object is a report generator and uses a lot of utility functions to justify, inflect and tabulate strings, then those methods have little to do with the purpose of the object. Generating records involves justifying lines of text, but such routines can be used for many other purposes as well, so they should live outside the class - in fact, probably within a general string-handling module.
If the methods are strongly connected to the state and member variables of the object, then they should probably be private member functions. A good heuristic is that you end up always passing some of your own member variables to a function, that function should probably be a member function itself.
Side from polymorphism, the difference between putting them at the module level versus the class level is really subtle. So unless you need to override these in a subclass, the answer is: it really doesn't matter much. Do what makes it the easiest to read and understand. You don't have a parameter in the module level version which would lead me to probably not put in in the class.
Hi,
Some time ago I work with a senior that don't use private method because he said you could access them anyway, so it didn't make sense, in other languages it did, because it was impossible to access it and that's why it was useful, but not in Python.
What do you think, have sense?
(I want to create a survey but I can't, so I'll put two comments, and wait for your upvotes)
The name scrambling is used to ensure that subclasses don't accidentally override the private methods and attributes of their superclasses. It's not designed to prevent deliberate access from outside.
For example:
>>> class Foo(object):
... def __init__(self):
... self.__baz = 42
... def foo(self):
... print self.__baz
...
>>> class Bar(Foo):
... def __init__(self):
... super(Bar, self).__init__()
... self.__baz = 21
... def bar(self):
... print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}
Of course, it breaks down if two different classes have the same name.
When I first came from Java to Python I hated this. It scared me to death.
Today it might just be the one thing I love most about Python.
I love being on a platform, where people trust each other and don't feel like they need to build impenetrable walls around their code. In strongly encapsulated languages, if an API has a bug, and you have figured out what goes wrong, you may still be unable to work around it because the needed method is private. In Python the attitude is: "sure". If you think you understand the situation, perhaps you have even read it, then all we can say is "good luck!".
Remember, encapsulation is not even weakly related to "security", or keeping the kids off the lawn. It is just another pattern that should be used to make a code base easier to understand.
I prefix private modules with an underscore to communicate the intent to the user. In your case, this would be mypack._mod_b
This is in the same spirit (but not completely analogous to) the PEP8 recommendation to name C-extension modules with a leading underscore when it’s wrapped by a Python module; i.e., _socket and socket.
The solution I've settled on is to create a sub-package 'private' and place all the modules I wish to hide in there. This way they stay stowed away, leaving mypack's module list cleaner and easier to parse.
To me, this doesn't look unpythonic either.
Use a single underscore prefix:
class _Internal:
...
This is the official Python convention for 'internal' symbols; from module import * does not import underscore-prefixed objects.
Reference to the single-underscore convention in the Python 2 and Python 3 documentation.
In short:
You cannot enforce privacy. There are no private classes/methods/functions in Python. At least, not strict privacy as in other languages, such as Java.
You can only indicate/suggest privacy. This follows a convention. The Python convention for marking a class/function/method as private is to preface it with an _ (underscore). For example,
def _myfunc()orclass _MyClass:. You can also create pseudo-privacy by prefacing the method with two underscores (for example,__foo). You cannot access the method directly, but you can still call it through a special prefix using the classname (for example,_classname__foo). So the best you can do is indicate/suggest privacy, not enforce it.
Python is like Perl in this respect. To paraphrase a famous line about privacy from the Perl book, the philosophy is that you should stay out of the living room because you weren't invited, not because it is defended with a shotgun.
For more information:
- Private variables Python Documentation
- Why are Python’s ‘private’ methods not actually private? Stack Overflow question 70528