Python 继承 - 如何禁用一个函数

41 投票
7 回答
31812 浏览
提问于 2025-04-11 19:08

在C++中,你可以通过在子类中把父类的某个函数声明为私有的,来禁用这个函数。那么在Python中该怎么做呢?也就是说,如何让子类的公共接口中隐藏父类的函数呢?

7 个回答

15

这是对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

这样做会在属性上引发一个AttributeError错误,而不是在调用方法的时候出现这个错误。

我本来想在评论里提这个建议,但可惜我还没有足够的声望来评论。

20

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使用“包装”模式来限制对被包装对象的访问。Martelli有一场很好的讲座讨论了这个问题。Baz使用内置的property来实现属性的描述符协议,以便进行覆盖。

34

在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'

撰写回答