According to the Classes section of the Python docs:

“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.

Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.

_something indicates to others that something isn't part of the API and can/will be changed without notice, ie should be treated as internal/private.

If you are using inheritance, then __something is a better choice as it both indicates it's an implementation detail and avoids name conflicts with subclasses.

Answer from David Arno on Stack Exchange
Top answer
1 of 16
1685

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, where classname 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!'}
2 of 16
589
  • _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.

🌐
Medium
medium.com › python-explainers › single-and-double-underscores-in-python-explained-63a805ef34db
Single and Double Underscores in Python explained | by Leendert Coenen | Python explainers | Medium
February 28, 2023 - A single underscore is used to indicate a private variable or method (although this is not enforced), while a double underscore is used to implement name mangling for a variable or method.
🌐
GitHub
github.com › pastas › pastas › issues › 74
Make private method private with leading underscore · Issue #74 · pastas/pastas
June 12, 2018 - I think we should make all non-public methods known by adding a leading underscore to the method name. This is suggested in PEP8 (https://www.python.org/dev/peps/pep-0008/), and is followed by all major packages (E.g. Numpy, Scipy, Pandas, Flopy).
Author   raoulcollenteur
🌐
Llego
llego.dev › home › blog › mastering private class members in python with leading underscores
Mastering Private Class Members in Python with Leading Underscores - llego.dev
July 17, 2023 - But Python does not actually prevent ... from outside class · So underscores in Python do not enforce privacy, they simply guide programmers to treat the member as private as a matter of convention....
Find elsewhere
🌐
Better Stack
betterstack.com › community › questions › what-does-underscores-before-object-name-mean-in-python
What is the meaning of single and double underscore before an object name in Python? | Better Stack Community
October 5, 2023 - In Python, single underscore _ before an object name means that the object is meant to be private, and shouldn't be directly accessed from outside the class.
🌐
Reddit
reddit.com › r/learnpython › when should i prefix class private attributes/methods with single underscore instead of double underscore?
r/learnpython on Reddit: When should I prefix class private attributes/methods with single underscore instead of double underscore?
April 15, 2023 -

Note: I'm aware that Python isn't truly private. This question is focusing more on the principles and rationale driving code-level design choices.

Private attributes and methods are supposed to be accessible by only the class and its instantiated objects, not external parties.

In Python, prefixing class attributes/methods with one underscore is, from what I've read, just a symbolic indication to readers of the code that this is intended to be private, but it's not enforced. Prefixing with two underscores implements name-mangling, which is seen as a stricter enforcement of privacy (within Python's language constraints). For example:

class Test:
    abc = 1
    _abc = 2
    __abc = 3

print(Test.abc)  # This works
print(Test._abc)  # This also works
print(Test.__abc)  # This throws an error
print(Test._Test__abc)  # This works

So, this is how I'm currently interpreting these two prefixes: Single underscore has no practical benefit. If someone intentionally wishes to access names with either prefix, they're able to do it regardless. What double-underscore-prefixes can do, which single underscore can't, is protect against accidental access: the IDEs I've worked with to date don't auto-suggest mangled names, so it takes conscious effort to bypass double-underscore-prefixes.

tldr: names with a single underscore prefix are functionally the same as not having any at all, while double underscore prefixes at least protect against unintended direct access. If my intent is to make something private, why would I use single underscore at all? So, under what circumstances should I use single underscore?

Top answer
1 of 4
7
Single underscore has no practical benefit. TBH, I'd say it's really the same benefit as access modifiers in other languages: it's there to communicate that "you're not supposed to touch this". Even in languages with more robust access specifiers, you can still access those things if you really want to: you'd just have to use non-standard mechanisms, like reflection, direct memory access or hacks like #define private public. The fact that you have to jump through such hoops clearly signals "You're not supposed to be doing this", but it's likewise only protection against accidental, rather than deliberate violation of the protections. Python doesn't really have those hoops, so the "you're not supposed to do this" is only enforced through convention, rather than having to go outside the standard mechanisms, but the same role is being performed. It's there to signal that touching this is done at your own risk: it's not part of the public API of your class, and if your code breaks because I change how my class operates in the next release of my library (even if it's just a minor point release), then that's 100% your fault, not mine. As such, this is only really important when you're exposing such an API. Ie. this is a library or otherwise externally accessible object and you care about not breaking other people's code who use it. Use them to signal "internals" that you don't want people to use (or use only at their own risk) that you consider yourself free to break. If this is just an application with no API guarantees involved, you don't really have to care. Double underscores are more important if your API is deeply inheritance based (ie. you expect other uses to subclass your classes and implement functionality that way), where you don't want a subclass to break everything because they happened to use a variable with the same name as yours. However, deep inheritance based APIs have somewhat gone out of fashion these days, especially in python, so I don't think people tend to use this much.
2 of 4
3
I agree with the other answers, leading underscores already signal the intent that you generally shouldn't rely on them in external code, and that they're not part of the public API - in other words they can freely change at a moment's notice, even be deleted without a deprecation step or other warning. So from that point of view it's irrelevant how many underscores you use, as long as it's more than zero. However, I generally recommended to go for a single underscore by default, because the name mangling of two underscores breaks setter properties. So unless it's a value that's only meant to be read, not written to, via the public API, using single underscores results in cleaner code. Double underscores have their place in inheritance, but outside of that I personally don't see a strong reason to prefer them in Python. Other languages would of course differ.
🌐
Real Python
realpython.com › python-double-underscore
Single and Double Underscores in Python Names – Real Python
August 18, 2025 - Underscores in Python names indicate intent: a single leading underscore signals a non-public name, a single trailing underscore helps avoid naming conflicts, and a double leading underscore triggers name mangling for class attributes and methods.
🌐
DataCamp
datacamp.com › tutorial › python-private-methods-explained
Python Private Methods Explained | DataCamp
March 27, 2024 - To summarize the private methods syntax in Python: Single underscore: merely a convention for the programmers, can be accessed outside the function.
🌐
Finxter
blog.finxter.com › home › learn python blog › the underscore in python [“_” vs “__”]
Python Single vs Double Underscore (_ vs __) - Be on the Right Side of Change
November 11, 2023 - The single underscore in Python "_" is used to either make a variable different from a Python keyword such as in float_=8, or to indicate that it should be used in a private context such as in _var=8. ... dunder“) is used to make an instance ...
🌐
Better Programming
betterprogramming.pub › how-to-use-underscore-properly-in-python-37df5e05ba4c
How To Use the Underscore (_) Properly in Python | by Doron Chosnek | Better Programming
January 5, 2023 - Consider the following absurd Python class that defines two local variables, one prepended by a single underscore and the other with two underscores. class MyClass: def __init__(self): self._myprivate = 12 self.__myreallyprivate = 42 · These variables are easily accessed directly by anyone using this class, even though I intended those variables to be private.
🌐
Medium
mike-vincent.medium.com › the-python-underscore-2626d5d4096f
The Python Underscore _. Read this guide to learn how to use the… | by Mike Vincent | Medium
March 10, 2025 - The single leading underscore (_variable) signals to other developers that a variable or method is meant for internal use within a module or class. class Student: def __init__(self): self._internal_id = 12345 # Internal use only def ...
🌐
Medium
purnimachowrasia.medium.com › what-is-private-method-in-python-778bd6e77bad
What is Private method in Python? | by Purnima Chowrasia | Medium
March 26, 2025 - This double underscore before the ... techincally not private or hidden or inaccessible from outside the class. Double underscore(__) is just a convention....
🌐
dbader.org
dbader.org › blog › meaning-of-underscores-in-python
The Meaning of Underscores in Python – dbader.org
May 23, 2017 - The underscore prefix is meant as a hint to another programmer that a variable or method starting with a single underscore is intended for internal use. This convention is defined in PEP 8. This isn’t enforced by Python.
🌐
W3Schools
w3schools.com › python › python_encapsulation.asp
Python Encapsulation
This prevents accidental changes to your data and hides the internal details of how your class works. In Python, you can make properties private by using a double underscore __ prefix:
🌐
TutorialsPoint
tutorialspoint.com › private-methods-in-python
Python - Private Variables
October 17, 2024 - Private methods are methods that are only accessible within the class they are defined in. They are not accessible from outside the class or from any subclass. To define a private method, we use a double underscore (__) before the method name.
🌐
FavTutor
favtutor.com › blogs › python-private-methods
Private Methods in Python | FavTutor
October 18, 2021 - In python, private access to private methods and attributes is not enforced. Therefore, when attributes start with a single underscore, that is just a convention and not an enforced decision.