-1

I am having an unexpected issue in some code, and could reproduce it in a more simple example:

file1.py

class FirstClass:
    def function1(self):
        print("hello from function1")
    def __function2(self):
        print("hello from function2")

file2.py

from file1 import FirstClass

fc = FirstClass()

fc.function1()

fc.__function2()

..and here's what happens:

$ python file2.py 
hello from function1
Traceback (most recent call last):
  File "file2.py", line 7, in <module>
    fc.__function2()
AttributeError: FirstClass instance has no attribute '__function2'

What can you do so that the call to __function2 works? I am not really supposed to go into that imported class and make that private method public.

martineau
  • 119,623
  • 25
  • 170
  • 301
cardamom
  • 6,873
  • 11
  • 48
  • 102
  • Why is that unexpected? – Daniel Roseman Jan 11 '19 at 15:51
  • Well, it is the first time it has happened to me, that's why I wasn't expecting it. – cardamom Jan 11 '19 at 15:54
  • You can do it with `_FirstClass__function2`. If you must. I won't bother with the health warnings. See the section Private Variables here: https://docs.python.org/3.7/tutorial/classes.html – BoarGules Jan 11 '19 at 15:56
  • 1
    Note that `def __somefunction` is *not* a private method, it's used for avoiding namespace collisions, as python has no privacy model for access – C.Nivs Jan 11 '19 at 16:02
  • You can do it like was said, but should you? Someone has modelled the class thinking that client code should not access that "private" attribute. – progmatico Jan 11 '19 at 16:06
  • The class can call its own private method, also. For example: ``` class FirstClass: def function1(self): print("hello from function1") def __function2(self): print("hello from function2") def alias2(self): self.__function2() ``` – bjdduck Jan 11 '19 at 16:09
  • @progmatico I will mention it to that someone at the beginning of next week and see what they say. When he built this software it had a more limited scope of usage. His classes have already needed to be modified a few times because of this new feature, and he is more of a pragmatist than a purist.. – cardamom Jan 11 '19 at 16:12
  • @cardmom, yes, use common sense or ask someone, because if that kind of things accumulate, you start having code scattered around that reads and looks like something, but then it is not used (or isn't) like it looks. – progmatico Jan 11 '19 at 16:22

1 Answers1

2

A function with a name starting with 2 underscore characters is not intented to be called from outside its class. And in order to allow users to redefine it in a subclass with each class calling its one (not the normal method override), its name is mangled to _className__methodName.

So here, you really should not use it directly, but if you really need to, you should be able to do:

fc._FirstClass__function2()
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252