How do you make a variable private in Python class? A Comprehensive Guide for Python Beginners
When you're diving into the world of Python and object-oriented programming (OOP), you'll inevitably encounter the concept of making variables "private." This is a crucial aspect of encapsulating your data and controlling how it's accessed and modified within your classes. In Python, "private" isn't enforced as strictly as in some other languages, but there's a well-established convention and a mechanism to achieve this.
Understanding Privacy in Python
In Python, the idea of a "private" variable isn't about absolute secrecy. Instead, it's a way to signal to other programmers (including your future self) that a particular attribute or method is intended for internal use within the class and shouldn't be directly accessed or modified from outside the class. Python's approach is often described as "pro-privacy" rather than strictly enforcing it.
The Double Underscore (__) Naming Convention
The primary way to make a variable or method appear "private" in Python is by prefixing its name with a double underscore (__). This is known as name mangling.
Let's illustrate with an example:
class MyClass:
def __init__(self):
self.__private_variable = "I am a private variable!"
self.public_variable = "I am a public variable!"
def __private_method(self):
print("This is a private method.")
def public_method(self):
print("This is a public method.")
print(f"Accessing private variable from within: {self.__private_variable}")
self.__private_method()
# Creating an instance of the class
obj = MyClass()
# Accessing public members
print(obj.public_variable)
obj.public_method()
# Trying to access private members (this will cause an error)
# print(obj.__private_variable)
# obj.__private_method()
In the code above:
__private_variableis defined with a double underscore prefix.__private_methodis also defined with a double underscore prefix.public_variableandpublic_methodare defined without any special prefix, making them public.
How Name Mangling Works
When Python encounters a name prefixed with a double underscore (and not ending with a double underscore), it performs name mangling. It transforms the name into a new name by prepending the name of the class in which it's defined. This makes it harder (but not impossible) to accidentally access these members from outside the class.
For example, if you have a class named MyClass and a private variable __private_variable, Python will internally rename it to _MyClass__private_variable.
Let's see how this looks in practice:
class AnotherClass:
def __init__(self):
self.__secret_data = "This is super secret!"
# Creating an instance
instance = AnotherClass()
# If you try to access it directly, it will fail:
# print(instance.__secret_data) # This will raise an AttributeError
# However, you can access it using the mangled name:
print(instance._AnotherClass__secret_data)
As you can see, by knowing the class name and the original variable name, you can still access the "private" variable. This is why Python's privacy is considered more of a convention.
When to Use Double Underscores
You should use the double underscore prefix for:
- Internal data that shouldn't be modified directly by users of your class. This helps maintain the integrity of your object's state.
- Internal helper methods that are only meant to be called by other methods within the same class.
- Preventing naming conflicts in subclasses. If a subclass defines a method with the same name as a "private" method in its parent class, name mangling ensures that they won't clash.
Alternatives and Considerations
Single Underscore (_) for Convention
A single underscore prefix (_) is also used to indicate that a variable or method is intended for internal use. However, this is purely a convention and does not involve name mangling. Anyone can still access these members directly.
This convention is useful for:
- Indicating that a variable or method is part of the internal implementation details. It's a signal to other developers to tread carefully.
- When you don't need the added protection of name mangling but want to communicate your intent.
class YetAnotherClass:
def __init__(self):
self._internal_data = "This is for internal use."
def _helper_method(self):
print("This is an internal helper method.")
# Accessing these members is straightforward
obj_internal = YetAnotherClass()
print(obj_internal._internal_data)
obj_internal._helper_method()
Properties for Controlled Access
While double underscores make variables harder to access, they don't provide a way to control how they are accessed or modified. For that, Python uses properties.
Properties allow you to define methods that can be accessed like attributes. This lets you add logic to validation, computation, or side effects when a "private" variable is accessed or set.
class Product:
def __init__(self, name, price):
self._name = name # Using single underscore for convention
self.__price = price # Using double underscore for stronger privacy
@property
def name(self):
"""Getter for the product name."""
return self._name
@property
def price(self):
"""Getter for the product price."""
return self.__price
@price.setter
def price(self, value):
"""Setter for the product price with validation."""
if value < 0:
raise ValueError("Price cannot be negative.")
self.__price = value
# Creating an instance
my_product = Product("Gadget", 99.99)
# Accessing using properties (looks like attribute access)
print(f"Product Name: {my_product.name}")
print(f"Product Price: ${my_product.price}")
# Using the setter
my_product.price = 109.50
print(f"Updated Price: ${my_product.price}")
# Trying to set an invalid price
try:
my_product.price = -10.00
except ValueError as e:
print(f"Error: {e}")
# Trying to access the mangled variable directly (will fail)
# print(my_product.__price)
In this example:
_nameis conventionally internal.__priceis truly intended to be private and uses name mangling.- The
@propertydecorator creates a getter forprice, allowing us to accessmy_product.price. - The
@price.setterdecorator allows us to set the price usingmy_product.price = value, but it includes validation logic.
Why Use Private Variables?
The main reasons to use private variables are:
- Encapsulation: It bundles data and methods that operate on that data within a single unit (the class), hiding the internal implementation details.
- Data Hiding: It prevents external code from directly manipulating the internal state of an object in unintended ways, which can lead to bugs.
- Maintainability: When you need to change the internal implementation of a class, having private variables means you're less likely to break code that uses your class, as long as the public interface (methods and properties) remains the same.
- Flexibility: Properties allow you to evolve the internal representation of your data without changing how users interact with your class.
Frequently Asked Questions (FAQ)
How do you make a variable truly private in Python?
Python doesn't have truly private variables in the same way some other languages do. The closest you can get is by using the double underscore (__) prefix, which triggers name mangling. This makes it difficult to access the variable directly from outside the class, but it's still accessible if you know the mangled name (e.g., _ClassName__variableName).
Why should I use private variables in Python?
You should use private variables to enforce encapsulation and data hiding. This means controlling how the internal state of your objects can be accessed and modified, which helps prevent bugs, makes your code more maintainable, and provides flexibility for future changes.
What's the difference between a single underscore (_) and a double underscore (__) prefix for variables?
A single underscore (_) is a convention to indicate that a variable or method is intended for internal use, but it can still be accessed directly. A double underscore (__) triggers name mangling, making the variable harder to access from outside the class by changing its name internally to prevent accidental access and potential naming conflicts with subclasses.
Can I still access a double underscore variable from outside the class?
Yes, you can. While the double underscore makes it harder to accidentally access a variable, it's not impossible. You can access it by using the mangled name, which is constructed by prepending the class name and an underscore to the original variable name (e.g., _MyClass__my_private_var).
When should I use properties instead of just private variables?
You should use properties when you need to control how a private variable is accessed or modified. Properties allow you to add validation logic, perform computations, or execute other code when a variable is read (getter) or written to (setter), without changing how users interact with the class.

