1669 votes

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

Quelle est la meilleure façon de vérifier si un objet donné est d'un type donné ? Pourquoi ne pas 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 ?

9 votes

Eh bien, l'approche canonique en Python est de ne pas vérifier le type du tout (sauf si vous déboguez). En général, vous essayez simplement de l'utiliser comme une chaîne de caractères (par exemple, concaténation avec d'autres chaînes, impression sur la console, etc.) ; si vous pensez que cela peut échouer, utilisez try/except ou hasattr. Ceci dit, la réponse acceptée est la manière canonique de faire ce que vous ne devriez généralement pas faire dans le monde Python. Pour plus d'informations, recherchez "Python duck typing" sur Google ou lisez ce qui suit : voidspace.org.uk/python/articles/duck_typing.shtml stackoverflow.com/questions/610883/

16 votes

Je pense que M. Coombs néglige des exemples comme les classes sérialisables non-JSON. Si l'on fait passer un gros morceau de données par une fonction (dont on ne peut pas influencer le code), on peut vouloir convertir certains morceaux de ces données en, par exemple, un <str> avant de les transmettre. En tout cas, c'est ainsi que I a atterri sur cette page...

3 votes

Il semble que la raison la plus courante de cette demande soit que l'on souhaite faire la distinction entre les chaînes de caractères et les itérables de chaînes de caractères. C'est une question délicate car les chaînes sont itérables de chaînes de caractères -- une chaîne de caractères unique est même une séquence d'elle-même (la dernière fois que j'ai vérifié -- on ne devrait probablement pas s'y fier). Mais quelqu'un aurait-il jamais l'utilité de quelque chose qui ressemble à une chaîne ? Oui . Donc la réponse à la question "Que dois-je faire pour distinguer les chaînes de caractères des autres itérables de chaînes de caractères ?" est bien : "Cela dépend de ce que vous essayez de faire" :-D

1970voto

Fredrik Johansson Points 5247

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

if isinstance(o, str):

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

if type(o) is str:

La méthode suivante fonctionne également, et peut être utile dans certains cas :

if issubclass(type(o), str):

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

Une remarque supplémentaire : dans ce cas, si vous utilisez Python 2, il est préférable d'utiliser :

if isinstance(o, basestring):

car cela permettra également d'attraper les chaînes Unicode ( unicode n'est pas une sous-classe de str ; les deux str y 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 chaînes de caractères ( str ) et les données binaires ( bytes ).

Alternativement, isinstance accepte un tuple de classes. Ceci retournera True si o est une instance de toute sous-classe de l'un des éléments suivants (str, unicode) :

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

32 votes

Str.__subclasses__() ne renvoie que les sous-classes directes de str, et ne fait pas la même chose que issubclass() ou isinstance(). (Pour faire cela, vous devriez appeler récursivement .__subclasses__().

17 votes

C'est une bonne réponse, mais je pense qu'elle devrait vraiment commencer par un avertissement indiquant que vous ne devriez généralement pas faire cela en Python. En l'état, elle semble valider l'hypothèse que c'est une "chose canonique à faire en Python", ce qui n'est pas le cas.

5 votes

Quelle est la différence entre "instance" et "exactement" ? Si type(a) is Object alors n'est-il pas également vrai que isinstance(a, Object) . Toutefois, si type(a) is SubClassOfObject alors type(a) is Object == False pero isinstance(a, Object) == True . N'est-ce pas ?

252voto

Dan Points 18831

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

Puisque Python encourage Dactylographie du canard vous devriez juste try...except pour utiliser les méthodes de l'objet de la manière dont vous voulez les utiliser. Donc si votre fonction cherche un objet fichier inscriptible, no vérifier que c'est une sous-classe de file essayez simplement d'utiliser son .write() méthode !

Bien sûr, parfois ces belles abstractions s'effondrent et isinstance(obj, cls) est ce dont vous avez besoin. Mais utilisez-le avec parcimonie.

89 votes

IMHO, la manière la plus pythique est de faire face à n'importe quel argument qui est donné. Dans mon code, je ne peux souvent pas savoir si je reçois un objet ou un tableau d'objets, et j'utilise le contrôle de type en interne pour convertir un objet unique en une liste à un élément.

15 votes

Plutôt que de simplement essayer d'utiliser sa méthode d'écriture, il y a des moments où vous voulez le faire sans provoquer d'exception. Dans ce cas, vous pourriez faire... if hasattr(ob, "write") and callable(ob.write): Ou sauver un accès à la dictée... func = getattr(ob, "write", None) if callable(func): ...

160 votes

La dactylographie du canard, c'est en utilisant une bibliothèque. Le contrôle de type consiste à écrire une bibliothèque. Ce n'est pas le même domaine de problèmes.

74voto

Herge Points 2326

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

type(o) is str retournera True si et seulement si o est un str. Elle retournera False si o est d'un type qui hérite de str .

8 votes

Bien sûr, cela échouera si l'objet n'est pas une instance de 'str', mais de quelque chose qui ressemble à une chaîne. Comme unicode, mmap, UserString ou tout autre type défini par l'utilisateur. L'approche habituelle en Python est de ne pas faire de vérification de type.

2 votes

C'est très utile. Parce que la différence entre isinstance y type(var) == type('') n'est pas clair.

19voto

Dmitry Points 886

Voici un exemple de la raison pour laquelle la saisie en canard est un mal sans savoir quand elle est dangereuse. Par exemple : Voici le code Python (en omettant éventuellement l'indentation appropriée), notez que cette situation est évitable en prenant soin des fonctions isinstance et issubclassof pour s'assurer que lorsque vous avez vraiment besoin d'un canard, vous n'obtenez 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()

38 votes

Même avec la vérification de type, vous pourriez créer un class EvilDuck(Duck) et remplacez talk(). Ou plus probablement, class ChineseCancerDuck(Duck) avec un méchant effet secondaire qui ne se manifeste que des années plus tard. Vous feriez mieux de surveiller votre enfant (et de tester minutieusement ses jouets).

45 votes

Les bombes ne parlent pas. N'ajoutez pas de méthodes absurdes et cela n'arrivera pas.

7 votes

@Dmitry, c'est la critique courante du Duck Typing : fr.wikipedia.org/wiki/Duck_typing#Critique ... vous dites en gros que toute interface dont la sémantique n'est pas appliquée par le langage est mauvaise. Je crois que c'est plutôt l'approche de Java. L'intérêt du typage en canard de Python est qu'il ne fonctionne que lorsqu'il existe une convention commune sur la signification des interfaces spécifiques. Par exemple, vous pourriez bousiller une grande partie du code Python en surchargeant l'interface __file__ (couramment utilisé pour identifier les objets de type fichier) pour signifier autre chose.

12voto

isinstance(o, str)

Lien vers les documents

7 votes

Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien à titre de référence. Les réponses ne comportant qu'un lien peuvent devenir invalides si la page liée change.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X