2008-10-23 5 views

ответ

18

Там действительно не любой истинный «частные» атрибуты или методы в 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' 
+0

> На самом деле нет истинных «частных» атрибутов или методов в Python. Вот почему я не спрашивал, как сделать их приватными, но как «удалить» их из интерфейса. Надеюсь, что отредактированная версия более точная. – 2008-10-23 23:03:46

+2

Я согласен с тем, что NotImplementedError, вероятно, лучший, но если вы действительно хотите совместить с не унаследованным методом вообще, поднимите AttributeError (это то, что вы получите, если родительский метод не существует). – 2008-10-24 10:37:19

+1

Хорошая точка относительно AttributeError. Я обновлю свой пример. – kurosch 2008-10-24 15:37:58

5
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") 
17

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 использует «завернуть» шаблон, чтобы ограничить доступ к обернутому объекту. Martelli has a good talk имеющий дело с этим. Baz использует the property built-in для реализации протокола дескриптора для переопределения атрибута.

0

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

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

Вариантом ответа 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 на имущество, а не при вызове метода.

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