web-dev-qa-db-fra.com

Quel est le moyen 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 s'il s'agit d'une str?

1018
Herge

Pour vérifier si o est une instance de str ou une sous-classe de str, utilisez isinstance (ce serait la méthode "canonique"):

if isinstance(o, str):

Pour vérifier si le type de o est exactement str (sous-classes exclues):

if type(o) is str:

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

if issubclass(type(o), str):

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

Encore une remarque: dans ce cas, si vous utilisez Python 2, vous souhaiterez peut-être utiliser:

if isinstance(o, basestring):

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

Sinon, isinstance accepte un tuple de classes. Cela retournera True si x est une instance d'une sous-classe de l'un des éléments suivants (str, unicode):

if isinstance(o, (str, unicode)):
1247
Fredrik Johansson

La méthode most Pythonic pour vérifier le type d'un objet est ... de ne pas le vérifier.

Puisque Python encourage Duck Typing , vous devriez simplement try...except utiliser les méthodes de l’objet de la manière dont vous voulez les utiliser. Donc, si votre fonction recherche un objet fichier en écriture, non vérifiez qu'il s'agit d'une sous-classe de file, essayez simplement d'utiliser sa méthode .write()!

Bien sûr, ces abstractions de Nice tombent parfois en panne et isinstance(obj, cls) est ce dont vous avez besoin. Mais utilisez avec parcimonie.

163
Dan Lenski

isinstance(o, str) retournera true si o est une str ou est d'un type héritant de str.

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

44
Herge

Voici un exemple pour lequel taper sur un canard est diabolique sans savoir quand il est dangereux . fonctions pour vous 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()
17
Dmitry
isinstance(o, str)

Lien vers docs

12

Je pense que l’avantage d’utiliser 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 requises sur votre objet et attraper un AttributeError. Ceci vous permettra plus tard d’appeler vos méthodes avec d’autres objets (apparemment non liés) pour accomplir différentes tâches, telles que le moquage d’un objet à des fins de test.

J'ai beaucoup utilisé cette méthode pour récupérer des données sur le Web avec urllib2.urlopen() qui renvoie un fichier file comme object. Cela peut à son tour être transmis à presque toutes les méthodes qui lisent un fichier, car elles implémentent la même méthode read() en tant que fichier réel.

Mais je suis sûr qu'il y a un lieu et une heure pour utiliser isinstance(), sinon ce ne serait probablement pas là :)

6
Will Harding

Pour Hugo:

Vous voulez probablement dire list plutôt que array, mais cela indique tout le problème de la vérification de type - vous ne voulez pas savoir si l'objet en question est une liste, vous voulez savoir s'il s'agit d'une séquence ou d'un simple objet. Alors essayez de l'utiliser comme une séquence.

Supposons que vous souhaitiez ajouter l'objet à une séquence existante ou que, s'il s'agit d'une séquence d'objets, ajoutez-les tous.

try:
   my_sequence.extend(o)
except TypeError:
  my_sequence.append(o)

Une astuce consiste à travailler avec des chaînes et/ou des séquences de chaînes, ce qui est délicat, car une chaîne est souvent considérée comme un objet unique, mais c’est aussi une séquence de caractères. Pire que cela, car il s'agit en réalité d'une séquence de chaînes d'une seule longueur.

Je choisis généralement de concevoir mon API de manière à ce qu’elle n’accepte qu’une valeur ou une séquence - cela facilite les choses. Il n'est pas difficile de mettre un [ ] autour de votre valeur unique lorsque vous le transmettez au besoin.

(Bien que cela puisse causer des erreurs avec les chaînes, elles ressemblent à des séquences.)

4
Chris Barker

Vous pouvez vérifier le type d'une variable en utilisant __d'un type.

Ex:

>>> a = [1,2,3,4]  
>>> b = 1  
>>> type(a).__name__
'list'
>>> type(a).__== 'list'
True
>>> type(b).__== 'list'
False
>>> type(b).__name__
'int'
0
Yerramsetty Rohit

Pour les validations de type plus complexes, j'aime bien l'approche de validation de typeguard basée sur des annotations d'indication de type python:

from typeguard import check_type
from typing import List

try:
    check_type('mylist', [1, 2], List[int])
except TypeError as e:
    print(e)

Vous pouvez effectuer des validations très complexes de manière très propre et lisible.

check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo) 
0
Granitosaurus