29

Is it possible to make a public method private in a subclass? I don't want other classes extending this one to be able to call some of the methods. Here is an example:

class A:
    def __init__(self):
        #do something here

    def method(self):
        #some code here

class B(A):
    def __init__(self):
        A.__init__(self)
        #additional initialization goes here

    def method(self):
        #this overrides the method ( and possibly make it private here )

from this point forward, I don't want any class that extends from B to be able to call method. Is this possible?

EDIT: a "logical" reason for this is that I don't want users to call methods in the wrong order.

John R Perry
  • 3,916
  • 2
  • 38
  • 62
Geo
  • 93,257
  • 117
  • 344
  • 520

13 Answers13

34

Contrary to popular fashion on this subject, there are legitimate reasons to have a distinction between public, private, and protected members, whether you work in Python or a more traditional OOP environment. Many times, it comes to be that you develop auxiliary methods for a particularly long-winded task at some level of object specialization. Needless to say, you really don't want these methods inherited by any subclass because they make no sense in the specialized context and shouldn't even be visible; and yet they are visible, and they diminish the utility of things like tab completion, object navigators, and other system software, because everything at all different levels of abstraction get flattened and thrown together. These programming aids are not trivial, mind you. They are only trivial if you're a student and enjoy doing the same thing a million times just because you're learning how.

Python historically developed in such a way that to implement the public/private distinction became increasingly difficult due to ideological inertia and compatibility concerns. That's the plain truth. It would be a real headache for everyone to change what they've been doing. Consequently, we now have a million Python fans out there, all of whom have read the same one or two original articles deciding unequivocally that the public/private distinction is "unpythonic". These people, for lack of critical thought or fairness to wide-spread, common practices, instantly use this occasion to accrete a predictable slew of appologetics -- De Defensione Serpentis -- which I suspect arises not from a rational selection of the via pythonis (the pythonic way) but from neglect of other languages, which they either choose not to use, are not skilled at using, or are not able to use because of work.

As someone already said, the best you can do in Python to produce an effect similar to private methods is to prepend the method name with __ (two underscores). On the other hand, the only thing this accomplishes, practically speaking, is the insertion of a transmogrified attribute name in the object's __dict__. For instance, say you have the following class definition:

class Dog(object):
    def __bark(self):
        print 'woof'

If you run dir(Dog()), you'll see a strange member, called _Dog__bark. Indeed, the only reason this trick exists is to circumvent the problem I described before: namely, preventing inheritance, overloading, and replacement of super methods.

Hopefully there will be some standardized implementation of private methods in the future, when people realize that tissue need not have access to the methods by which the individual cell replicates DNA, and the conscious mind need constantly figure out how to repair its tissues and internal organs.

Dan Gabriele
  • 349
  • 1
  • 3
  • 2
  • 2
    A nice rant. But it does not make the idea less legitimate that the user - and not the creator - of a class, or any piece of code, ultimately should have the power to decide what and how to use it. If you want to warn users, put a single underscore before names; also, that prevents cluttering tab completion. – fbmd Jul 18 '14 at 07:19
  • I needed to make a method private because I have two methods which are similar in name, but only one should be called from outside the class. The other is more of a convenience method to make things easier inside the class. I just don't want to accidentally call the wrong one by mistake. Perhaps my code could be retooled to be more "Pythonic", but that's a lotta work. I'm tired, and just want it to work tonight. :-) – MikeyE Aug 13 '16 at 07:19
29

There's no way to truly do this in Python. Rather unpythonic, it is.

As Guido would say, we're all consenting adults here.

Here's a good summary of the philosophy behind everything in Python being public.

Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
12

You can prefix methods and members with a single or double underscore. A single underscore implies "please don't use me, I'm supposed to be used only by this class", and a double underscore instructs the Python compiler to mangle the method/member name with the class name; as long as the class and its subclasses don't have the same name, the methods/members can be considered "private".

However, the solution to your requirements so far is to write clear documentation. If you don't want your users to call methods in the wrong order, then say so in the documentation.

After all, even C++ privates aren't that private. For example think the old trick:

#define private public
#include <module>
tzot
  • 92,761
  • 29
  • 141
  • 204
11

I am surprised that no one has mentioned this, but prefixing the method name with a single underscore is the correct way of labelling it as "private". It's not really private of course, (as explained in other answers), but there you go.

