Private Methods in Python
Encapsulation is one of the fundamental concepts in object-oriented programming (OOP) in Python. It describes the idea of wrapping data and the methods that work on data within one unit. This puts restrictions on accessing variables and methods directly and can prevent the accidental modification of data. A class is an example of encapsulation as it encapsulates all the data that is member functions, variables, etc. Now, there can be some scenarios in which we need to put restrictions on some methods of the class so that they can neither be accessed outside the class nor by any subclasses. To implement this private methods come into play.
Private functions in Python
Consider a real-life example, a car engine, which is made up of many parts like spark plugs, valves, pistons, etc. No user uses these parts directly, rather they just know how to use the parts which use them. This is what private methods are used for. It is used to hide the inner functionality of any class from the outside world. Private methods are those methods that should neither be accessed outside the class nor by any base class. In Python, there is no existence of Private methods that cannot be accessed except inside a class. However, to define a private method prefix the member name with the double underscore “__”. Note: The __init__ method is a constructor and runs as soon as an object of a class is instantiated.
# Creating a Base class
class Base:
# Declaring public method
def fun(self):
print("Public method")
# Declaring private method
def __fun(self):
print("Private method")
# Creating a derived class
class Derived(Base):
def __init__(self):
# Calling constructor of
# Base class
Base.__init__(self)
def call_public(self):
# Calling public method of base class
print("\nInside derived class")
self.fun()
def call_private(self):
# Calling private method of base class
self.__fun()
# Driver code
obj1 = Base()
# Calling public method
obj1.fun()
obj2 = Derived()
obj2.call_public()
# Uncommenting obj1.__fun() will
# raise an AttributeError
# Uncommenting obj2.call_private()
# will also raise an AttributeError
Output:
Public method
Inside derived class
Public method
Traceback (most recent call last):
File "/home/09d6f91fdb63d16200e172c7a925dd7f.py", line 43, in
obj1.__fun()
AttributeError: 'Base' object has no attribute '__fun'
Traceback (most recent call last):
File "/home/0d5506bab8f06cb7c842501d9704557b.py", line 46, in
obj2.call_private()
File "/home/0d5506bab8f06cb7c842501d9704557b.py", line 32, in call_private
self.__fun()
AttributeError: 'Derived' object has no attribute '_Derived__fun'
The above example shows that private methods of the class can neither be accessed outside the class nor by any base class. However, private methods can be accessed by calling the private methods via public methods.
Example:
# Creating a class
class A:
# Declaring public method
def fun(self):
print("Public method")
# Declaring private method
def __fun(self):
print("Private method")
# Calling private method via
# another method
def Help(self):
self.fun()
self.__fun()
# Driver's code
obj = A()
obj.Help()
Output:
Public method
Private method
Name mangling
Python provides a magic wand that can be used to call private methods outside the class also, it is known as name mangling. It means that any identifier of the form __geek (at least two leading underscores or at most one trailing underscore) is replaced with _classname__geek, where the class name is the current class name with a leading underscore(s) stripped.
Example:
# Creating a class
class A:
# Declaring public method
def fun(self):
print("Public method")
# Declaring private method
def __fun(self):
print("Private method")
# Driver's code
obj = A()
# Calling the private member
# through name mangling
obj._A__fun()
Output:
Private method
Private Methods in Python – FAQs
Can private methods be accessed outside their class?
Private methods in Python are designed to be inaccessible from outside the class where they are defined. They are prefixed with a double underscore (e.g.,
__private_method
). However, Python does not enforce strict access controls, so these methods can still be accessed using name mangling.Name mangling works by changing the method’s name to include the class name. For example, a private method named
__private_method
in a classMyClass
will be mangled to_MyClass__private_method
. This can be accessed from outside the class, but it is generally discouraged as it goes against the intended encapsulation.Example:
class MyClass:
def __private_method(self):
return 'Private method'
obj = MyClass()
print(obj._MyClass__private_method()) # Output: Private method
How to call a private method from within the same class?
To call a private method from within the same class, you use the method’s name with the double underscore prefix. This is straightforward and allows you to utilize the private method for internal class operations.
Example:
class MyClass:
def __private_method(self):
return 'Private method called from within the class'
def public_method(self):
return self.__private_method() # Accessing the private method
obj = MyClass()
print(obj.public_method()) # Output: Private method called from within the class
What is the difference between private and protected methods?
- Private Methods:
- Indicated by a double underscore prefix (
__private_method
).- Intended to be used only within the class where they are defined.
- They are subject to name mangling, which changes their name to include the class name, making it harder to accidentally access them from outside the class.
- Protected Methods:
- Indicated by a single underscore prefix (
_protected_method
).- Intended for use within the class and its subclasses. It is a convention to indicate that these methods should not be accessed from outside the class.
- There is no name mangling; this is a hint to developers, not a strict rule.
Can private methods be inherited in Python?
Yes, private methods can be inherited in Python. Even though private methods are meant to be used only within the class, they still exist in the class’s namespace and can be inherited by subclasses. However, these methods are not meant to be accessed directly from the subclass.
If you want to use private methods from a subclass, you need to access them through name mangling, but this is generally not recommended as it breaks encapsulation principles.
Example:
class BaseClass:
def __private_method(self):
return 'This is a private method'
class DerivedClass(BaseClass):
def call_private(self):
return self._BaseClass__private_method() # Accessing private method via name mangling
obj = DerivedClass()
print(obj.call_private()) # Output: This is a private method
How does name mangling work with private methods?
Name mangling is a mechanism used to make private methods and attributes harder to access from outside the class. When you define a method with a double underscore prefix, Python automatically changes the method’s name to include the class name. This makes it less likely that you will accidentally access or override these methods.
For a method named
__private_method
in a classMyClass
, Python converts it to_MyClass__private_method
.Here’s how name mangling affects method names:
- Definition:
def __private_method(self):
- Mangled Name:
_MyClass__private_method
This feature allows the method to be accessed from outside the class by explicitly using the mangled name, but it is generally best to avoid accessing private methods in this way to respect the intended encapsulation.
Example:
class MyClass:
def __private_method(self):
return 'This is a private method'
# Access private method from outside the class using name mangling
obj = MyClass()
print(obj._MyClass__private_method()) # Output: This is a private method