Наследование Python - как отключить функцию - PullRequest
28 голосов
/ 24 октября 2008

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

Ответы [ 5 ]

20 голосов
/ 24 октября 2008

На самом деле в 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'
17 голосов
/ 25 октября 2008
Метод

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()

Бар использует шаблон «обтекание», чтобы ограничить доступ к обернутому объекту. Мартелли хорошо говорит , имея дело с этим. Baz использует встроенное свойство для реализации протокола дескриптора для переопределения атрибута.

10 голосов
/ 17 апреля 2014

Вариант ответа от 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 для свойства вместо того, когда вызывается метод.

Я бы предложил это в комментарии, но, к сожалению, пока не пользуюсь репутацией.

5 голосов
/ 24 октября 2008
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")
1 голос
/ 17 апреля 2014

Это самый чистый способ, которым я знаю.

Переопределите методы, и каждый из переопределенных методов вызовет ваш метод 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()
...