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!'}
Answer from Andrew Keeton on Stack Overflow
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.

🌐
Reddit
reddit.com › r/python › what’s the meaning of single and double underscores in python?
r/Python on Reddit: What’s the Meaning of Single and Double Underscores In Python?
January 25, 2022 -

Have you ever been curious about the several meanings of underscores in Python? A little break-down?

- you can find detailed explanations and code snippets here

1️⃣ single leading underscore ("_var"): indicates that the variable is meant for internal use. This is not enforced by the interpreter and is rather a hint to the programmer.

2️⃣ single trailing underscore ("var_"): it's used to avoid conflicts with Python reserved keywords ("class_", "def_", etc.)

3️⃣ double leading underscores ("__var"): Triggers name mangling when used in a class context and is enforced by the Python interpreter. 
What this means is that it should be used to avoid your method is being overridden by a subclass or accessed accidentally.

4️⃣ double leading and trailing underscores ("__var__"): used for special methods defined in the Python language (ex. __init__, __len__, __call__, etc.). They should be avoided to use for your own attributes.

5️⃣ single underscore ("_"): Generally used as a temporary or unused variable. (If you don't use the running index of a for-loop, you can replace it with "_").

🌐
Reddit
reddit.com › r/learnpython › confused about double leading and trailing underscore use?
r/learnpython on Reddit: Confused about double leading and trailing underscore use?
August 30, 2017 -

double_leading_and_trailing_underscore: "magic" objects or attributes that live in user-controlled namespaces. E.g. init, import or file. Never invent such names; only use them as documented.

Can someone please ELI5? My understanding of a namespace is that it's just a collection that the programmer will set up with specific names so that identifies don't clash in large scale projects. What does the author mean by magic objects or attributes? Aren't all namespaces user-controlled? Just confused about what this is supposed to mean and about what double leading and trailing underscores are supposed to be used for. Thanks guys.

Top answer
1 of 4
5
Let's try and make this simple: Any name (variable, class, function, what have you) in Python can begin with a letter or an underscore. Any name that begins with a single underscore -- but isn't the single underscore itself -- is, by convention, considered an "internal" name, meaning you probably shouldn't use it without realizing that the implementation may change. This is why from module import * will not import any names that begin with an underscore (unless, confusingly, those names are listed in a magic variable we'll discuss below. 2b. Any name that is just a single underscore itself is conventionally seen as an unimportant variable that will not be used. The one extremely important edge case of this is in internationalization with gettext, where the single underscore is actually a function that marks a string constant as one that will be translated. Life gets weird at the edges. 3. Any name that begins with two underscores, but does not end with two underscores, is considered "private" inasmuch as anything in Python is private; the name will be munged using a specific rule. This is basically only useful for preventing inheritance from these names into child classes of the class with a method or variable so named, but a lot of people incorrectly think it makes their code harder to rip off or keeps implementation details private ... these people are generally wrong. 4. Any name that begins and ends with two underscores is what is known as a magic or dunder method. Neither name is really correct, first because these can be constants, variables, or functions, not just methods, and second because there's nothing magical about them, while dunder is actually in the dictionary as the leftover bits in an empty rum barrel, or a rather stupid person, and these are neither. The main reason you do not want to create your own new such names -- as opposed to creating implementations of the existing names on your classes and in your modules -- is because it reduces the space for new such names to be added in Python in the future without causing you conflicts. Basically these are reserved for use by the language itself, and for standardized names within the language, and overwriting them willy nilly or inventing your own may break things in strange ways if you accidentally conflict with one that exists, or if Python adds one and you've become reliant on the same name in your internal code. 4b. One good example of a magic non-method is __all__, which is a list of exactly what names your module exports if someone does a star import of it. 5. A single underscore at the end of a name with no underscore at the front is, by convention, a way of re-using a built in name without conflicting with it ... this is usually seems as class_ instead of klass or cls. So, that about summarizes it. The general role is single-underscore functions and methods you don't want people to consider part of your supporter API, double underscore names inside parent classes you need to not be inherited by child classes, triple underscore nothing whatsoever, add a single underscore to the end of names you want to use that would conflict with language reserved names, and don't write your own magic/dunder names. Clear as mud.
2 of 4
3
The dunder methods really aren't magic. However, if you delete or redefine most dunder methods then expect python to stop working as many of these methods are called by python itself. For instance, a + b will look something like a.__add__(b) after your code is compiled. You can see that here: >>> a = 1 >>> b = 2 >>> print(f' sum: a + b = {a+b}') sum: a + b = 3 >>> print(f'__add__: a + b = {a.__add__(b)}') __add__: a + b = 3 Much of what python does is through the dunder methods on objects, so you shouldn't fiddle with them unless you know what you are doing. Some dunder methods you write yourself, such as the __init__ method of a class: class Test: def __init__(self, name) self.name = name def say_name(self): print(self.name) For an overview of dunder methods, see this . The references to namespaces in your quote isn't really clear for a beginner. I'm not actually a beginner and I'm not sure what they are trying to say. Everything in python is an object and every object has a namespace. Take the class above. Once the class is defined and we create an instance of the class we can't access the say_name attribute unless we say what namespace it is in. That is, we have to do this to call the say_name() method: my_test = Test('fred') my_test.say_name() Note that we must use my_test. to access the method say_name. We can't just call say_name() since we will get an error saying "say_name is not defined". Also note that if we have two instances of class Test each instance has its own namespace: my_test = Test('fred') my_test.say_name() my_test2 = Test('fred') my_test2.say_name() Namespaces are nested. In the my_test example above we have themy_test variable defined. So my_test is defined in the top namespace (often called "global"). The variable my_test has its own internal namespace which is why we call the say_name() method this way: my_test.say_name() When python execution gets to this line it tries to find my_test in the "current" namespace which is the top namespace or "global". That succeeds, as we defined it on the previous line. Then python looks for say_name in the my_test internal namespace. This succeeds because we defined that method. Then python calls the method. Note that my_test has other internal objects, like my_test.name which is a string. The string will have its own internal methods, so we could do this: name_len = my_test.name.__len__() but we don't get a string length that way normally. We usually use the len() builtin: name_len =len(my_test.name) which has the same effect.
🌐
Real Python
realpython.com › python-double-underscore
Single and Double Underscores in Python Names – Real Python
August 18, 2025 - Double leading and trailing underscores—known as dunders—denote special methods or attributes, such as .__init__(), .__len__(), and __name__, which Python uses to support internal behaviors.
🌐
Python Engineer
python-engineer.com › posts › double-single-leading-underscore
What is the meaning of single and double leading underscore in Python - Python Engineer
That's why variables with two leading underscores are sometimes thought of as "real private" attributes since they cannot be accessed from outside the class. However, they can still be accessed via the new given name: class Sample: def __init__(self): self.foo = "hello" self.__bar = "world" s = Sample() s.foo # ok s.__bar # not ok s._Sample__bar # ok · Names with double leading and trailing ...
Top answer
1 of 1
103

As a starting point, you will probably find helpful this quote from PEP 8 - Style Guide For Python Code:

In addition, the following special forms using leading or trailing underscores are recognized (these can generally be combined with any case convention):

_single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g. Tkinter.Toplevel(master, class_='ClassName')

__double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

__double_leading_and_trailing_underscore__: "magic" objects or attributes that live in user-controlled namespaces. E.g. __init__, __import__ or __file__. Never invent such names; only use them as documented.

You asked in the context of class attributes, though, so let's take a look at your specific examples:

Single leading underscore

Naming an attribute in your class self._var1 indicates to the user of the class that the attribute should only be accessed by the class's internals (or perhaps those of a subclass) and that they need not directly access it and probably shouldn't modify it. You should use leading underscores in the same places that you would use a private or protected field in Java or C#, but be aware that the language doesn't actually enforce non-access - instead you trust your class's user to not do anything stupid, and leave them the option of accessing (or modifying) your class's private field if they're really, really sure that they know what they're doing and it makes sense.

Single leading and trailing underscore

self._var1_ isn't something I've ever seen. I don't think this naming style has any conventional meaning in the Python world.

Double leading underscore

This one actually has syntactical significance. Referring to self.__var1 from within the scope of your class invokes name mangling. From outside your class, the variable will appear to be at self._YourClassName__var1 instead of self.__var1. Not everyone uses this - we don't at all where I work - and for simple classes it feels like a slightly absurd and irritating alternative to using a single leading underscore.

However, there is a justification for it existing; if you're using lots of inheritance, if you only use single leading underscores then you don't have a way of indicating to somebody reading your code the difference between 'private' and 'protected' variables - ones that aren't even meant to be accessed by subclasses, and ones that subclasses may access but that the outside world may not. Using a single leading underscore to mean 'protected' and a double underscore to mean 'private' may therefore be a useful convention in this situation (and the name mangling will allow a subclasses to use a variable with the same name in their subclass without causing a collision).

Double leading and trailing underscore

self.__var1__ is something you should never create as I've literally written it, because the double leading and trailing underscore naming style is meant to be used only for names that have a special meaning defined by Python, like the __init__ or __eq__ methods of classes. You're free to override those to change your class's behavior (indeed, almost all classes will have a programmer-defined __init__), but you shouldn't make up your own names in this style like self.__var1__.

🌐
dbader.org
dbader.org › blog › meaning-of-underscores-in-python
The Meaning of Underscores in Python – dbader.org
May 23, 2017 - Variables surrounded by a double ... = 42 >>> PrefixPostfixTest().__bam__ 42 · However, names that have both leading and trailing double underscores are reserved ......
🌐
Delft Stack
delftstack.com › home › howto › python › python double underscore
Double Underscore in Python | Delft Stack
October 10, 2023 - When a variable is surrounded by double underscore on both the leading and trailing sides, the process of name mangling is not applied to it. Variables clustered by the double underscore as both the prefix and the postfix are ignored by the ...
Find elsewhere
🌐
Python
peps.python.org › pep-0008
PEP 8 – Style Guide for Python Code | peps.python.org
Module level “dunders” (i.e. names with two leading and two trailing underscores) such as __all__, __author__, __version__, etc. should be placed after the module docstring but before any import statements except from __future__ imports.
🌐
Scaler
scaler.com › home › topics › what is the meaning of double underscore in python
What is the Meaning of Double Underscore in Python? - Scaler Topics
April 12, 2024 - Double underscore prefix is used in Python to avoid naming conflict. Rewriting attribute names to avoid naming collision is called name mangling. Leading and trailing double underscore does not rewrite the attribute name.
🌐
NBShare
nbshare.io › notebook › 287240024 › Python-Underscore
Python Underscore
Like we said before, leading underscore is just a convention. ... If you look closely, you would notice _Test__num3 attribute at the start of the list. This is the name mangling that the Python interpreter applies. It works that way to protect the variable from overriding in subclasses. Name mangling also applies to method names (and frankly, to all names that start with double leading underscore in class context):
Top answer
1 of 1
2

Pyramid and SQLAlchemy have disobeyed the instruction not to invent such names.

It's not clear to me what you mean by "using this convention in the context of an API", but once they've invented the name, you don't have much choice but to use it as documented by them.

There's no difference between you inventing such names, and inventing them only in user-controlled namespaces. Since you're a user of Python, any namespace that you could put the name into is user-controlled. If you're modifying the Python source to add a new extension to the language that requires some "magic" name, then you can invent one. I expect if you're doing this, you'll usually be in communication with GvR one way or another, so you can ask his opinion directly :-)

What's happening here is that the library authors want a name that none of their users will use by accident to mean something else. The Python language also wants names that no user will use by accident to mean something else, so it "reserves" names of a particular format for use by the language. But then the library-writer has decided to "steal" one of those reserved names and use it anyway, because they feel that's the best way to avoid a clash with one of their users. They have tens of thousands of users, most of whom they don't know anything about. But there's only one Python language spec, and they have access to it. So if a clash occurs the library developers will know about it, which is the plus side, but it will be their fault and difficult to fix, which is the minus side.

Perhaps they're hoping that by using it, the have de facto reserved it for themselves, and that GvR will choose never to use a name that a popular library has already used. Or perhaps they've discussed it on the relevant mailing lists and obtained an exception to the usual rule -- I don't know whether there's a process for that.

🌐
LabEx
labex.io › tutorials › python-how-to-use-the-underscore-in-the-python-interpreter-417289
How to use the underscore in the Python interpreter | LabEx
Double Leading and Trailing Underscore: A double leading and trailing underscore (__variable__) is used to denote special methods in Python, also known as "dunder" (double underscore) methods.
Top answer
1 of 7
859

From the Python PEP 8 -- Style Guide for Python Code:

Descriptive: Naming Styles

The following special forms using leading or trailing underscores are recognized (these can generally be combined with any case convention):

  • _single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

  • single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g.

    Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

  • __double_leading_and_trailing_underscore__: "magic" objects or attributes that live in user-controlled namespaces. E.g. __init__, __import__ or __file__. Never invent such names; only use them as documented.

Note that names with double leading and trailing underscores are essentially reserved for Python itself: "Never invent such names; only use them as documented".

2 of 7
92

The other respondents are correct in describing the double leading and trailing underscores as a naming convention for "special" or "magic" methods.

While you can call these methods directly ([10, 20].__len__() for example), the presence of the underscores is a hint that these methods are intended to be invoked indirectly (len([10, 20]) for example). Most python operators have an associated "magic" method (for example, a[x] is the usual way of invoking a.__getitem__(x)).

🌐
DEV Community
dev.to › hyperkai › private-attributes-in-python-1-5e6g
Underscore in Python (1) - DEV Community
November 7, 2025 - A double leading underscore(__abc) ... class. A double leading and trailing underscore(__abc__) can make the special public attributes which are used in and out a class, e.g....
🌐
Hazadus
hazadus.github.io › knowledge › Articles › Single-and-Double-Underscores-in-Python-Names-–-Real-Python
Single and Double Underscores in Python Names – Real Python
Using double leading underscores triggers name mangling in Python classes. (View Highlight) Additionally, those names with double leading and trailing underscores that are listed in the Python data model trigger internal ...
🌐
sqlpey
sqlpey.com › python › python-underscore-conventions-internal-use-vs-name-mangling
Python Underscore Conventions: Internal Use vs. Name Mangling
October 29, 2025 - ANS: No. Variables with double leading and trailing underscores (dunders) are reserved for Python’s special/built-in methods and are not subject to name mangling.
🌐
Medium
medium.com › @rajneeshjha9s › python-dunders-underscores-373c19c43dda
Python Dunders & Underscores. Original Story … | by Rajneesh Jha | Medium
December 4, 2022 - The double underscore is somewhat ... by the python community, rather it causes the python interpreter to rewrite the attribute name in order to avoid conflicts with names in subclasses....
🌐
Intellipaat
intellipaat.com › home › blog › single and double underscores in python
Single and Double Underscores in Python - Intellipaat
February 18, 2026 - Explanation: Double leading underscores in Python modify variable names to avoid conflicts in inheritance, allowing the child class to access the parent’s “private” variable using its mangled name.