def _i_am_private(self):
    """If you call me from a subclass you are a naughty person!"""
Ali Afshar
  • 40,967
  • 12
  • 95
  • 109
10

Python is distributed as source. The very idea of a private method makes very little sense.

The programmer who wants to extend B, frustrated by a privacy issue, looks at the source for B, copies and pastes the source code for method into the subclass C.

What have you gained through "privacy"? The best you can hope for is to frustrate your potential customers into copying and pasting.

At worst, they discard your package because they can't extend it.

And yes, all open source is extended in one way or another. You can't foresee everything and every use to which you code will be put. Preventing some future use is hard to do when the code is distributed as source.

See How do I protect Python code?


Edit On "idiot-proof" code.

First, python is distributed as source 90% of the time. So, any idiot who downloads, installs, and then refuses to read the API guide and calls the methods out of order still has the source to figure out what went wrong.

We have three classes of idiots.

  • People who refuse to read the API guide (or skim it and ignore the relevant parts) and call the methods out of order in spite of the documentation. You can try to make something private, but it won't help because they'll do something else wrong -- and complain about it. [I won't name names, but I've worked with folks who seem to spend a lot of time calling the API's improperly. Also, you'll see questions like this on SO.]

    You can only help them with a working code sample they can cut and paste.

  • People who are confused by API's and call the methods every different way you can imagine (and some you can't.) You can try to make something private, but they'll never get the API.

    You can only help them by providing the working code sample; even then, they'll cut and paste it incorrectly.

  • People who reject your API and want to rewrite it to make it "idiot proof".

    You can provide them a working code sample, but they don't like your API and will insist on rewriting it. They'll tell you that your API is crazy and they've improved on it.

    You can engage these folks in an escalating arms race of "idiot-proofing". Everything you put together they take apart.

At this point, what has privacy done for you? Some people will refuse to understand it; some people are confused by it; and some people want to work around it.

How about public, and let the folks you're calling "idiots" learn from your code?

Community
  • 1
  • 1
