Quelles sont les différences entre ces deux fragments de code?
En utilisant type()
:
import types
if type(a) is types.DictType:
do_something()
if type(b) in types.StringTypes:
do_something_else()
En utilisant isinstance()
:
if isinstance(a, dict):
do_something()
if isinstance(b, str) or isinstance(b, unicode):
do_something_else()
python
oop
inheritance
types
abbé
la source
la source
str
etunicode
où vous pouvez simplement vérifierbasestring
), vous pouvez utiliser un tuple pour comparer plusieurs types. Pour vérifier sisomething
c'estint
oustr
utiliserisinstance(something, (int, str))
.Réponses:
Pour résumer le contenu d'autres réponses (déjà bonnes!), L'
isinstance
héritage (une instance d'une classe dérivée est également une instance d'une classe de base), tout en vérifiant l'égalité detype
ne pas (il exige l'identité des types et rejette les instances de sous-types, sous-classes AKA).Normalement, en Python, vous voulez que votre code prenne en charge l'héritage, bien sûr (puisque l'héritage est si pratique, il serait mauvais d'arrêter le code utilisant le vôtre de l'utiliser!), Donc
isinstance
c'est moins mauvais que de vérifier l'identité detype
s car il prend en charge de manière transparente héritage.Ce n'est pas
isinstance
est bon , l' esprit vous-ce est juste moins mauvais que de vérifier l' égalité des types. La solution normale, Pythonique, préférée est presque invariablement le "typage du canard": essayez d'utiliser l'argument comme s'il était d'un certain type souhaité, faites-le dans une instructiontry
/ enexcept
attrapant toutes les exceptions qui pourraient survenir si l'argument n'était pas en fait de cela type (ou tout autre type imitant bien le canard ;-), et dans laexcept
clause, essayez autre chose (en utilisant l'argument "comme si" c'était d'un autre type).basestring
est , cependant, un cas assez spécial - un type intégré qui existe uniquement pour vous permettre d'utiliserisinstance
(les deuxstr
et launicode
sous - classebasestring
). Les chaînes sont des séquences (vous pouvez les boucler, les indexer, les découper, ...), mais vous voulez généralement les traiter comme des types "scalaires" - il est quelque peu peu pratique (mais un cas d'utilisation assez fréquent) de traiter toutes sortes de chaînes (et peut-être d'autres types scalaires, c'est-à-dire celles sur lesquelles vous ne pouvez pas boucler) d'une manière, tous les conteneurs (listes, ensembles, dict, ...) d'une autre manière, etbasestring
plusisinstance
vous aide à le faire — la structure globale de cette idiome est quelque chose comme:On pourrait dire qu'il
basestring
s'agit d'une classe de base abstraite ("ABC") - elle n'offre aucune fonctionnalité concrète aux sous-classes, mais existe plutôt en tant que "marqueur", principalement pour une utilisation avecisinstance
. Le concept est évidemment en pleine croissance en Python, puisque PEP 3119 , qui en introduit une généralisation, a été accepté et a été implémenté à partir de Python 2.6 et 3.0.Le PEP indique clairement que, si les ABC peuvent souvent remplacer le typage du canard, il n'y a généralement pas de grande pression pour le faire (voir ici ). Les ABC tels qu'implémentés dans les versions récentes de Python offrent cependant des avantages supplémentaires:
isinstance
(etissubclass
) peuvent désormais signifier plus que "[une instance de] une classe dérivée" (en particulier, n'importe quelle classe peut être "enregistrée" avec un ABC afin qu'elle montrer comme une sous-classe, et ses instances comme des instances de l'ABC); et les ABC peuvent également offrir une commodité supplémentaire aux sous-classes réelles de manière très naturelle via les applications de modèle de conception de la méthode de modèle (voir ici et ici [[partie II]] pour en savoir plus sur le TM DP, en général et spécifiquement en Python, indépendant des ABC) .Pour les mécanismes sous-jacents de la prise en charge ABC proposés dans Python 2.6, voir ici ; pour leur version 3.1, très similaire, voir ici . Dans les deux versions, les collections de modules de bibliothèque standard (c'est la version 3.1 - pour la version 2.6 très similaire, voir ici ) offrent plusieurs ABC utiles.
Aux fins de cette réponse, l'élément clé à retenir sur les ABC (au-delà d'un placement sans doute plus naturel pour la fonctionnalité TM DP, par rapport à l'alternative classique Python des classes de mixage telles que UserDict.DictMixin ) est qu'ils font
isinstance
(etissubclass
) beaucoup plus attrayants et omniprésents (dans Python 2.6 et versions ultérieures) qu'auparavant (dans les versions 2.5 et antérieures), et par conséquent, en revanche, la vérification de l'égalité des types est une pratique encore pire dans les versions récentes de Python qu'elle ne l'était déjà.la source
Voici un exemple où
isinstance
réalise quelque chose quitype
ne peut pas:dans ce cas, un objet camion est un véhicule, mais vous obtiendrez ceci:
En d'autres termes, cela
isinstance
vaut également pour les sous-classes.Voir aussi: Comment comparer le type d'un objet en Python?
la source
type
est obsolète, utilisezisinstance
plutôt" au premier coup d'œil. par exemple, ce que je voulais était detype()
vérifier exactement , mais j'ai été induit en erreur pendant une courte période (et j'ai dû déboguer un peu) pour cette raison.type()
et nonisinstance()
. On n'est pas mieux; ils sont pour des choses différentes.Vérification de type avec
permet des instances de sous-classes et de multiples bases possibles:
tandis que la vérification de type avec
prend uniquement en charge le type référencé.
En tant que sidenote,
is
est probablement plus approprié queparce que les classes sont des singletons.
Évitez la vérification de type - utilisez le polymorphisme (typage de canard)
En Python, vous voulez généralement autoriser n'importe quel type pour vos arguments, le traiter comme prévu, et si l'objet ne se comporte pas comme prévu, il générera une erreur appropriée. Ceci est connu sous le nom de polymorphisme, également connu sous le nom de typage de canard.
Si le code ci-dessus fonctionne, nous pouvons supposer que notre argument est un canard. Ainsi, nous pouvons passer dans d'autres choses sont de réels sous-types de canard:
ou qui fonctionnent comme un canard:
et notre code fonctionne toujours.
Cependant, dans certains cas, il est souhaitable d'effectuer une vérification de type explicite. Vous avez peut-être des choses sensées à faire avec différents types d'objets. Par exemple, l'objet Pandas Dataframe peut être construit à partir de dictés ou d' enregistrements. Dans un tel cas, votre code doit savoir quel type d'argument il obtient pour pouvoir le gérer correctement.
Donc, pour répondre à la question:
Différences entre
isinstance()
ettype()
en Python?Permettez-moi de démontrer la différence:
type
Supposons que vous devez garantir un certain comportement si votre fonction obtient un certain type d'argument (un cas d'utilisation courant pour les constructeurs). Si vous vérifiez un type comme celui-ci:
Si nous essayons de transmettre un dict qui est une sous-classe de
dict
(comme nous devrions pouvoir, si nous nous attendons à ce que notre code suive le principe de la substitution de Liskov , que les sous-types puissent être substitués aux types), notre code casse!:soulève une erreur!
isinstance
Mais si nous utilisons
isinstance
, nous pouvons soutenir la substitution Liskov!:Retour
OrderedDict([('foo', 'bar'), ('fizz', 'buzz')])
Classes de base abstraites
En fait, nous pouvons faire encore mieux.
collections
fournit des classes de base abstraites qui appliquent des protocoles minimaux pour différents types. Dans notre cas, si nous n'attendons que leMapping
protocole, nous pouvons faire ce qui suit, et notre code devient encore plus flexible:Réponse au commentaire:
Oui, vous pouvez tester l'égalité des types, mais au lieu de ce qui précède, utilisez les bases multiples pour le flux de contrôle, sauf si vous autorisez spécifiquement ces types uniquement:
La différence, encore une fois, est qu'elle
isinstance
prend en charge les sous-classes qui peuvent être substituées au parent sans autrement casser le programme, une propriété connue sous le nom de substitution Liskov.Encore mieux, cependant, inversez vos dépendances et ne vérifiez pas du tout les types spécifiques.
Conclusion
Donc, comme nous voulons prendre en charge la substitution de sous-classes, dans la plupart des cas, nous voulons éviter la vérification de type avec
type
et préférer la vérification de type avecisinstance
- à moins que vous n'ayez vraiment besoin de connaître la classe précise d'une instance.la source
isinstance(instance, y)
et utilisezfrom v.w.x import y
, et que vous importez cette vérification, mais lorsque vous instanciezinstance
vous utilisez à lafrom x import y
place de la façon dont y a été importé dans votre_module.py, la vérification isinstance échouera, même si c'est la même classe.Ce dernier est préféré, car il gérera correctement les sous-classes. En fait, votre exemple peut être écrit encore plus facilement car
isinstance()
le deuxième paramètre de peut être un tuple:ou, en utilisant la
basestring
classe abstraite:la source
Selon la documentation de python, voici une déclaration:
Il
isinstance()
faut donc préférertype()
.la source
Une différence d'utilisation pratique est la façon dont ils gèrent
booleans
:True
et neFalse
sont que des mots clés qui signifient1
et0
en python. Donc,et
les deux reviennent
True
. Les deux booléens sont une instance d'un entier.type()
, cependant, est plus intelligent:retourne
False
.la source
Pour les vraies différences, nous pouvons le trouver dans
code
, mais je ne trouve pas l'implémentation du comportement par défaut duisinstance()
.Cependant, nous pouvons obtenir le même abc .__ instancecheck__ selon __instancecheck__ .
D'en haut
abc.__instancecheck__
, après avoir utilisé le test ci-dessous:Je reçois cette conclusion, pour
type
:Pour
isinstance
:BTW: mieux vaut ne pas mélanger l'utilisation
relative and absolutely import
, utiliserabsolutely import
depuis project_dir (ajouté parsys.path
)la source