Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsPython does not enforce public, protected, or private access levels for ordinary class attributes. Instead, underscore naming conventions signal how a name is intended to be used. A single leading underscore marks a non-public implementation detail by convention; a double leading underscore in a class body triggers name mangling to help avoid accidental subclass name clashes—not to provide privacy.
Does Python have access modifiers?
No—not as visibility keywords that block callers from accessing ordinary class members. Python’s tutorial puts it plainly: “Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. The labels public, protected, and private are familiar from other object-oriented languages, but Python relies primarily on naming conventions and, where needed, explicit attribute-management behavior.
That distinction matters: a name may communicate “please treat this as internal” without the interpreter denying access to it.
What do Python’s underscore conventions mean?
| Form | Intended signal or behavior | What it does not do |
|---|---|---|
name |
Public-facing name by convention. | Does not automatically validate or protect data. |
_name |
Non-public implementation detail by convention. | Does not prevent access. |
__name in a class body |
Triggers class-name-based name mangling, which helps reduce accidental name clashes with subclasses. | Does not make a value secret or inaccessible. |
| Descriptor-managed public attribute | Lets code customize or manage attribute reads and writes. | Is not a language-level visibility modifier. |
What does a single underscore mean in Python?
A leading underscore, as in _balance, tells other programmers that the name is an implementation detail rather than part of the class’s public interface. It remains accessible to code that has an instance. The convention helps communicate intent; it is not an access check.
#1 Best Overall
How does a name without a leading underscore behave?
A name such as owner is public by convention and can be read like an ordinary attribute. Public naming alone does not add validation, constrain assignment, or protect the underlying value.
How do private variables work in Python?
They are not made private by an access modifier, because Python has no such modifier for ordinary instance attributes. The following example contrasts a public-by-convention name, a non-public-by-convention name, and a double-leading-underscore name:
Rank #2
class Account:
def __init__(self, owner, balance):
self.owner = owner
self._balance = balance
self.__audit_tag = "A1"
account = Account("Mina", 100)
print(account.owner) # ordinary public name
print(account._balance) # accessible despite the convention
print(account._Account__audit_tag) # deliberate access to mangled name
_balance is not blocked from callers. The double-underscore attribute uses a different mechanism, explained below, but that mechanism also does not establish a security boundary.
What is name mangling?
When an identifier beginning with at least two underscores and ending with no more than one underscore appears in a class definition, Python transforms its spelling to include the class name. For example, __audit_tag in Account is stored under the mangled spelling _Account__audit_tag. The transformation is a compile-time textual change to qualifying identifiers, with special cases; it is not encryption or access control.
Recommended Free Tools
The purpose is to help avoid accidental collisions when subclasses use the same double-leading-underscore name. It can make accidental access or overriding less likely, but code can still deliberately use the mangled name, as the example shows. The Python FAQ explains the transformation and its rationale at the name-mangling FAQ.
Can you access an underscore-prefixed name through a star import?
For from module import *, names beginning with an underscore are omitted. This is an import behavior, not general privacy or class-member access control: it does not make an underscored name inaccessible if code refers to it directly. See the Python tutorial’s explanation of module imports.
How can Python manage attribute reads and writes?
If you need behavior when an attribute is read or assigned, a descriptor can handle those operations through __get__ and __set__. This manages access behavior; it does not create a built-in private modifier.
class Managed:
def __get__(self, obj, objtype=None):
return obj._value
def __set__(self, obj, value):
obj._value = value
class Example:
value = Managed()
Here, value is a public class attribute whose descriptor controls reads and writes on instances. The official descriptor guide demonstrates descriptors as a way to manage attributes. Use them when customized attribute behavior is useful; they are not required for every property-like use.
Best Value
Which approach should you use?
- Use an ordinary name when the attribute is part of the intended public interface.
- Use a single leading underscore to signal that callers should treat an attribute as an implementation detail, while recognizing that Python does not block access.
- Use a double-leading-underscore class attribute when reducing accidental name collisions with subclasses is useful—not to hide secrets or enforce privacy.
- Use a descriptor when attribute reads or writes need managed behavior.
For the class-level conventions and examples, see the Python tutorial’s section on classes and private variables.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




