January 19, 2022

Underscores in Python. Part-2

Underscores in Python. Part-2. © [0|1]

We are going to continue underscores that we have started exploring last time.

2. Trailing underscore:

var_

Well, trailing underscore's used only for giving Python's keyword names to variables. Let's so on the example:

print_ #instead of print
while_ #instead of while

3. Double leading (dunders) underscores:

__var

Avoid naming conflicts in subclasses by rewriting the name of a class attribute in a class context — name mangling. The attribute would be protected from being overridden. For example:

class Parent:
     def __init__(self):
         self.foo = 11
         self.__baz = 23

t = Parent()
print(dir(t))

As an output we get:

['_Parent__baz', '__class__', '__delattr__', '__dict__', '__dir__', 
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', 
'__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 
'__weakref__', 'foo']

Another example:

class Child(Parent):
      def __init__(self):
          super().__init__()
          self.foo = 'overridden'
          self.__baz = 'overridden'

t2 = Child()
t2.foo #overriden
t2.__baz

As a result we get the following error:

AttributeError:
"'Child' object has no attribute '__baz'"

Let's continue exploring a code from the example:

print(dir(t2)) #a long list of attributes
t2._Child__baz #ovverriden
t2._Parent__baz #result is 42

We have noticed that variables reserved by using dir(). The name mangling is transparent to a programmer. That my seem confusing, right? Let's look at an example:

class ManglingTest:
      def __init__(self):
          self.__mangled = 'hello'
          
      def get_mangled(self):
          return self.__mangled

ManglingTest().get_mangled() #we get 'hello'
ManglingTest().__mangled #it raises AttributeError
AttributeError:
"'ManglingTest' object has no attribute '__mangled'"

We are getting access via the class method that uses the original name.

That's a lot to consume. Spend a little time and play with the example to get it more clearly. I know that you can get it. Good luck in your exploration.👍🏼