В C++ вы можете отключить функцию в родительском классе, объявив ее как приватную в дочернем классе. Как это можно сделать в Python? т.е. Как я могу скрыть родительскую функцию от общедоступного интерфейса ребенка?
Наследование Python — как отключить функцию
Ответы (7)
На самом деле в 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'
NotImplementedError
рекомендует просто установить его в None
: его не следует использовать для указания того, что оператор или метод вообще не предназначен для поддержки — в этом случае либо оставьте оператор/метод неопределенным, либо, если это подкласс, установите его на Нет.
- person Bachsau; 17.12.2018
способ решения проблемы Курошем не совсем корректен, потому что вы все еще можете использовать 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()
Бар использует шаблон «обертки», чтобы ограничить доступ к обернутому объекту. Мартелли хорошо рассказал об этом. Baz использует встроенное свойство для реализации протокола дескриптора для атрибут для переопределения.
__getattr__
медленный
- person JBernardo; 21.04.2013
property()
вместо чего-либо еще, например None
?
- person Praxeolitic; 10.04.2016
Вариант ответа куроша:
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")
? К сожалению, у меня нет интерпретатора Python, чтобы протестировать его.
- person Adrian Ratnapala; 17.04.2014
getattr(b, 'foo')
, то да, будет
- person John Damen; 17.04.2014
getattr(b, 'Foo')
также выдаст вам ошибку атрибута, так что не беспокойтесь!
- person Adrian Ratnapala; 17.04.2014
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")
Это самый чистый способ, который я знаю.
Переопределите методы, и пусть каждый из переопределенных методов вызывает ваш метод 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()
Другой подход заключается в определении дескриптора, который выдает ошибки при доступе.
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
Это может быть еще проще.
@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