2010-06-20 18 views
5

Consideremos el siguiente ejemplo:¿Cómo proteger los errores tipográficos cuando se establece el valor para los miembros de la clase?

class A(): 
    def __init__(self): 
     self.veryImportantSession = 1 

a = A() 
a.veryImportantSession = None # ok 

# 200 lines below 
a.veryImportantSessssionnnn = 2 # I wanna exception here!! It is typo! 

¿Cómo podría hacerlo de modo que una excepción será levantado si trato de establecer un miembro que no se encuentra en __init__?

El código anterior no fallará cuando se ejecute, pero me da un tiempo divertido para solucionar los problemas.

Al igual que con str:

>>> s = "lol" 
>>> s.a = 1 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'str' object has no attribute 'a' 

Gracias!

+2

Puede obtener mejores respuestas si también explica por qué desea hacer esto. – detly

+3

Los intentos de convertir Python en Java/C++ siempre me han dejado perplejo de la misma manera que el anti-patrón de Singleton. Si no quieres más de un Foo, no lo instales, si no quieres 'a.y' no lo vincules. Si desea restringir a su usuario de la biblioteca de formas misteriosas, está haciendo algo mal. – msw

+0

bien, probablemente eso no es lo que realmente quiero hacer. El problema es que los objetos de la clase A se utilizan en muchos lugares del código, y el miembro "a" tiene una gran importancia. Digamos que su verdadero nombre es "superImportantSession". En caso de que haya hecho un error tipográfico en un lugar del código y haya escrito "a.superImportantSesssssion = 1", no obtendré ningún error cuando se ejecute esa línea de código. Pero me divertiré mucho para depurar el error. Probablemente tengo que usar setSession/getSession o smth así. – lstipakov

Respuesta

6

Puede anular __setattr__ para permitir solo nombres de atributos de una lista definida.

class A(object): 
    def __setattr__(self, name, value): 
     allowed = ('x',) 
     if name in allowed: 
      self.__dict__[name] = value 
     else: 
      raise AttributeError('No attribute: %s' % name) 

En funcionamiento:

>>> a = A() 
>>> a.x = 5 
>>> a.other = 5 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "myc.py", line 7, in __setattr__ 
    raise AttributeError('No attribute: %s' % name) 
AttributeError: No attribute: other 

Sin embargo, como msw ha comentado, los intentos de hacer que Python se comportan más como Java o C++ son por lo general una mala idea y dará lugar a la pérdida de una gran cantidad de los beneficios que Python proporciona. Si le preocupa cometer errores tipográficos que pueden pasar por alto, entonces es mucho mejor que dedique tiempo a escribir pruebas unitarias para su código que tratar de bloquear el uso de sus clases.

+2

De acuerdo con las pruebas de unidad, pero ¿es realmente la mejor manera de evitar errores tipográficos? – lstipakov

+1

Una combinación de pruebas unitarias y otros tipos de pruebas automatizadas. p.ej. utilizando su ejemplo de los comentarios sobre la pregunta en sí, si hubo una prueba que verificó el estado de su sesión antes y después de una operación, podría saber si 'superImportantSession' no se había configurado correctamente. – mikej

+1

@Stipa: Yo diría que sí, ya que tendría que hacer dos errores tipográficos iguales. Algo así como un error tipográfico durante la declaración de variable y el configurador. – Almad

1

Puede definir una variable de clase llamada __slots__. Vea el Language Reference para más información.

__slots__ solo funcionan en clases de estilo nuevo, por lo que necesita class A(object) en lugar de class A en este ejemplo.

class A(object): 
    __slots__ = ['x'] 
    def __init__(self): 
     self.x = 1 

>>> a = A() 
>>> a.x = 2 
>>> a.y = 2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'A' object has no attribute 'y' 
+2

'__slots__' es para la optimización de la memoria y muy rara vez se debe utilizar. Usarlo para "proteger contra errores tipográficos" es un uso indebido, por favor no lo recomiende para este propósito. Los principiantes no entenderán lo que están rompiendo, por ejemplo, esto rompió silenciosamente las vulnerabilidades. –

2

La mejor manera de protegerse contra los errores tipográficos es el uso de una herramienta como pyflakes o pylint - irán éstos a través de su código y dejar saber si tiene una variable a.superImportantSesssssionnnn que no se haya usado de nuevo, como así como muchas otras cosas.

Si insiste en hacerlo en código que tienen dos opciones:

  • (ab) uso __slots__ - el propósito principal de __slots__ es la optimización de la memoria para esos momentos en los que tendrá cientos, miles, o millones de objetos y necesitas mantener las huellas de tus objetos lo más pequeñas posible. Si realiza esta ruta, debe asegurarse e incluir __weakref__ como uno de los nombres permitidos para que weak references continúe funcionando.

  • (ab) uso __setattr__ - el propósito principal de __setattr__ es permitir la ejecución de código para validar, manipular, o de lo contrario tomar los datos dados y ponerla en el formato correcto para el almacenamiento

Para reiterar, las dos opciones anteriores no están destinadas a ser usadas como correctores ortográficos, y tus esfuerzos por limitar la utilidad de tu código al no permitir cada nombre de atributo posible, excepto aquellos pocos que uses, pueden no ser apreciados cuando alguien está intentando para admitir un caso de uso que no anticipó.

Cuestiones relacionadas