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
?
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
?
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)):
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__().
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.
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 ?
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.
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.
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): ...
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.
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.
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()
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).
@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.
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.
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
5 votes
Les annotations de type Python existent désormais. Jetez un coup d'œil à mypy