Reputation: 4063
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
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
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:
Extra point which can help:
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
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