1

I am having an unexpected issue. This is the simplified code:

class test():
    def __init__(self,name):
        self.name = name

    def __private(self):
        print(self.name)

    def public(self):
        exec("self.__private()")

obj = test('John')
obj.public()

does anyone know how I can make this code work without getting rid of the exec statement?

Daan
  • 13
  • 3
  • That's not a private method. There is no such thing as "private" in Python. – Ignacio Vazquez-Abrams Sep 18 '17 at 16:35
  • @Ignacio Vazquez-Abrams it is the closest one can get to a private function if you called it like obj.__private() it would return an error – Daan Sep 18 '17 at 16:40
  • It is not any sort of private. It is not intended for making things private. It is for preventing attribute name conflicts when using multiple inheritance. – Ignacio Vazquez-Abrams Sep 18 '17 at 16:42
  • @Daan Did you try `self.__private()` without the `exec`? – SethMMorton Sep 18 '17 at 16:42
  • Why do you need `exec` at all? This seems like an XY problem to me. – Kevin Sep 18 '17 at 16:43
  • I need the exec because of the way the original code is build, it requires the repeated calling of functions on functions which change every time it is run. So instead it generates a string that can be run. This enables me to change the code that is used every turn the program in run. – Daan Sep 18 '17 at 16:45

1 Answers1

2

Names of attributes starting with two underscores and not ending with two underscores are subject to name mangling.

When you do

def __private(self):
    print(self.name)

in a class definition, you actually create a method called _<ClassName>__private.

You can still access it normally as __private within the class body (using a proper qualifier, such as self, if applicable), but in order to call it via exec or eval, or outside of the class body, you'll have to use its full name:

def public(self):
    exec('self._test__private()')
vaultah
  • 44,105
  • 12
  • 114
  • 143