S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • Well , I would like to kinda make the class "idiot proof" , as in , you can only call about 2 methods , which will do everything is needed . I don't want users to call methods in wrong order . Does this make sense ? – Geo Jan 16 '09 at 21:13
  • Python *can* be distributed in compiled form, it just usually isn't. – Kenan Banks Jan 16 '09 at 21:14
  • Donovan, the correct way of preventing them being called in the wrong order would be some state to prevent exactly that: raise RuntimeError("You must first call method1") – Ali Afshar Jan 16 '09 at 22:13
  • +1 for making me think, but python's "everything is public" agreement still makes me feel like something is missing. If you were distributing a C++ opensource library, would you declare all members and methods as public? No. No, you wouldn't. And why not? – Federico A. Ramponi Jan 17 '09 at 05:05
  • 18
    Your arguments are not against private members in Python; they are against information hiding in general. Why does information hiding make sense in C++ and Java but not in Python? – Federico A. Ramponi Jan 17 '09 at 05:07
  • 7
    The best answers a Pythonist can provide are, in general, "because that wouldn't be pythonic", or "because Guido would say ...". But these answers beg the question. – Federico A. Ramponi Jan 17 '09 at 05:16
  • 8
    Indeed, the real question is, *is information hiding useful or not?* If not, C++ and Java are messing up things for no reason. If yes, as I think, something is missing in Python. – Federico A. Ramponi Jan 17 '09 at 05:17
  • "information hiding" is a metaphor. Not a design goal or even a technical feature of any value. Private is a fussy legalistic declaration that allows change without notice. It generally *does* mess things up for no real value. – S.Lott Jan 17 '09 at 21:56
  • 74
    Information hiding is documentation. By removing crud from the API, the API becomes easier to learn. Go work on code with 150,000 methods, none of them private, and then see if you still feel like calling people idiots. – joeforker Jan 22 '09 at 18:49
  • 2
    @Daniel Holth: There's the documented API and there's the "private" keyword. Python has names that begin with "_", which are not literally "private" but are not part of the documented API. I never say "idiot-proof" because I do NOT agree that any other programmer is an idiot. – S.Lott Jan 22 '09 at 22:46
  • I always thought "private" as a "comment checked by the compiler". It is not essential, but it is useful. I can express my intent with underscores in Python, but the fact that I need to change all occurrences of a variable when I decide to change its visibility is annoying. At least I can avoid name clashes with two underscores, but it looks like a hack. – marcus Nov 08 '11 at 19:48
  • @marcus: Don't use double `__`. It creates problems and doesn't actually solve any actual problem anyone actually has. The renaming from `_name` to `name` indicates that privacy (even the Python level of privacy) is easy to overuse. It's much easier to make **everything** public except a few things which can be **proven** to be implementation-specific **and** leads to class method breakage when misused. Your "change all occurrences of a variable when I decide to change its visibility is annoying" is a great example of the consequence of overusing privacy considerations. – S.Lott Nov 11 '11 at 14:57
  • 1
    @S. Lott “doesn't actually solve any actual problem anyone actually has”. I have no words to describe my astonishment after reading this. The rationale for __ is well known, and denying the problem (name clashes) won't make your point stronger. – marcus Dec 01 '11 at 17:09
  • For example, if I subclass Thread, how can I be sure I won't overwrite some essential internal thread state if all attributes are public? – marcus Dec 01 '11 at 17:15
  • 1
    @marcus: You're sure it's correct when you're done testing. If you have private methods, you still have no idea of whether or not you overrode the public methods correctly. It's easy to get code to pass the compiler and still not work. Merely getting past the public/private compiler check tells you nothing useful out whether or not the code works. – S.Lott Dec 01 '11 at 18:38
  • @S. Lott It's easy to get code to pass *the tests* and have nasty bugs lurking around too. Getting past the public/private compiler check tells you exactly that: the variable you created is only yours, not part of the implementation of any superclass or subclass. I would not program using only global variables, so I don't see why should I program with only public variables. – marcus Dec 01 '11 at 18:50
  • @marcus: "It's easy to get code to pass the tests and have nasty bugs lurking around too". Sorry. That contradicts my understanding of testing. "I would not program using only global variables, so I don't see why should I program with only public variables" are irrelevant comparisons. Using class definitions already imposes scoping on method names. Public/private (as demonstrated in Python) doesn't **solve** any actual programming problem that unit testing doesn't solve in a more complete way. – S.Lott Dec 01 '11 at 20:13
  • 24
    This is a *very* naive answer. One bad assumption is that private methods are only necessary to avoid overriding of methods. However, it is useful in general for API use. Private methods reduce the API to the important methods; why expose useless helper methods to the end user? If anything, protected methods should be supported. Another issue (short-sighted?) is that with everything being public, you have a lot higher chance of having name conflicts of extended classes when upgrading libraries due to the code's public nature. Encapsulation and abstraction are a GOOD thing. – Lo-Tan May 08 '12 at 18:39
7

This may be a fair approximation. Lexical scoping to the "rescue":

#!/usr/bin/env python

class Foo(object):
    def __init__(self, name):
        self.name = name
        self.bar()

    def bar(self):
        def baz():
            print "I'm private"
            print self.name

        def quux():
            baz()

        self.quux = quux


if __name__ == "__main__":
    f = Foo("f")
    f.quux()

    g = Foo("g")
    g.quux()

    f.quux()

Prints:

I'm private
f
I'm private
g
I'm private
f
joeforker
  • 40,459
  • 37
  • 151
  • 246
7

"Everything must be public" proponents think the author is trying to hide a useful API from the users. This guy doesn't want to violate an unquestionable law of Python. He wants to use some methods to define a useful API, and he wants to use other methods to organize the implementation of that API. If there's no separation between the two it doesn't mean the author is not an idiot. It means the author was too lazy to actually define an API.

In Python, instead of marking properties or methods as private, they may be prefixed with _ as a weak "internal use" indicator, or with __ as a slightly stronger one. In a module, names may be prefixed with _ in the same way, and you may also put a sequence of strings that constitute the modules' public API in a variable called __all__.

A foolish consistency is the hobgoblin of little minds.

joeforker
  • 40,459
  • 37
  • 151
  • 246
6

Changing an inherited method from public to private breaks inheritance. Specifically, it breaks the is-a relationship.

