pashute
pashute

Reputation: 4063

How to call a __private static method from other methods in python

I'm assuming a private static method in a Python class is something that can and should be done. But perhaps in actuality, I should simply be using a module private method outside the class.

I want to understand calling different kinds of static methods from various locations:

I have a Python class with a private and a public static method. I want to call them from other places, and from each other.

When outside the class and calling the public static method, I must add the classname. i.e.

m = MyClass.the_staticmethod(100) # I must use the classname as a prefix

See questions in code:

    class Myclass():
        @staticmethod
        __my_privatestaticmethod(myparam):
             return myparam

        @staticmethod
        def the_staticmethod(myparam):
            # will the following work?
            result = __my_staticmethod(1) # will this work?

            # data-mingling set as private, so following line cannot work!
            result = Myclass.__my_staticmethod(2) # this cannot work. 

            result = the_staticmethod(3) # will this work without the prefix

            return result
 

        def __my_privatemethod(self, param1):
            # which of the following are valid?
            return __my_staticmethod(11) # will this work?

            # data-mingling set as private, so following line cannot work!
            return Myclass.__my_staticmethod(12) # this cannot work. 

            return the_staticmethod(13) # will this work without the prefix of the class? 
            
            return self.the_staticmethod(14) # will this work. Is the self also considered the class? 

            return  Myclass.the_staticmethod(15) # this of course works. 
            

        def the_method(param1):
            return __my_staticmethod(param1) # will this work?

If the answers to 1 and 11 are no, then the conclusion is that you cannot make a private static method.

I would then make a private module method outside the class without a decorator. This would be equivalent to the private static class method.

    def __my_privatemodulemethod(param1):
         return param1

and can call it from anywhere in my module, without a prefix.

Upvotes: 10

Views: 31728

Answers (3)

stansy
stansy

Reputation: 308

We can just as well declare an alias for a private method. Following Bruno's example, we can do this in a simple way:

class Foo(object):
  @classmethod
  def __protected(self, arg):
     print("{}._protected() called with {}".format(self.__name__, arg))    
  public = Foo.__protected 

try:
  Foo.public('public')
  Foo.__protected('protected')
except AttributeError as e:
  print(e)

Foo._protected() called with public
type object 'Foo' has no attribute '__protected'

Upvotes: 0

Gopal Gupta
Gopal Gupta

Reputation: 31

I tried every possible thing which can be done in calling static methods and the results were surprising. For understanding this thing, there are few things, we need to recall:

  1. (i) Private members can be accessed WITHIN THE CLASS, i.e. in other methods. (ii) To access private members outside the class we have to use _ClassName__privateMember.
  2. Static methods can only be accessed using class or object.

Extra point which can help:

  1. Any method of a class can be accessed using class. For instance method you have to pass object as self argument i.e., Myclass.instanceMethod(obj,params).

    class Myclass():
        @staticmethod
        def __myPrivateStaticMethod(myparam):
            return myparam   
        @staticmethod
        def myStaticMethod(myparam):   
            # result = __myPrivateStaticMethod(1)           # This will not work. Point 2   
            # data-mingling set as private outside the class, but can be accessed within the class
            result = Myclass.__myPrivateStaticMethod(2)     # This will work. Point 1 (i)   
            # result = myStaticMethod(3)                    # This will not work. Point 2   
            return result   
        def __myPrivateMethod(self, param1):   
            # result = __myPrivateStaticMethod(11)          # This will not work. Point 2   
            # data-mingling set as private outside the class, but can be accessed within the class
            result = Myclass.__myPrivateStaticMethod(12)    # This will work. Point 1 (i)   
            # result = myStaticMethod(13)                   # This will not work Point 2   
            # self is object of the class
            result = self.myStaticMethod(14)                # This will work Point 2   
            # this of course works. Point 2
            result = Myclass.myStaticMethod(15)
            return result   
        def instanceMethod(self, param1):
            # return __myPrivateStaticMethod(param1)        # This will not work. Point 2
            Myclass._Myclass__myPrivateMethod(self, 45)     # This will work. Point 3
            pass   
    obj = Myclass()
    obj._Myclass__myPrivateStaticMethod(45)                 # Point 1 (ii) and Point 2
    obj.myStaticMethod(45)                                  # Point 2
    obj._Myclass__myPrivateMethod(45)                       # Point 1 (ii)
    obj.instanceMethod(45)                                  
    Myclass._Myclass__myPrivateMethod(obj,45)               # Point 3
    

Hope Everything will be clear.

Upvotes: 3

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

As deceze already mentionned in a comment, in Python a staticmethod is a method that doesn't take the instance nor the class as first argument. Since Python has no implicit this pointer, obviously a staticmethod has no way to reference the current class, so it cannot call another staticmethod on the current class. The obvious solution here is to use classmethods instead (classmethods takes the current class as first argument):

class Foo(object):
    @classmethod
    def _protected(cls, arg):
        print("{}._protected() called with {}".format(cls.__name__, arg))

    @classmethod
    def public(cls, arg):
        cls._protected(arg)

there IS a notion of private/public achieved with data mingling

s/data mingling/name mangling/g ;)

"dunder" names and the name mangling mechanism don't make anything private:

class Foo(object):
    @staticmethod
    def __not_private():
        print("peek a boo")


Foo._Foo_not_private()

As the "clunky" doc states, the point here is mostly to avoid accidental overridding of some important implementation part of a base class. Practically this is very seldom used, and most of the time not even really needed. The convention to indicate "implementation" methods and attribute is to name them with a single leading underscore.

As a side note, snarky remarks about Python's doc quality is not going to get you much helping friends.

Upvotes: 16

Related Questions