Question Quelle est la manière canonique de vérifier le type en Python?


Quel est le meilleur moyen de vérifier si un objet donné est d'un type donné? Que diriez-vous de vérifier si l'objet hérite d'un type donné?

Disons que j'ai un objet o. Comment puis-je vérifier si c'est un str?


886
2017-09-30 11:00


origine


Réponses:


Pour vérifier si o est une instance de str ou toute sous-classe de str, utilisation isinstance (Ce serait la manière "canonique"):

if isinstance(o, str):

Pour vérifier si le type de o est exactement str:

if type(o) is str:

Ce qui suit fonctionne également, et peut être utile dans certains cas:

if issubclass(type(o), str):

if type(o) in ([str] + str.__subclasses__()):

Voir Fonctions intégrées dans la référence de la bibliothèque Python pour des informations pertinentes.

Une note de plus: dans ce cas, si vous utilisez python 2, vous voudrez peut-être utiliser:

if isinstance(o, basestring):

car cela capture également les chaînes Unicode (unicode n'est pas une sous-classe de str; tous les deux str et unicode sont des sous-classes de basestring). Notez que basestring n'existe plus dans python 3, où il y a une séparation stricte de cordes (str) et des données binaires (bytes).

Alternativement, isinstance accepte un tuple de classes. Cela retournera True si x est une instance de n'importe quelle sous-classe de (str, unicode):

if isinstance(o, (str, unicode)):

1104
2017-09-30 11:07



le plus La façon pythonique de vérifier le type d'un objet est ... de ne pas le vérifier.

Depuis que Python encourage Duck Typing, vous devriez juste essayer d'utiliser les méthodes de l'objet comme vous voulez les utiliser. Donc, si votre fonction recherche un objet fichier inscriptible, ne pas vérifier que c'est une sous-classe de file, essayez d'utiliser son .write() méthode!

Bien sûr, parfois ces belles abstractions se décomposent et isinstance(obj, cls) est ce dont vous avez besoin. Mais utilisez avec parcimonie.


142
2017-09-30 17:40



isinstance(o, str) reviendra true si o est un str ou est d'un type qui hérite de str.

type(o) is str reviendra true si et seulement si o est un str. Il reviendra false si o est d'un type qui hérite de str. ----


38
2017-09-30 11:05



Après la question a été posée et a répondu, les astuces de type ont été ajoutées à Python. Les astuces de type en Python permettent de vérifier les types mais de manière très différente des langages statiquement typés. Les indications de type en Python associent les types d'arguments attendus avec des fonctions en tant que données accessibles à l'exécution associées aux fonctions et ceci permet pour les types à vérifier. Exemple de syntaxe d'indice de type:

def foo(i: int):
    return i

foo(5)
foo('oops')

Dans ce cas, nous voulons qu'une erreur soit déclenchée pour foo('oops') puisque le type annoté de l'argument est int. L'indice de type ajouté ne cause une erreur à se produire lorsque le script est exécuté normalement. Cependant, il ajoute des attributs à la fonction décrivant les types attendus que d'autres programmes peuvent interroger et utiliser pour vérifier les erreurs de type.

Un de ces autres programmes qui peuvent être utilisés pour trouver l'erreur de type est mypy:

mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"

(Vous devrez peut-être installer mypy de votre gestionnaire de paquets. Je ne pense pas que cela vienne avec CPython mais semble avoir un certain niveau de "officialité".)

La vérification de type de cette manière est différente de la vérification de type dans les langages compilés statiquement typés. Parce que les types sont dynamiques en Python, la vérification de type doit être faite à l'exécution, ce qui impose un coût - même sur les programmes corrects - si nous insistons sur le fait que cela arrive à chaque occasion. Les vérifications de type explicites peuvent également être plus restrictives que nécessaire et provoquer des erreurs inutiles (par exemple, l'argument doit-il vraiment être exact? list tapez ou est-ce que quelque chose d'itérable suffit?).

L'avantage de la vérification de type explicite est qu'elle peut détecter des erreurs plus tôt et donner des messages d'erreur plus clairs que le typage de canard. Les exigences exactes d'un type de canard ne peuvent être exprimées qu'avec une documentation externe (espérons-le, c'est complet et précis) et les erreurs de types incompatibles peuvent se produire loin de leur origine.

Les indices de type Python sont destinés à offrir un compromis où les types peuvent être spécifiés et vérifiés, mais il n'y a pas de coût supplémentaire pendant l'exécution du code habituel.

le typing package propose des variables de type qui peuvent être utilisées dans les conseils de type pour exprimer les comportements nécessaires sans nécessiter de types particuliers. Par exemple, il comprend des variables telles que Iterable et Callable pour des conseils pour spécifier le besoin de n'importe quel type avec ces comportements.

Tandis que les astuces de type sont la façon la plus pythonique de vérifier les types, il est souvent encore plus Pythonic de ne pas vérifier les types du tout et de compter sur le typage du canard. Les conseils de type sont relativement nouveaux et le jury est toujours sur quand ils sont la solution la plus Pythonic. Une comparaison relativement non controversée mais très générale: Les astuces de type fournissent une forme de documentation qui peut être appliquée, permettent au code de générer des erreurs plus tôt et plus faciles à comprendre, peuvent intercepter des erreurs que le typage du canard ne peut pas et peuvent être vérifiées statiquement. sens mais c'est encore en dehors de l'exécution). D'un autre côté, le typage du canard a longtemps été la méthode Pythonienne, il n'impose pas le surcoût cognitif du typage statique, il est moins verbeux, il accepte tous les types viables et ensuite certains.


17
2018-05-06 16:12



Voici un exemple pourquoi le typage du canard est mauvais sans savoir quand il est dangereux. Par exemple: Voici le code Python (en omettant éventuellement l'indentation correcte), notez que cette La situation est évitable en prenant soin de isinstance et issubclassof fonctions pour s'assurer que lorsque vous avez vraiment besoin d'un canard, vous ne recevez pas une bombe.

class Bomb:
    def __init__(self):
        ""

    def talk(self):
        self.explode()

    def explode(self):
        print "BOOM!, The bomb explodes."

class Duck:
    def __init__(self):
        ""
    def talk(self):
        print "I am a duck, I will not blow up if you ask me to talk."    

class Kid:
    kids_duck = None

    def __init__(self):
        print "Kid comes around a corner and asks you for money so he could buy a duck."

    def takeDuck(self, duck):
        self.kids_duck = duck
        print "The kid accepts the duck, and happily skips along"

    def doYourThing(self):
        print "The kid tries to get the duck to talk"
        self.kids_duck.talk()

myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()

12
2018-01-25 23:54



isinstance(o, str)

Lien vers les documents


10
2017-09-30 11:01



Je pense que la chose cool à propos de l'utilisation d'un langage dynamique comme Python est que vous ne devriez vraiment pas avoir à vérifier quelque chose comme ça.

Je voudrais simplement appeler les méthodes nécessaires sur votre objet et attraper un AttributeError. Plus tard, cela vous permettra d'appeler vos méthodes avec d'autres objets (apparemment sans rapport) pour accomplir différentes tâches, comme se moquer d'un objet pour le tester.

Je l'ai beaucoup utilisé lors de l'obtention de données sur le web avec urllib2.urlopen() qui renvoie un fichier comme objet. Cela peut à son tour être transmis à presque n'importe quelle méthode qui lit à partir d'un fichier, car il implémente la même read() méthode comme un vrai fichier.

Mais je suis sûr qu'il y a un temps et un endroit pour utiliser isinstance(), sinon ça ne serait probablement pas là :)


5
2017-09-30 13:33