python type-safety

plot title python



Tipo de seguridad en Python (5)

Pero no hay nada que impida que uno haga lo siguiente:

Creo que tratar de evitar que alguien haga algo así no es Pythonic. Si debe hacerlo, debería verificar la seguridad de tipos durante cualquier operación que pueda hacer utilizando Vector , en mi opinión.

Para citar GVR:

todos somos adultos

después de todo. Vea esta question y sus respuestas para más información.

Estoy seguro de que los pitonistas más experimentados aquí pueden darte mejores respuestas.

He definido una clase Vector que tiene tres variables de propiedad: x , y , z . Las coordenadas deben ser números reales, pero no hay nada que impida que uno haga lo siguiente:

>>> v = Vector(8, 7.3, -1) >>> v.x = "foo" >>> v.x "foo"

Podría implementar "seguridad de tipo" de esta manera:

import numbers class Vector: def __init__(self, x, y, z): self.setposition(x, y, z) def setposition(self, x, y, z): for i in (x, y, z): if not isinstance(i, numbers.Real): raise TypeError("Real coordinates only") self.__x = x self.__y = y self.__z = z @property def x(self): return self.__x @property def y(self): return self.__y @property def z(self): return self.__z

... pero eso parece un poco pitónico.

Sugerencias?


Debe preguntarse por qué desea probar el tipo al configurar estos valores. Solo levante un TypeError en cualquier cálculo que se tropiece con el tipo de valor incorrecto. Bonus: las operaciones estándar ya lo hacen.

>>> 3.0 / ''abc'' Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: unsupported operand type(s) for /: ''float'' and ''str''


Las otras respuestas ya indicaron que no tiene mucho sentido verificar el tipo aquí. Además, tu clase no será muy rápida si está escrita en Python puro.

Si desea una solución más pitónica, podría usar los establecedores de propiedades como:

@x.setter def x(self, value): assert isinstance(value, numbers.Real) self.__x = value

La declaración de confirmación se eliminará cuando deshabilite la depuración o habilite el modo de optimización.

Alternativamente, podría forzar el value a punto flotante en el setter. Eso generará una excepción si el tipo / valor no es convertible:

@x.setter def x(self, value): self.__x = float(value)


Se supone que no debe proporcionar seguridad de tipo de esta manera. Sí, alguien puede romper su código deliberadamente al proporcionar valores para los cuales su contenedor no funcionará, pero esto es lo mismo con otros idiomas. E incluso si alguien pone el valor correcto para un parámetro en un método o función miembro no significa necesariamente que no esté roto: si un programa espera una dirección IP, pero pasa un nombre de host, no funcionará, aunque ambos pueden ser instrumentos de cuerda.

Lo que estoy diciendo es: La mentalidad de Python es intrínsecamente diferente. La escritura de pato básicamente dice: Oye, no estoy limitado a ciertos tipos, sino a la interfaz o al comportamiento de los objetos. Si un objeto actúa como si fuera el tipo de objeto que yo esperaría, no me importa, solo hágalo.

Si intenta introducir la comprobación de tipos, básicamente está limitando una de las funciones más útiles del idioma.

Dicho esto, realmente necesitas entrar en el desarrollo guiado por pruebas, o al menos en las pruebas unitarias. Realmente no hay excusa para no hacerlo con lenguajes dinámicos: simplemente está moviendo la forma en que se detectan los errores (de tipo) a otro paso en el proceso de compilación, desde la compilación hasta la ejecución de un conjunto de pruebas varias veces al día. Si bien esto parece un esfuerzo adicional, en realidad reducirá el tiempo dedicado a depurar y corregir el código, ya que es una forma inherentemente más poderosa de detectar errores en su código.

Pero ya basta de eso, ya estoy divagando.


Escribir pato es la forma habitual en Python. Debería funcionar con cualquier cosa que se comporte como un número, pero no necesariamente es un número real.

En la mayoría de los casos, en Python no se deben verificar explícitamente los tipos. Obtiene flexibilidad porque su código puede usarse con tipos de datos personalizados, siempre que se comporten correctamente.