Imagine a Restaurant class with a open-doors public method (i.e. it's dinnertime and we want to flip the front door sign from closed to open). Now we want a Catering class that would share many of the implementation details of Restaurant (they both need cooks, kitchens, dishes, food suppliers, and maybe even waitstaff), but not have a dining area, front doors, or the open-doors method. Inheritance from Restaurant is a mistake! It might appear that all you need to do is change the open-doors method to private so no one can use it, but then "any Catering object is-a Restaurant" is false, since part of Restaurant's public interface is open-doors. It's better to refactor Restaurant by adding a new base class and then both Restaurant and Catering derive from it.

Languages with a notion of protected or private inheritance support this idea of inheritance for implementation only, but Python is not one of those. (Nor is it useful in those languages, except rarely.) Usually when non-public inheritance is sought, containment (aka "has-a relationship") is the better path, you can even make the attribute protected or private.

Python spells protected with a single leading underscore and private with double leading underscores, with the modification of the "consenting adults" philosophy mentioned in Triptych's answer. "Dangerous" attributes and methods of your class, e.g. ones that might cause data loss, should be non-public (whether to make them protected or private is influenced by other factors), with public methods used to provide a simpler, safer interface.

5

To make a method sort of private, you can name-mangle a method like so:

class Foo:
    def __blah():
        pass

class Bar(Foo):
    def callBlah():
        self.__blah() # will throw an exception

But subclasses can still find your methods through introspection if they really want to.

But Python (by deliberate design and choice) has no notion of private members.

Dana
  • 32,083
  • 17
  • 62
  • 73
  • What about replacing the method with getattr/setattr ? Will that work ? Even if I lose the method ... – Geo Jan 16 '09 at 21:07
  • I think you could replace the property so that they call something like: subclassInstance.foo(), it'll throw an exception. But I think they'll still be able to call SuperClass.foo(subclassInstance) and still get at it. There may be more metaprogramming wizardry possible, but none that I know of. – Dana Jan 16 '09 at 21:10
1
class MyClass(object): 
    def _prtectedfunc(self):
        pass # with one undersocre

    def __privatefunc(self):
        pass # with two undersocre

http://linuxwell.com/2011/07/21/private-protected-and-public-in-python/

PersianGulf
  • 2,845
  • 6
  • 47
  • 67
1

There are many good answers in this thread but here is somewhat opinionated answer from practical point of view:

You do need to avoid crud of private members from public APIs, intellisense, docs, import * etc. So always attach _ or __ to these members.

The big question: Should it be _ or __? The purist OOP perspective is to always attach __ to private members and _ for protected methods. The __ does name mangling and makes it hard to use things like setattrib, test frameworks and reduces readability. So my personal view is to avoid __ as much as possible and use _ for private members.

But what about protected members which we want derived class to use but not as public API. My preference here is to use no underscore at all. This allows these members to get in public docs. We then rely on docstring to tell user that these are protected members like this:

class Class1:
  def _private1():
    pass

  def protected1():
    """(for derived classes) Does XYZ."""
    pass

  def public1()
    pass
Shital Shah
  • 63,284
  • 17
  • 238
  • 185
1

Even among consenting adults, there are reasons why you do not want to expose methods to a derived class. The question is, can I have a hierarchy like Parent > Child, where a user can derive from either Parent or Child but not be exposed any private or protected methods. In the following example, Child explicitly overloads Parent.__private without exposing it.

class Parent(object):
    def __private(self):
        print 'Parent'

    def go(self):
        self.__private()

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)
        self._Parent__private = self.__private

    def __private(self):
        print 'Child'
  • Are these "hidden" or inaccessible? If so, what is the point of having them at all? Could we get them and set/increment them using methods in `Parent`, without enabling them to be changed to just anything? – Andy Hayden Aug 13 '12 at 11:02
0

There are many good answers in this thread but here is somewhat opinionated answer from practical point of view:

You do need to hide (aka document) low level variables and methods from public APIs. So always attach _ or __ to these members. The bigger question: Should it be _ or __? The purist OOP perspective is to always attach __ to private members and _ to "protected" methods (i.e. accessible, overridable from derived class). The __ makes sure that derived class cannot override it. On the other hand it also makes it difficult to use things like setattr, testability and readability.

My personal view (as well as Google's style guide) is to avoid __ as much as possible and use _ for private members.

But what about protected members? How do we tell our library users what do they must/should override? Here I prefer not to use underscore for protected members and instead rely on docstring comments and optionally @abstractmethod in base class. One advantage here is that protected members then does not get dropped from various documentation generators.

Shital Shah
  • 63,284
  • 17
  • 238
  • 185