Python继承-如何禁用函数 C++中,可以通过在子类中声明它为私有函数来禁用父类中的函数。如何在Python中实现这一点?也就是说,我如何从孩子的公共界面隐藏家长的功能 class X(object): def some_function(self): do_some_stuff() class Y(object): some_function = None

Python继承-如何禁用函数 C++中,可以通过在子类中声明它为私有函数来禁用父类中的函数。如何在Python中实现这一点?也就是说,我如何从孩子的公共界面隐藏家长的功能 class X(object): def some_function(self): do_some_stuff() class Y(object): some_function = None,python,inheritance,interface,private,Python,Inheritance,Interface,Private,但这可能会导致抛出一些令人讨厌且难以发现的异常,因此您可以尝试以下方法: class X(object): def some_function(self): do_some_stuff() class Y(object): def some_function(self): raise NotImplementedError("function some_function not implemented") Python中确实没有任何真正的“私有

但这可能会导致抛出一些令人讨厌且难以发现的异常,因此您可以尝试以下方法:

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

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

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'
>>类Foo(对象):
...     def foo(self):
...         打印“FOO!”
...         
>>>分类栏(Foo):
...     def foo(self):
...         raise AttributeError(“'Bar'对象没有属性'foo'”)
...     
>>>b=巴()
>>>b.foo()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第3行,在foo中
AttributeError:“Bar”对象没有属性“foo”

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

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使用“包裹”模式限制对包裹对象的访问。处理这件事。Baz用于为要覆盖的属性实现描述符协议。

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

重写这些方法,并让每个被重写的方法调用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()

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


我本想在评论中提出这一点,但不幸的是,目前还没有这样的名声。

这可能更简单

@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

另一种方法是定义一个描述访问错误的描述符

    class NotHereDescriptor:
        def __get__(self, obj, type=None):
            raise AttributeError
    
    class Bar:
        foo = NotHereDescriptor()
这在本质上类似于上面几个人使用的财产法。但是,它的优点是
hasattr(Bar,'foo')
将返回
False
,如果函数真的不存在,这是可以预料的。这进一步减少了出现奇怪虫子的机会。尽管它仍然显示在
dir(Bar)


如果您感兴趣的是它在做什么以及它为什么起作用,请查看数据模型页面的描述符部分和描述符如何

>在Python中确实没有任何真正的“私有”属性或方法。这就是为什么我没有问如何使它们私有化,而是问如何从接口中“删除”它们。希望编辑后的版本更准确我同意NotImplementedError可能是最好的使用方法,但是如果你真的想匹配根本没有继承的方法,请改为使用AttributeError(如果父方法不存在,你会得到AttributeError)。关于AttributeError的观点很好。我将更新我的示例。这并不是你想要的——只有当foo方法被/invoked/--getattr(b,'foo')仍然返回一个方法对象(一个属性!)时,才会引发AttributeError。@JBernardo,你不应该对答案投否决票,因为它没有以你认为最好的方式回答问题。问题中没有任何东西表明这个答案是错误的。剥猫皮的方法不止一种。当然,在我的回答中,它仍然是“可见的”,但你不能“使用”它本身,因为它会引发异常。一个有效的点,但是。+1,使用“空”属性来“删除”foo方法是多么聪明的把戏啊!:因为没有子类,所以这将破坏类以使用在父类上定义的运算符。另外
\uuu getattr\uuuu
也很慢。将其设置为
property()
而不是任何其他属性(如
None
)的优点是什么?如果调用
getattr(b,“Foo”)
,会不会导致AttributeError?不幸的是,我这里没有Python解释器来测试它。如果你的意思是
getattr(b,'foo')
,那么是的,它会是的,这就是我的意思。虽然
getattr(b,'Foo')
也会给您一个属性错误,所以不用担心!这是一种有趣的方法,但是您需要确保在pop情况下参数号匹配,并且允许关键字args进行排序和反转。否则将抛出TypeError而不是预期的异常。