Reputation: 7839
Consider a class with a "private" method such as:
class Foo(object):
def __init__(self):
self.__method()
def __method(self):
print('42')
When I try to subclass Foo
and override method __method
, it can be seen that Foo.__method
is still called, instead of MoreFoo.__method
.
class MoreFoo(Foo):
def __method(self):
print('41')
>>> MoreFoo()
42
<__main__.MoreFoo object at 0x7fb726197d90>
What would be the way to override such a method?
Upvotes: 25
Views: 20343
Reputation: 1125368
The point of using the double-underscore name convention is to prevent subclasses from (accidentally) overriding the method.
If you have to override it anyway, someone made a serious class design error. You can do it still, by naming your object just so:
def _Foo__method(self):
where you prefix the method name with one more underscore and the defining classname (so in this case prefixed with _Foo
). The process of renaming methods and attributes with a double underscore is called private name mangling.
If you want to define a 'private' method that is still overridable in a subclass, you generally stick to names with one underscore instead (def _method(self):
).
Due to its dynamic nature, almost nothing in Python is truly private; with a little introspection almost anything can be reached.
Upvotes: 45
Reputation: 89097
A double underscore prefix invokes name mangling. It is not equivalent to a private method and is specifically designed to avoid being overridden by subclasses (and in this case, the method name becomes _Foo__method
).
If you have an implementation detail, prefix it with a single underscore. This is the universally accepted sign for Python methods that are not to be used externally. There is no enforcement of this, because that's not the way Python functions.
Upvotes: 16
Reputation: 310307
I believe that you would do something like:
class MoreFoo(Foo):
def _Foo__method(self):
print('41')
as documented.
Any identifier of the form
__spam
(at least two leading underscores, at most one trailing underscore) is textually replaced with_classname__spam
, whereclassname
is the current class name with leading underscore(s) stripped.
But the designers of the original class were of the opinion that you shouldn't need to do something like this as making it difficult to override with subclassing is the whole point of the double underscores to begin with:
Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls.
Upvotes: 6