4

Consider the following class

class Foo(object):

    @staticmethod
    def __is():
        print('__is')

    def m(self):
        Foo.__is()  # executes


Foo.__is()  # fails because of mangling

print(Foo.__dict__.keys())

Foo.__is() when it is run after the class is defined, it fails because of name mangaling. How is python interpreter able to resolve Foo.__is() inside methods but not outside the class?

Chillar Anand
  • 27,936
  • 9
  • 119
  • 136
  • https://stackoverflow.com/a/1301369/183910 – Bernhard Vallant Jan 30 '19 at 13:37
  • @BernhardVallant not a duplicate - the op clearly knows about the name-mangling mechanism, the question is "how is this implemented". – bruno desthuilliers Jan 30 '19 at 13:56
  • Note that your first two class statements raise an error because Foo is not yet defined. Used inside methods they work because methods body won't execute until called. And by then the class is already defined. – progmatico Jan 30 '19 at 15:13

2 Answers2

2

Name mangling for names starting with __ inside a class, is implemented by rewriting this names to the mangled form, inside the class ONLY. So your Foo.__is inside the class gets replaced by _Foo__is that is now present in the class __dict__. That attribute is accessible either inside or outside the class, so no private protection. But after replacement the __is name does not exist anywhere (I think), that's why it does not work from outside.

From the Python help:

"__*" Class-private names. Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes. See section Identifiers (Names).

Also see my comment to errors in your code snippet.

progmatico
  • 4,714
  • 1
  • 16
  • 27
  • You are right. I was using ipython to test code and `Foo.__is()` inside class body was working because it was using previous `Foo` class not the current one. – Chillar Anand Jan 31 '19 at 05:45
-2

You can think of classes as of namespaces with some whistles.

One of whistles is ability to resolve __methods inside themselves without _class__method. This is no different from "magic" of automatically passing instances as first argument to methods (your regular self)

To illustrate "namespace" idea, you can do some weird things like

class A:
    def insane():
        return 42

    for _ in range(5):
        print(insane()
Slam
  • 8,112
  • 1
  • 36
  • 44