Подтвердить что ты не робот

Наследование Python - как отключить функцию

В С++ вы можете отключить функцию в родительском классе, объявив ее закрытой в дочернем классе. Как это можно сделать в Python? И.Е. Как скрыть родительскую функцию от дочернего общедоступного интерфейса?

4b9b3361

Ответ 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