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

Bor*_*lik 31 python inheritance private interface

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

kur*_*sch 23

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'
Run Code Online (Sandbox Code Playgroud)

  • 这不符合你的要求 - 只有在foo方法被/ invoked /时,才会引发AttributeError - getattr(b,'foo')仍然返回一个方法对象(属性!). (8认同)
  • 我同意NotImplementedError可能是最好用的,但是如果你真的想要匹配没有继承的方法,那么引发AttributeError(如果父方法不存在,那就是你得到的). (4认同)
  • -1这个答案仍然允许访问该属性. (4认同)
  • Python 关于 `NotImplementedError` 的文档建议将其设置为 `None`:“它不应该用于指示根本不支持某个运算符或方法 - 在这种情况下,要么保留运算符/方法未定义,要么如果子类,将其设置为 None。” (2认同)

cdl*_*ary 18

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()
Run Code Online (Sandbox Code Playgroud)

Bar使用"wrap"模式来限制对包装对象的访问.Martelli对此有一个很好的谈话.Baz使用内置属性来实现要覆盖的属性的描述符协议.

  • 嗯,当然,在我的回答中它仍然是"可见的",但你不能"使用"它本身,因为它会引发异常.但有一点是有效的. (2认同)
  • +1,使用"空"属性"删除"foo方法的智能技巧!:d (2认同)

Joh*_*men 11

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
Run Code Online (Sandbox Code Playgroud)

这会引发AttributeError属性,而不是调用方法时.

我会在评论中提出这个问题,但遗憾的是还没有它的声誉.


Jas*_*ker 5

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

class Y(object):
    some_function = None
Run Code Online (Sandbox Code Playgroud)

这可能会导致一些令人讨厌且难以发现的异常被抛出,所以你可以试试这个:

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

class Y(object):
    def some_function(self):
        raise NotImplementedError("function some_function not implemented")
Run Code Online (Sandbox Code Playgroud)