2

I'm trying to call __search from parent class A in child class B but I get the error:

AttributeError: 'B' object has no attribute '_B__search'

This seems to be only happening for methods starting with __. Is there a way to call these class-private methods when doing inheritance?

class A:
    def __init__(self, a):
        self.a = a
        
    def __search(self):        
        return self.a

    def display(self):
        print(self.a)

class B(A):
    def display(self):
        res = self.__search()
        return res

cB = B(2)

cB.display()
wjandrea
  • 28,235
  • 9
  • 60
  • 81
codeBarer
  • 2,238
  • 7
  • 44
  • 75
  • 2
    By naming the method with two leading (and no trailing) underscores, you are declaring that it is a private method that cannot be accessed by child classes. Why did you do that if you want to access it from child classes? – jasonharper Jun 28 '22 at 18:39
  • 1
    Well it's more like trying to patch someones code for the short term while I can find better solution – codeBarer Jun 28 '22 at 18:40
  • 1
    For the sake of nomenclature, `__search` isn't a dunder method since it doesn't have underscores on both sides. – Daniel Walker Jun 28 '22 at 18:46

2 Answers2

4

Yes, but it's terrible practice.

In Python, a method whose name begins with __ and does not end with it (so magic methods like __add__ are excluded) is obfuscated with the class name. That is,

class A:
  def __foo(self):
    return 1

is equivalent to

class A:
  def _A__foo(self):
    return 1

So if you really want to call __search defined on A, you should write

res = self._A__search()

Again, this is bad practice. Methods starting with __ are obfuscated because that's the Python convention for private functions, so they shouldn't be called from outside the class or in subclasses. You mention in the comments that this is a temporary fix, so that's understandable, but I do hope it's not intended to stay this way for very long.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
2

An attribute name beginning with __ is private, and mangled to _classname__attribute. You need to call it by the mangled name.

class B(A):
    def display(self):
        res = self._A__search()
        return res
Barmar
  • 741,623
  • 53
  • 500
  • 612