【发布时间】:2010-09-18 21:53:07
【问题描述】:
在 C++ 中,您可以通过在子类中将其声明为私有来禁用父类中的函数。如何在 Python 中做到这一点? IE。如何在孩子的公共界面中隐藏父母的功能?
【问题讨论】:
标签: python inheritance interface private
在 C++ 中,您可以通过在子类中将其声明为私有来禁用父类中的函数。如何在 Python 中做到这一点? IE。如何在孩子的公共界面中隐藏父母的功能?
【问题讨论】:
标签: python inheritance interface private
class X(object):
def some_function(self):
do_some_stuff()
class Y(object):
some_function = None
这可能会导致一些令人讨厌且难以发现的异常被抛出,所以你可以试试这个:
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'
【讨论】:
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 使用“wrap”模式来限制对被包装对象的访问。 Martelli has a good talk 处理这个问题。 Baz 使用the property built-in 实现要覆盖的属性的描述符协议。
【讨论】:
__getattr__ 也很慢
property()而不是其他任何东西有什么好处,例如None?
这是我所知道的最干净的方法。
覆盖这些方法并让每个被覆盖的方法调用您的 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()
【讨论】:
@staticmethod缩进的答案
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。
我会在评论中建议它,但不幸的是还没有它的声誉。
【讨论】:
getattr(b, "Foo"),这会引发 AttributeError 吗?不幸的是,我这里没有 Python 解释器来测试它。
getattr(b, 'foo'),那么是的
getattr(b, 'Foo') 也会给你一个属性错误,所以不用担心!
这可能更简单。
@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)。
如果您对它的作用及其工作原理感兴趣,请查看数据模型页面 https://docs.python.org/3/reference/datamodel.html#descriptors 的描述符部分以及如何使用 https://docs.python.org/3/howto/descriptor.html 的描述符
【讨论】: