Making a method private in a python subclass

25,791

Solution 1

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?

Solution 2

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.

Solution 3

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.

Solution 4

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>

Solution 5

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!"""
Share:
25,791
MarkD
Author by

MarkD

Updated on November 18, 2020

Comments

  • MarkD
    MarkD over 3 years

    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.