Question

J'ai défini une classe Vector qui a trois variables de propriété: x, y et z. Les coordonnées doivent être des nombres réels, mais il n'y a rien pour arrêter un de faire ce qui suit:

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

Je pourrais mettre en œuvre la "sécurité de type" comme ceci:

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

... mais qui semble non Pythonic.

Suggestions?

Était-ce utile?

La solution

Vous devez vous demander pourquoi vous voulez le type de test sur la définition de ces valeurs. Il suffit de lever un TypeError dans le calcul qui arrive à trébucher sur la mauvaise valeur Type. Bonus:. Opérations standard font déjà

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

Autres conseils

Canard Typing est de la manière habituelle en Python. Il devrait fonctionner avec tout ce qui se comporte comme un nombre, mais pas nécessairement est un nombre réel.

Dans la plupart des cas en Python il ne faut pas explicitement vérifier les types. Vous gagnez la flexibilité parce que votre code peut être utilisé avec des types de données personnalisés, aussi longtemps qu'ils se comportent correctement.

Les autres réponses déjà fait remarquer qu'il ne fait pas beaucoup de sens pour vérifier le type ici. En outre, votre classe ne sera pas très rapide s'il est écrit en Python pur.

Si vous voulez une solution plus pythonique - vous pouvez utiliser setters de propriété comme:

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

L'instruction assert sera supprimé lorsque vous désactivez le débogage ou activer le mode optimisation.

Sinon, vous pouvez forcer value à point flottant dans le poseur. Cela déclenche une exception si le type / valeur est convertible:

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

Mais il n'y a rien pour arrêter un de faire ce qui suit:

Je crois en essayant d'empêcher quelqu'un de faire quelque chose comme ça est non Pythonic. Si vous devez, alors vous devriez vérifier la sécurité de type pendant toutes les opérations que vous pourriez faire en utilisant Vector, à mon avis.

Pour citer G.V.R:

  

nous sommes tous adultes.

après tout. Voir cette question et ses réponses pour plus d'informations.

Je suis sûr Pythoneux plus expérimenté ici peut vous donner de meilleures réponses.

Vous n'êtes pas censé assurer la sécurité du type de cette façon. Oui, quelqu'un peut délibérément briser votre code en fournissant des valeurs pour lesquelles votre conteneur ne fonctionnera pas - mais cela est la même chose avec d'autres langues. Et même si quelqu'un a mis la bonne valeur pour un paramètre dans une méthode ou une fonction membre ne signifie pas nécessairement qu'il est pas cassé: Si un programme attend une adresse IP, mais vous passez un nom d'hôte, il ne fonctionne toujours pas, même si les deux peuvent être cordes.

Ce que je veux dire est: L'état d'esprit de Python est fondamentalement différent. frappe de canard dit essentiellement: Hé, je ne suis pas limité à certains types, mais à l'interface, ou le comportement des objets. Si un objet ne agit comme c'est le genre d'objet que je pense, je ne me soucie pas -. Allez-y juste

Si vous essayez d'introduire la vérification de type, vous limitez essentiellement l'une des plus caractéristiques utiles de la langue.

Cela étant dit, vous avez vraiment besoin d'entrer dans le développement piloté par tests ou tests unitaires au moins. Il n'y a vraiment aucune excuse pour ne pas faire avec les langues dynamiques - il est juste de déplacer le chemin (type) des erreurs sont détectées à une autre étape dans le processus de construction, loin de la compilation à l'exécution d'une suite de tests plusieurs fois par jour. Bien que cela semble effort supplémentaire, il va réduire le temps passé sur le débogage et le code de fixation, comme il est un moyen intrinsèquement plus puissant pour détecter les erreurs dans votre code.

Mais assez de cela, je suis déjà décousu.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top