Alex Rivera | Logout

Making a method private in a Python subclass

Asked 2009-01-16T20:53:50.157
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?

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

Edit
Report

3 Answers

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
answered 2009-01-16T21:16:58.050
7

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.

answered 2009-01-17T16:19:59.290
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.

answered 2009-01-16T20:56:31.260

Your Answer