Skip to content

robertbenson/Python_Private_Variables

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Python Private Variables and Methods

Python does not have true private variables. It does not enforce privacy in the way some other languages like Java or C++ do.
A general guideline that helps produce better code, encapsulation, is to make everything as hidden as possible. This can be achieved by using underscores, single or double.

Encapsulation

Encapsulation is where data and the methods that work on data are within one unit. This puts restrictions on accessing variables and methods directly and can prevent the accidental modification of data. There are two ways this can be achieved using Python:

1 Single Underscore

_foo: Python convention says that this is to be treated as a private variable. There is no Python enforcement and it is a weak indicator.

2 Double Underscores

__foo: This takes privacy to the next level, name mangling will be used, there will be Python enforcement and is therefore stronger. The idea of a private attribute is to make it accessible within the class only, encapsulating the data.

Name Mangling - leading double underscore

Leading double underscore names are a signal that the variable is intended to be "private", meaning it should not be accessed or modified directly from outside its containing class. Variables with double underscores have their local scope enforced when a variable in a function is declared with a double underscore. It is used to prevent accidental reuse of variables or clashes.

Name mangling sounds more complicated than it is. It is just the variable name with the class name and _ prefixed to the front.

mangled name: _ + <class name> + __variable

In the example code, the __counter variable is prefixed by the name of the class. The Python interpreter will automatically mangle leading __ names.

Therefore, the new mangled name for the original variable name __counter in class Singleton becomes _Singleton__counter

Enforcement - AttributeError raised

The following unittest, correctly raises an AttributeError. The variable name has been mangled by the Python interpreter and does not appear to the programmer in its originally typed form. The name that the programmer is trying to access does not exist. The user may not access the variable and an error is raised, this is a desired behaviour.

        def test_get_private_variable_error(self):
        """access member variable not allowed."""
        with self.assertRaises(AttributeError):
            dun1 = Singleton()
            x = dun1.__counter

AttributeError can be avoided

The mangled name can be accessed without raising an error.

This is not recommended as it violates the principle of encapsulation, but it is possible and is therefore not truly private.

It is here for demonstration purposes only.

unittest - passes using mangled name

    def test__modify_contents_mangled_name(self):
        """Demostration purposes only. This is not good programming
        practice."""
        self.s1._Singleton__counter = 345
        print(f"s1.__dict__: {self.s1.__dict__}")
        print(f"s2.__dict__: {self.s2.__dict__}")
        print(f"s3.__dict__: {self.s3.__dict__}")
        self.assertEqual(self.s1._Singleton__counter, 345)
        self.assertEqual(self.s1._Singleton__counter, self.s3._Singleton__counter)
        self.assertEqual(self.s2._Singleton__counter, self.s3._Singleton__counter)

output

    s1.__dict__: {'_Singleton__counter': 345}
    s2.__dict__: {'_Singleton__counter': 345}
    s3.__dict__: {'_Singleton__counter': 345}

Releases

No releases published

Packages

No packages published

Languages