2008-10-23 10 views

Respuesta

18

Realmente no hay ninguna verdad "privado" atributos o métodos en Python . Una cosa que puede hacer es simplemente reemplazar el método no desea en la subclase, y elevar una excepción: Método

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

> Realmente no hay ningún verdadero atributo o método "privado" en Python. Es por eso que no pregunté cómo hacer que sean privados, sino cómo 'eliminarlos' de la interfaz. Espero que la versión editada sea más precisa. –

+2

Estoy de acuerdo en que NotImplementedError es probablemente el mejor para usar, pero si realmente deseas que coincida con no tener el método heredado, levanta AttributeError en su lugar (que es lo que obtendrías si el padre el método no existía). –

+1

Buen punto con respecto a AttributeError. Actualizaré mi ejemplo. – kurosch

5
class X(object): 
    def some_function(self): 
     do_some_stuff() 

class Y(object): 
    some_function = None 

Esto puede conducir a una cierta desagradable y difícil de encontrar excepciones ser lanzado sin embargo, por lo que podría intentar esto:

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

de kurosch de resolver el problema no es del todo correcto, porque todavía puede utilizar sin b.foo obteniendo un AttributeError. Si no invocas la función, no se produce ningún error. Aquí hay dos maneras que se me ocurre de hacerlo:

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 utiliza el patrón de "envolver" para restringir el acceso al objeto envuelto. Martelli has a good talk que trata de esto. Baz usa the property built-in para implementar el protocolo descriptor para el atributo anular.

+2

Bueno, claro, en mi respuesta todavía es "visible", pero no se puede "usar" per se porque generará la excepción. Un punto válido, sin embargo. – kurosch

+2

+1, ¡qué truco inteligente usar una propiedad "vacía" para "eliminar" el método foo! : D – MestreLion

+0

Esto romperá la clase para el uso de operadores definidos en el padre porque no hay subclases. También '__getattr__' es lento – JBernardo

0

Esta es la manera más limpia que conozco para hacerlo.

Reemplace los métodos y haga que cada uno de los métodos reemplazados invoque su método disabledmethods(). De esta manera:

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

Una variación en la respuesta de 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 

Esto plantea una AttributeError en la propiedad en lugar de cuando se llama al método.

Lo hubiera sugerido en un comentario, pero desafortunadamente aún no tengo la reputación para él.

+0

¿Aumentará AttributeError si llama a 'getattr (b," Foo ")'? Desgraciadamente, no tengo un intérprete de Python aquí para probarlo. –

+0

si te refieres a 'getattr (b, 'foo')' entonces sí lo hará –

+0

Sí, eso es lo que quise decir. Aunque 'getattr (b, 'Foo')' también te dará un error de Atributo, ¡así que no te preocupes! –

Cuestiones relacionadas