What do single and double leading underscores before an object's name represent in Python?

- 24,552
- 19
- 101
- 135

- 84,019
- 84
- 236
- 374
-
4A great short answer from another thread: https://stackoverflow.com/a/8689983/911945 – Anton Tarasenko Dec 03 '17 at 08:33
-
See also this _excellent_ answer here, which discusses single vs double leading underscores, and demonstrates "name mangling"!: [Answer to "Private members in Python"](https://stackoverflow.com/a/2064212/4561887) – Gabriel Staples Mar 22 '21 at 23:53
18 Answers
Single Underscore
In a class, names with a leading underscore indicate to other programmers that the attribute or method is intended to be be used inside that class. However, privacy is not enforced in any way. Using leading underscores for functions in a module indicates it should not be imported from somewhere else.
From the PEP-8 style guide:
_single_leading_underscore
: weak "internal use" indicator. E.g.from M import *
does not import objects whose name starts with an underscore.
Double Underscore (Name Mangling)
From the Python docs:
Any identifier of the form
__spam
(at least two leading underscores, at most one trailing underscore) is textually replaced with_classname__spam
, whereclassname
is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, variables stored in globals, and even variables stored in instances. private to this class on instances of other classes.
And a warning from the same page:
Name mangling is intended to give classes an easy way to define “private” instance variables and methods, without having to worry about instance variables defined by derived classes, or mucking with instance variables by code outside the class. Note that the mangling rules are designed mostly to avoid accidents; it still is possible for a determined soul to access or modify a variable that is considered private.
Example
>>> class MyClass():
... def __init__(self):
... self.__superprivate = "Hello"
... self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

- 5,759
- 1
- 32
- 47

- 22,195
- 6
- 45
- 72
-
29What if there's a variable name declared with 2 underscores which is not in the class? It's just a normal variable then right? – Dhruv Ramani Jul 27 '15 at 08:10
-
5what is the meaning of simply `__` double underscore as a variable name? like `a, __ = foo()` – A.J. Dec 03 '15 at 06:24
-
164This answer is extremely misleading, as it leads the reader to believe that dunderscore is used to make instance attributes "superprivate". This is *not* the case, as [explained here](https://www.youtube.com/watch?v=HTLu2DFOdTg&t=33m8s) by Raymond Hettinger, who explicitly states that dunderscore is incorrrectly used to mark members private, while it was designed to be the opposite of private. – Markus Meskanen May 17 '16 at 10:01
-
27@MarkusMeskanen I disagree, the answer explicitly states the use of a dunderscore to make instances of class-private variables and methods. While the dunderscore was designed to make these methods and variables easily overwritten by subclasses (making them public), use of a dunderscore preserves a private instance for use within that class. – arewm Jul 05 '16 at 15:11
-
14@MarkusMeskanen: The freedom is for the subclasses to use the same names as the superclass does without clobbering the superclass -- in otherwords, the superclasses' dunder names become private to itself. – Ethan Furman Jul 15 '16 at 17:48
-
1Seriously, I think it's a mistake to use _ ahead of private variables. _ is far too ambiguous. That's why it throws off so many people. A more appropriate convention would be "privateVarName" because it leaves without question what the intended visibility is supposed to be. I realize it's extra typing, however, clarity is far more important than elegance when it comes to programming. Use variable names that are self-explanatory, don't make people have to come to StackOverflow to read your code. That's a good sign your code is unreadable. – kiwicomb123 Jul 24 '17 at 02:24
-
16For a single underscore, the answer says "nothing special is done with the name itself" but then goes on to say `from M import *` treats it differently...so something special *is* done... – flow2k May 11 '18 at 17:27
-
If you did want to access variable names with a double underscore, just reference it with the class name like so: mc._MyClass__superprivate rather than me.__superprivate. The reason for this is the name mangling by the compiler. – Advait Saravade Dec 09 '18 at 22:44
-
2Please can you update your answer with an example of double underscore with respect to inheritence? – variable Sep 09 '19 at 15:56
-
1Aha! A single leading underscore indicates the author intended it to be a seldom-used function outside the class implementation, but "private" is NOT enforced in Python here like it is in C++, so I can still use this "semi-private" method call anywhere I want outside the class! That's what I needed to know. Voilá! I now know I can call "semi-private" methods in tests. – Gabriel Staples Mar 22 '21 at 23:24
-
Lets say you have private constant _BOB in module_to_test.py. Now assuming I want to test this module in test_module.py. What do you do if you want to make some asserts which imply the _BOB constant value. Would you import _BOB from module_to_test.py (meaning you ignore the fact that _BOB should be viewed as private) so your test code will be automatically updated if at some point in the future _BOB get reassigned a new value) OR would you create a new constant in module_to_test.py (Ex: _BOB_FOR_TEST) this way you don't use an external private variable but you would need to updated your test ? – Greg7000 Mar 23 '22 at 12:29
_foo
: Only a convention. A way for the programmer to indicate that the variable is private (whatever that means in Python).__foo
: This has real meaning. The interpreter replaces this name with_classname__foo
as a way to ensure that the name will not overlap with a similar name in another class.__foo__
: Only a convention. A way for the Python system to use names that won't conflict with user names.
No other form of underscores have meaning in the Python world. Also, there's no difference between class, variable, global, etc in these conventions.

- 24,552
- 19
- 101
- 135

- 364,293
- 75
- 561
- 662
-
9Just came across `__foo` and curious. How can it overlap with similar method names with other Classes? I mean you still have to access it like `instance.__foo()`(if it were not renamed by interpreter), right? – Bibhas Debnath May 09 '13 at 08:03
-
171[This guy](http://stackoverflow.com/questions/551038/private-implementation-class-in-python) states that `from module import *` does not import underscore-prefixed objects. Therefore, `_foo` is more than just a convention. – dotancohen Jun 13 '13 at 13:28
-
7@Bibhas: if class `B` subclasses class `A`, and both implement `foo()`, then `B.foo()` overrides the `.foo()` inherited from `A`. An instance of `B` will only be able to access `B.foo()`, except via `super(B).foo()`. – naught101 Jan 26 '15 at 03:11
-
11For `__dunder__` names, implicit invocations skip the instance dictionary, so it's perhaps a little more than just a naming convention in some cases (see [*special method lookup*](https://docs.python.org/3/reference/datamodel.html#special-method-lookup) section in datamodel). – wim Feb 20 '20 at 20:43
Excellent answers so far but some tidbits are missing. A single leading underscore isn't exactly just a convention: if you use from foobar import *
, and module foobar
does not define an __all__
list, the names imported from the module do not include those with a leading underscore. Let's say it's mostly a convention, since this case is a pretty obscure corner;-).
The leading-underscore convention is widely used not just for private names, but also for what C++ would call protected ones -- for example, names of methods that are fully intended to be overridden by subclasses (even ones that have to be overridden since in the base class they raise NotImplementedError
!-) are often single-leading-underscore names to indicate to code using instances of that class (or subclasses) that said methods are not meant to be called directly.
For example, to make a thread-safe queue with a different queueing discipline than FIFO, one imports Queue, subclasses Queue.Queue, and overrides such methods as _get
and _put
; "client code" never calls those ("hook") methods, but rather the ("organizing") public methods such as put
and get
(this is known as the Template Method design pattern -- see e.g. here for an interesting presentation based on a video of a talk of mine on the subject, with the addition of synopses of the transcript).
Edit: The video links in the description of the talks are now broken. You can find the first two videos here and here.

- 1,292
- 1
- 14
- 25

- 854,459
- 170
- 1,222
- 1,395
-
2So how do you decide whether to use `_var_name` or use `var_name` + excluding it from `__all__`? – endolith Jan 30 '17 at 15:39
-
3@endolith Use leading underscore to signal to the reader of your code that they probably shouldn’t use this (e.g., because you might change it in version 2.0, or even 1.1); use explicit `__all__` whenever you want to make the module `from spam import *` friendly (including at the interactive interpreter). So most of the time, the answer is _both_. – abarnert Apr 25 '18 at 17:15
-
@AlexMartelli Is this import related rule discussed legally somewhere in docs or elsewhere? – Vicrobot Aug 31 '18 at 13:12
-
@AlexMartelli And why it doesn't import them? i mean; which processes are stopping the import of 'em? – Vicrobot Aug 31 '18 at 13:36
-
2I like the C++ analogy. Firstly, I dislike it when people call the `_` **private**. Evidently I'm talking about analogies, since nothing's truly **private** in Python. When diving into semantics I'd say we can tie the `_` to Java's **protected** since **proctected** in Java means "derived classes and/or within same package". Replace package with module since PEP8 already tells us that `_` is not just a convention when talking about `*` imports and there you have it. And definitely `__` would be equivalent to Java's **private** when talking about identifiers within a class. – Marius Mucenicu Jun 04 '19 at 19:03
-
@AlexMartelli: The links to your lectures presented here no longer work (after clicking on the link in this answer, the links on that page are broken). Is there an updated source? – Soren Bjornstad Aug 11 '19 at 13:15
-
Please can you update your answer with an example of double underscore with respect to inheritence? – variable Sep 09 '19 at 15:56
-
5
-
I was a little confused by "for example, names of methods that are fully intended to be overridden by subclasses [,,,] that said methods are not meant to be called directly" because when you override a method the name does not change. Only reading the next paragraph I understood what you mean – 463035818_is_not_an_ai Apr 08 '20 at 07:48
-
C++ **protected** members are not "fully intended to be overridden by subclasses". They are member that can be accessed by same class or any derived classes (if public or protected derive access specifier is declared) – Mike mik Oct 30 '20 at 09:48
-
Just a question: Does `from module import _leading_underscore_name` still work? – The_spider Dec 30 '22 at 08:18
._variable
is semiprivate and meant just for convention
.__variable
is often incorrectly considered superprivate, while it's actual meaning is just to namemangle to prevent accidental access[1]
.__variable__
is typically reserved for builtin methods or variables
You can still access .__mangled
variables if you desperately want to. The double underscores just namemangles, or renames, the variable to something like instance._className__mangled
Example:
class Test(object):
def __init__(self):
self.__a = 'a'
self._b = 'b'
>>> t = Test()
>>> t._b
'b'
t._b is accessible because it is only hidden by convention
>>> t.__a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'
t.__a isn't found because it no longer exists due to namemangling
>>> t._Test__a
'a'
By accessing instance._className__variable
instead of just the double underscore name, you can access the hidden value

- 19,939
- 18
- 80
- 119

- 305
- 1
- 4
- 14
-
but how about if "__a" was a class variable, then you cannot access it even with the instructions from python docs.. – Vitaliy Terziev Jul 06 '17 at 07:07
-
Please can you update your answer with an example of double underscore with respect to inheritence? – variable Sep 09 '19 at 15:56
-
1`._variable`, according to the posts above and PEP-8, is not only a convention: "`from M import *` does not import objects whose names start with an underscore.". However, in the presented case showing it as a class attribute, it doesn't change anything. – pdaawr May 03 '21 at 09:07
-
`.__variable is often incorrectly considered superprivate` this is somewhat misleading. The double underscores, whiles does name mangle, does so in an attempt to make it [properly private](https://docs.python.org/3/tutorial/classes.html#private-variables). – Amorphous Mar 02 '23 at 23:57
Single underscore at the beginning:
Python doesn't have real private methods. Instead, one underscore at the start of a method or attribute name means you shouldn't access this method, because it's not part of the API.
class BaseForm(StrAndUnicode):
def _get_errors(self):
"Returns an ErrorDict for the data provided for the form"
if self._errors is None:
self.full_clean()
return self._errors
errors = property(_get_errors)
(This code snippet was taken from Django source code: django/forms/forms.py). In this code, errors
is a public property, but the method this property calls, _get_errors, is "private", so you shouldn't access it.
Two underscores at the beginning:
This causes a lot of confusion. It should not be used to create a private method. It should be used to avoid your method being overridden by a subclass or accessed accidentally. Let's see an example:
class A(object):
def __test(self):
print "I'm a test method in class A"
def test(self):
self.__test()
a = A()
a.test()
# a.__test() # This fails with an AttributeError
a._A__test() # Works! We can access the mangled name directly!
Output:
$ python test.py
I'm test method in class A
I'm test method in class A
Now create a subclass B and do customization for __test method
class B(A):
def __test(self):
print "I'm test method in class B"
b = B()
b.test()
The output will be...
$ python test.py
I'm test method in class A
As we have seen, B.test() didn't call B.__test() methods, as we might expect. But in fact, this is the correct behavior for __. The two methods called __test() are automatically renamed (mangled) to _A__test() and _B__test(), so they do not accidentally override. When you create a method starting with __ it means that you don't want anyone to be able to override it, and you only intend to access it from inside its own class.
Two underscores at the beginning and at the end:
When we see a method like __this__
, don't call it. This is a method which Python is meant to call, not you. Let's take a look:
>>> name = "test string"
>>> name.__len__()
11
>>> len(name)
11
>>> number = 10
>>> number.__add__(40)
50
>>> number + 50
60
There is always an operator or native function which calls these magic methods. Sometimes it's just a hook Python calls in specific situations. For example __init__()
is called when the object is created after __new__()
is called to build the instance...
Let's take an example...
class FalseCalculator(object):
def __init__(self, number):
self.number = number
def __add__(self, number):
return self.number - number
def __sub__(self, number):
return self.number + number
number = FalseCalculator(20)
print number + 10 # 10
print number - 20 # 40
For more details, see the PEP-8 guide. For more magic methods, see this PDF.

- 69
- 8

- 4,287
- 6
- 32
- 39
-
2After editing this answer myself, I prefer https://stackoverflow.com/a/8689983/1048186 – Josiah Yoder Aug 21 '18 at 19:30
-
What do you mean by "As we have seen, A.test() didn't call B.__test() methods" - where have you called A.test()? – variable Sep 09 '19 at 15:27
-
According to Meaning of Underscores in Python
- Single Leading Underscore(
_var
): Naming convention indicating a name is meant for internal use. Generally not enforced by the Python interpreter (except in wildcard imports) and meant as a hint to the programmer only. - Single Trailing Underscore(
var_
): Used by convention to avoid naming conflicts with Python keywords. - Double Leading Underscore(
__var
): Triggers name mangling when used in a class context. Enforced by the Python interpreter. - Double Leading and Trailing Underscore(
__var__
): Indicates special methods defined by the Python language. Avoid this naming scheme for your own attributes. - Single Underscore(
_
): Sometimes used as a name for temporary or insignificant variables (“don’t care”). Also: The result of the last expression in a Python REPL.

- 2,010
- 1
- 15
- 32

- 2,335
- 30
- 28
Since so many people are referring to Raymond's talk, I'll just make it a little easier by writing down what he said:
The intention of the double underscores was not about privacy. The intention was to use it exactly like this
class Circle(object): def __init__(self, radius): self.radius = radius def area(self): p = self.__perimeter() r = p / math.pi / 2.0 return math.pi * r ** 2.0 def perimeter(self): return 2.0 * math.pi * self.radius __perimeter = perimeter # local reference class Tire(Circle): def perimeter(self): return Circle.perimeter(self) * 1.25
It's actually the opposite of privacy, it's all about freedom. It makes your subclasses free to override any one method without breaking the others.
Say you don't keep a local reference of perimeter
in Circle
. Now, a derived class Tire
overrides the implementation of perimeter
, without touching area
. When you call Tire(5).area()
, in theory it should still be using Circle.perimeter
for computation, but in reality it's using Tire.perimeter
, which is not the intended behavior. That's why we need a local reference in Circle.
But why __perimeter
instead of _perimeter
? Because _perimeter
still gives derived class the chance to override:
class Tire(Circle):
def perimeter(self):
return Circle.perimeter(self) * 1.25
_perimeter = perimeter
Double underscores has name mangling, so there's a very little chance that the local reference in parent class get override in derived class. thus "makes your subclasses free to override any one method without breaking the others".
If your class won't be inherited, or method overriding does not break anything, then you simply don't need __double_leading_underscore
.

- 18,344
- 20
- 107
- 140
-
1Thank you, the slide did not display properly so i ended up not untersanting why my code would fail. – cgte Oct 28 '19 at 21:29
-
Hmm, I got the same answer whether perimeter had leading dunder or not. – Gringo Suave Mar 26 '21 at 21:50
Sometimes you have what appears to be a tuple with a leading underscore as in
def foo(bar):
return _('my_' + bar)
In this case, what's going on is that _() is an alias for a localization function that operates on text to put it into the proper language, etc. based on the locale. For example, Sphinx does this, and you'll find among the imports
from sphinx.locale import l_, _
and in sphinx.locale, _() is assigned as an alias of some localization function.

- 1,645
- 1
- 25
- 46
-
1Yes this answer is helpful ; the [`gettext` module](https://pymotw.com/3/gettext/) describes this pattern "gettext works by looking up literal strings in a database of translations, and pulling out the appropriate translated string. The usual pattern is to bind the appropriate lookup function to the name “_” (a single underscore character) so that the code is not cluttered with a lot of calls to functions with longer names." Maybe that's what sphinx is doing "under the hood"; soemthing like the example`t = gettext.translation('example_domain', 'locale', fallback=True); _ = t.gettext` – Nate Anderson Mar 28 '23 at 20:43
-
1I **could not find the import or creation of the `_` localization function** in my project. I realized my project uses [`gettext.install(...)`](https://docs.python.org/3/library/gettext.html#gettext.install), which "installs the function _() **in Python’s builtins namespace**...", a technique of the ["class-based API"](https://docs.python.org/3/library/gettext.html#class-based-api) of the `gettext` module (vs using the API directly `gettext.gettext(...)`). More on built-ins vs a module's global namespace [here](https://docs.python.org/3/library/gettext.html#gettext.NullTranslations.install) – Nate Anderson Mar 28 '23 at 21:08
_var
: variables with a leading single underscore in python are classic variables, intended to inform others using your code that this variable should be reserved for internal use. They differ on one point from classic variables: they are not imported when doing a wildcard import of an object/module where they are defined (exceptions when defining the__all__
variable). Eg:# foo.py var = "var" _var = "_var"
# bar.py from foo import * print(dir()) # list of defined objects, contains 'var' but not '_var' print(var) # var print(_var) # NameError: name '_var' is not defined
_
: the single underscore is a special case of the leading single underscore variables. It is used by convention as a trash variable, to store a value that is not intended to be later accessed. It is also not imported by wildcard imports. Eg: thisfor
loop prints "I must not talk in class" 10 times, and never needs to access the_
variable.for _ in range(10): print("I must not talk in class")
var_
: single trailing underscore variables. They are classic variables used by convention to avoid conflicts with Python keyword. Eg:class_ = "MyClassName"
__var
: double leading underscore variables (at least two leading underscores, at most one trailing underscore). When used as class attributes (variables and methods), these variables are subject to name mangling: outside of the class, python will rename the attribute to_<Class_name>__<attribute_name>
. Example:class MyClass: __an_attribute = "attribute_value" my_class = MyClass() print(my_class._MyClass__an_attribute) # "attribute_value" print(my_class.__an_attribute) # AttributeError: 'MyClass' object has no attribute '__an_attribute'
When used as variables outside a class, they behave like single leading underscore variables.
__var__
: double leading and trailing underscore variables (at least two leading and trailing underscores). Also called dunders. This naming convention is used by python to define variables internally. Avoid using this convention to prevent name conflicts that could arise with python updates. Dunder variables behave like single leading underscore variables: they are not subject to name mangling when used inside classes, but are not imported in wildcard imports.

- 2,016
- 2
- 18
- 31
If one really wants to make a variable read-only, IMHO the best way would be to use property() with only getter passed to it. With property() we can have complete control over the data.
class PrivateVarC(object):
def get_x(self):
pass
def set_x(self, val):
pass
rwvar = property(get_p, set_p)
ronly = property(get_p)
I understand that OP asked a little different question but since I found another question asking for 'how to set private variables' marked duplicate with this one, I thought of adding this additional info here.

- 1,133
- 1
- 11
- 24
-
Just to add: using `propeety` as a method decorator is a bit cleaner. – TheLizzard Aug 06 '23 at 22:51
Great answers and all are correct.I have provided simple example along with simple definition/meaning.
Meaning:
some_variable --► it's public anyone can see this.
_some_variable --► it's public anyone can see this but it's a convention to indicate private...warning no enforcement is done by Python.
__some_varaible --► Python replaces the variable name with _classname__some_varaible (AKA name mangling) and it reduces/hides it's visibility and be more like private variable.
Just to be honest here According to Python documentation
"“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python"
The example:
class A():
here="abc"
_here="_abc"
__here="__abc"
aObject=A()
print(aObject.here)
print(aObject._here)
# now if we try to print __here then it will fail because it's not public variable
#print(aObject.__here)

- 21,260
- 6
- 105
- 81
-
_ __some_varaible --_ .... _and it reduces/hides it's visibility and be more like private variable._ No, name mangling is the point, it doesn't hide the method. – AMC Feb 11 '20 at 17:04
Here is a simple illustrative example on how double underscore properties can affect an inherited class. So with the following setup:
class parent(object):
__default = "parent"
def __init__(self, name=None):
self.default = name or self.__default
@property
def default(self):
return self.__default
@default.setter
def default(self, value):
self.__default = value
class child(parent):
__default = "child"
if you then create a child instance in the python REPL, you will see the below
child_a = child()
child_a.default # 'parent'
child_a._child__default # 'child'
child_a._parent__default # 'parent'
child_b = child("orphan")
## this will show
child_b.default # 'orphan'
child_a._child__default # 'child'
child_a._parent__default # 'orphan'
This may be obvious to some, but it caught me off guard in a much more complex environment

- 4,820
- 3
- 38
- 36
Single leading underscores is a convention. there is no difference from the interpreter's point of view if whether names starts with a single underscore or not.
Double leading and trailing underscores are used for built-in methods, such as __init__
, __bool__
, etc.
Double leading underscores w/o trailing counterparts are a convention too, however, the class methods will be mangled by the interpreter. For variables or basic function names no difference exists.

- 307,395
- 66
- 306
- 293
Your question is good, it is not only about methods. Functions and objects in modules are commonly prefixed with one underscore as well, and can be prefixed by two.
But __double_underscore names are not name-mangled in modules, for example. What happens is that names beginning with one (or more) underscores are not imported if you import all from a module (from module import *), nor are the names shown in help(module).

- 48,117
- 14
- 92
- 101
-
1Furthermore, names beginning with one or more underscores that have two or more trailing underscores behave as any other name again. – Bentley4 Apr 07 '12 at 15:19
“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.
reference https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references

- 51
- 3
-
1_ is much more similar to for example internal in c# then to private. Double underscore it much more similar to private then underscore is to private I would say. – Ini Nov 04 '17 at 00:38
Getting the facts of _ and __ is pretty easy; the other answers express them pretty well. The usage is much harder to determine.
This is how I see it:
_
Should be used to indicate that a function is not for public use as for example an API. This and the import restriction make it behave much like internal
in c#.
__
Should be used to avoid name collision in the inheritace hirarchy and to avoid latebinding. Much like private in c#.
==>
If you want to indicate that something is not for public use, but it should act like protected
use _
.
If you want to indicate that something is not for public use, but it should act like private
use __
.
This is also a quote that I like very much:
The problem is that the author of a class may legitimately think "this attribute/method name should be private, only accessible from within this class definition" and use the __private convention. But later on, a user of that class may make a subclass that legitimately needs access to that name. So either the superclass has to be modified (which may be difficult or impossible), or the subclass code has to use manually mangled names (which is ugly and fragile at best).
But the problem with that is in my opinion that if there's no IDE that warns you when you override methods, finding the error might take you a while if you have accidentially overriden a method from a base-class.

- 548
- 7
- 19
In the case of methods, you can use the double underscore to hide away private 'methods' with the following pattern:
# Private methods of MyClass
def _MyClass__do_something(obj:'MyClass'):
print('_MyClass__do_something() called. type(obj) = {}'.format(type(obj)))
class MyClass():
def __init__(self):
__do_something(self)
mc = MyClass()
Output:
_MyClass__do_something() called. type(obj) = <class '__main__.MyClass'>
I stumbled across this today when I tried using double underscore for class methods and got the NameError: name '_<class><method>' is not defined
error.

- 3,739
- 1
- 35
- 47
To frame it in simple words, let us compare python's variables' accessibility conventions to access modifiers in Java:
(Python) = (Java)
_single_underscore_variable = Protected (Accessible to class and its subclasses)
__double_underscore_variable = Private (Accessible to class itself only)
no_underscore_variable = Public (Accessible anywhere)
Reference: https://www.tutorialsteacher.com/python/public-private-protected-modifiers

- 677
- 3
- 10