Python 继承 - 如何禁用函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/231839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:41:40  来源:igfitidea点击:

Python inheritance - how to disable a function

pythoninheritanceinterfaceprivate

提问by Boris Gorelik

In C++ you can disable a function in parent's class by declaring it as private in the child class. How can this be done in Python? I.E. How can I hide parent's function from child's public interface?

在 C++ 中,您可以通过在子类中将其声明为私有来禁用父类中的函数。这如何在 Python 中完成?IE 如何从孩子的公共界面隐藏父母的功能?

采纳答案by kurosch

There really aren't any true "private" attributes or methods in Python. One thing you can do is simply override the method you don't want in the subclass, and raise an exception:

Python 中确实没有任何真正的“私有”属性或方法。您可以做的一件事是简单地覆盖子类中不需要的方法,并引发异常:

>>> class Foo( object ):
...     def foo( self ):
...         print 'FOO!'
...         
>>> class Bar( Foo ):
...     def foo( self ):
...         raise AttributeError( "'Bar' object has no attribute 'foo'" )
...     
>>> b = Bar()
>>> b.foo()
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "<interactive input>", line 3, in foo
AttributeError: 'Bar' object has no attribute 'foo'

回答by cdleary

kurosch's method of solving the problem isn't quite correct, because you can still use b.foowithout getting an AttributeError. If you don't invoke the function, no error occurs. Here are two ways that I can think to do this:

kurosch 解决问题的方法不太正确,因为您仍然可以使用b.foo而无需获得AttributeError. 如果不调用该函数,则不会发生错误。以下是我可以想到的两种方法:

import doctest

class Foo(object):
    """
    >>> Foo().foo()
    foo
    """
    def foo(self): print 'foo'
    def fu(self): print 'fu'

class Bar(object):
    """
    >>> b = Bar()
    >>> b.foo()
    Traceback (most recent call last):
    ...
    AttributeError
    >>> hasattr(b, 'foo')
    False
    >>> hasattr(b, 'fu')
    True
    """
    def __init__(self): self._wrapped = Foo()

    def __getattr__(self, attr_name):
        if attr_name == 'foo': raise AttributeError
        return getattr(self._wrapped, attr_name)

class Baz(Foo):
    """
    >>> b = Baz()
    >>> b.foo() # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    AttributeError...
    >>> hasattr(b, 'foo')
    False
    >>> hasattr(b, 'fu')
    True
    """
    foo = property()

if __name__ == '__main__':
    doctest.testmod()

Bar uses the "wrap" pattern to restrict access to the wrapped object. Martelli has a good talkdealing with this. Baz uses the property built-into implement the descriptor protocol for the attribute to override.

Bar 使用“wrap”模式来限制对被包装对象的访问。Martelli 有一个很好的演讲来处理这个问题。Baz 使用内置的属性来实现要覆盖的属性的描述符协议。

回答by John Damen

A variation on the answer of kurosch:

kurosch 答案的变体:

class Foo( object ):
    def foo( self ):
        print 'FOO!'

class Bar( Foo ):
    @property
    def foo( self ):
        raise AttributeError( "'Bar' object has no attribute 'foo'" )

b = Bar()
b.foo

This raises an AttributeErroron the property instead of when the method is called.

这会AttributeError在属性上而不是在调用方法时引发。

I would have suggested it in a comment but unfortunately do not have the reputation for it yet.

我会在评论中建议它,但不幸的是还没有它的声誉。

回答by Jason Baker

class X(object):
    def some_function(self):
        do_some_stuff()

class Y(object):
    some_function = None

This may lead to some nasty and hard to find exceptions being thrown though, so you might try this:

这可能会导致抛出一些令人讨厌且难以找到的异常,因此您可以尝试以下操作:

class X(object):
    def some_function(self):
        do_some_stuff()

class Y(object):
    def some_function(self):
        raise NotImplementedError("function some_function not implemented")

回答by Joey Nelson

This is the cleanest way I know to do it.

这是我所知道的最干净的方法。

Override the methods and have each of the overridden methods call your disabledmethods() method. Like this:

覆盖这些方法并让每个覆盖的方法调用您的 disabledmethods() 方法。像这样:

class Deck(list):
...
@staticmethod
    def disabledmethods():
        raise Exception('Function Disabled')
    def pop(self): Deck.disabledmethods()
    def sort(self): Deck.disabledmethods()
    def reverse(self): Deck.disabledmethods()
    def __setitem__(self, loc, val): Deck.disabledmethods()

回答by Joey Nelson

That could be even simpler.

那可能更简单。

@property
def private(self):
    raise AttributeError

class A:
    def __init__(self):
        pass
    def hello(self):
        print("Hello World")

class B(A):
    hello = private # that short, really
    def hi(self):
        A.hello(self)

obj = A()
obj.hello()
obj = B()
obj.hi() # works
obj.hello() # raises AttributeError