-1

Let's say I have the following class:

class A():
    def fn1(self):
        pass
    def fn2(self):
        pass

Now I would want to call function fn3 inside both fn1 and fn2. The function fn3 should be such a way that only fn1 and fn2 should be able to call it(because fn3 would be only required by fn1 or fn2).

My Approach would be,

class A():
    def fn3(self):
        pass
    def fn1(self):
        fn3()
        pass
    def fn2(self):
        fn3()
        pass

Here I see the drawback that fn3 should have argument self(In my case fn3 does not make use of it). One more drawback would be fn3 can be called by other objects declared outside the class, which is not necessary.

Amulya K Murthy
  • 130
  • 1
  • 2
  • 15
rakesh kotian
  • 232
  • 1
  • 5
  • 30
  • If it doesn't need self, make it a static method. If it shouldn't be accessed outside the class, call it `_fn3` - a method with a leading underscore is private by convention. – jonrsharpe Oct 16 '19 at 08:33
  • Possible duplicate of [Private members in Python](https://stackoverflow.com/questions/2064202/private-members-in-python) – scooper Oct 16 '19 at 08:51

2 Answers2

0

@jonrsharpe is correct. Python is considered a "programming language for adults" - in the sense that it doesn't have mechanism to prevent a programmer from doing things you don't want them to do. By adding the double-underscore __methodName you are telling other programmers "Don't call this externally." But if they want to, they will :D

If you really want to get pedantic, you could do something similar to here and check the calling method to make sure it's an "authorized" calling method.

I.e.

import inspect

class A():
    def fn1(self):
        curframe = inspect.currentframe()
        calframe = inspect.getouterframes(curframe, 2)
        if "fn3" == calframe[1][3]:
            print("This is fn1")
        else: 
            print("NO NO! Bad function '{}'".format(calframe[1][3]))

    def fn2(self):
        curframe = inspect.currentframe()
        calframe = inspect.getouterframes(curframe, 2)
        if "fn3" == calframe[1][3]:
            print("This is fn2")
        else: 
            print("NO NO! Bad function '{}'".format(calframe[1][3]))

    def fn3(self):
        self.fn1()
        print("This is fn3")

    def notfn3(self):
        self.fn1()
        print("This is notfn3")

if __name__ == '__main__':
    o = A()
    o.fn3()
    o.notfn3()

OUTPUT:

This is fn1
This is fn3
NO NO! Bad function 'notfn3'
This is notfn3

But (IMHO), this is a lot of code, and a lot of additional processing, just to try force someone not to do something you don't want them to do.

RightmireM
  • 2,381
  • 2
  • 24
  • 42
0

The closest thing you'll find in Python to a "private" method is to declare it with two underscore __. In your case:

class A():
    def fn1(self):
        pass
    def fn2(self):
        pass
    def __fn3(self):
        pass

The self part of __fn3 is just to "bind" the method to the class. You don't need to use it in the method's body.

Depending on how complex fn3 is, another solution is to create a lambda and pass it to the other functions:

__fn3 = lambda self: print("New private bound")

class A():
    def fn1(self, myfunc):
        pass
    def fn2(self, myfunc):
        pass

a = A()
a.fn1(__fn3)
Rui Vieira
  • 5,253
  • 5
  • 42
  • 55