В С++ вы можете отключить функцию в родительском классе, объявив ее закрытой в дочернем классе. Как это можно сделать в Python? И.Е. Как скрыть родительскую функцию от дочернего общедоступного интерфейса?
Наследование Python - как отключить функцию
Ответ 1
В Python действительно нет каких-либо истинных атрибутов "private" или методов. Вы можете просто переопределить метод, который вы не хотите в подклассе, и создать исключение:
>>> 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'
Ответ 2
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()
Бар использует шаблон "wrap" для ограничения доступа к обернутому объекту. У Martelli есть хороший разговор, посвященный этому. Baz использует встроенное свойство для реализации протокола дескриптора для переопределения атрибута.
Ответ 3
Вариант ответа куроша:
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 для свойства, а не при вызове метода.
Я бы предложил его в комментарии, но, к сожалению, еще не получил его репутации.
Ответ 4
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")
Ответ 5
Это самый чистый способ, которым я это знаю.
Переопределите методы и каждый из переопределенных методов вызовет метод 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()
Ответ 6
Это может быть еще проще.
@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