Making a method private in a python subclass

2019-02-03 03:36发布

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 wrong order.

13条回答
迷人小祖宗
2楼-- · 2019-02-03 03:56
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/

查看更多
小情绪 Triste *
3楼-- · 2019-02-03 03:57

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
查看更多
放荡不羁爱自由
4楼-- · 2019-02-03 03:58

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!"""
查看更多
够拽才男人
5楼-- · 2019-02-03 03:58

"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.

查看更多
仙女界的扛把子
6楼-- · 2019-02-03 04:00

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.

查看更多
The star\"
7楼-- · 2019-02-03 04:02

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
查看更多
登录 后发表回答