Déterminer le type d'un objet?
Est-il un moyen simple de déterminer si une variable est une liste, dictionnaire, ou quelque chose d'autre? Je suis un objet qui peut être de type et j'ai besoin d'être en mesure de faire la différence.
- Vous ne devriez pas avoir besoin de "faire la différence". Jamais. Le point de Python (et duck-typing), c'est que vous n'avez jamais besoin de savoir. Votre fonction à partir de laquelle votre "obtention d'un objet en arrière" n'est pas conçu correctement si elle retourne des objets de hasard, incompatible types.
- Même si en général je suis d'accord avec vous, il y a des situations où il est utile de savoir. Dans ce cas particulier, il a une action rapide de piratage que j'ai finalement annulée, donc vous avez raison cette fois. Mais dans certains cas - lors de l'utilisation de la réflexion, par exemple -, il est important de savoir quel type d'objet que vous travaillez avec.
- Vous devez fournir des exemples plus concrets de quand vous pensez que vous avez besoin de connaître le type de données. Généralement, c'est un signe de (un) une mal-fonction définie ou (b) assez pauvres polymorphisme. Il est généralement résolu avec un simple changement de conception.
- Je serais en désaccord avec cela, en étant en mesure de connaître le type, vous pouvez faire face à certaines jolie variante d'entrée et de toujours faire la bonne chose. Il vous permet de contourner les problèmes d'interface inhérents à compter sur pur canard-typage (par exemple, l' .l'écorce() la méthode sur un Arbre signifie quelque chose de complètement différent que sur un Chien.) Par exemple, vous pourriez faire une fonction qui effectue des travaux sur un fichier qui accepte une chaîne de caractères (par exemple, un chemin d'accès), un chemin d'accès d'objet, ou une liste. Tous ont des interfaces différentes, mais le résultat final est le même: faire une opération sur le fichier.
- P: "l' .l'écorce() la méthode sur un Arbre signifie quelque chose de complètement différent que sur un Chien". Si cela est vrai, je trouve cet exemple artificiel. Si votre demande est si désespérément confus que (1) les Chiens et les Arbres sont en train d'apparaître bon gré mal gré à l'intérieur de listes ou de n-uplets, et (2) vous avez sémantiquement surcharge d'une méthode de nom comme ça, puis la vérification de type ne va pas être de beaucoup d'aide. La "chaîne de caractères, le chemin d'accès d'objet ou une liste" exemple est aussi facilement manipulé par de simples
try:
blocs sans avoir recours à la vérification de type. La vérification de Type impose mauvais limites. Il étouffe "ouverte" de l'ouvert-fermé principe. - J'ai espéré qu'il serait évident que c'est un exemple artificiel; néanmoins, il s'agit d'une lacune importante du point de duck-typing, et qui
try
n'aide pas avec. Par exemple, si vous savez qu'un utilisateur pouvait passer dans une chaîne de caractères ou un tableau, les deux index sont-mesure, mais cet indice signifie quelque chose de complètement différent. Tout simplement en s'appuyant sur un try-catch dans ces cas, échoue dans l'inattendu et étrange des façons. Une solution est de faire une méthode séparée, un autre pour ajouter un peu de type de vérification. Personnellement, je préfère le comportement polymorphique sur plusieurs méthodes qui font presque la même chose...mais c'est juste moi 🙂 - P: Ce n'est pas un "grand point d'échec", car il n'a pas vraiment d'importance. "si vous saviez qu'un utilisateur pouvait passer dans une chaîne de caractères ou un tableau," est artificiel. Vous permet de définir une API pour accepter l'un ou l'autre. Ce que l'utilisateur "pourrait passer en" n'a pas d'importance. lorsqu'ils donnent le mauvais, quelque chose de doit finit par le briser. C'est la définition de "mauvais type" -- quelque chose se brise. Ce qui conduit à une exception. Ce qui conduit à une
try:
la détection du mauvais type. La définition de "mauvais type" est-ce une exception doit le faux quelque part. - quid des tests unitaires? Parfois, vous voulez que vos tests pour vérifier qu'une fonction retourne quelque chose du bon type. Un très réel, par exemple, lorsque vous avez de la fabrique de classe.
- Pour un peu artificiel exemple, considérons un sérialiseur/deserializer. Par définition, la conversion entre fournies par l'utilisateur des objets et une représentation sérialisée. Le sérialiseur besoins afin de déterminer le type d'objet que vous avez passé, et vous ne peut pas avoir suffisamment d'informations pour déterminer la désérialisé type sans demander l'exécution (ou à tout le moins, vous pourriez en avoir besoin pour les vérifications d'intercepter des données incorrectes avant qu'il pénètre dans votre système!)
- Un autre scénario possible: la Capture de plusieurs types d'exceptions dans une seule "exception" bloquer, faire un peu de traitement (comme l'ajout d'info pour le message d'erreur), puis soulever l'exception avec le complément d'info. Vous pouvez "à l'Exception de (Ex1, Ex2) comme erreur:" et plus tard, lever de type(tre)(some_better_error_message). En utilisant cette méthode, on peut aussi fourre-tout sur une base type d'exception (par exemple: les demandes.des exceptions.RequestsException comme err) et puis la soulever de nouveau en utilisant le droit de sous-classe (encore une fois: lever de type(tre)(new_message)).
- Une autre raison explicitement découvrir le type d'un objet, c'est que la documentation n'est pas toujours vous dire -- et il est parfois utile de le savoir. Donc pas de contrôle de flux, mais juste pour que vous pouvez désosser les valeurs de retour d'une fonction dans des conditions différentes. Exemple: Python3
subprocess.check_output()
retourne différents types en fonction de launiversal_newlines
paramètre. - double possible de What de la manière canonique pour vérifier le type en python?
- Aussi: Comment faire pour déterminer un Python type de la variable?
Vous devez vous connecter pour publier un commentaire.
Pour obtenir le type d'un objet, vous pouvez utiliser le haut-
type()
fonction. Passage d'un objet comme le seul paramètre permet de retourner le type d'objet de l'objet:Bien sûr, cela fonctionne également pour les types personnalisés:
Noter que
type()
ne retour immédiat type de l'objet, mais ne sera pas en mesure de vous dire sur le type d'héritage.Pour couvrir cela, vous devez utiliser le
isinstance
fonction. Bien sûr, cela fonctionne également pour les types intégrés:isinstance()
est généralement la meilleure façon de s'assurer que le type d'un objet parce qu'il acceptera également les types dérivés. Donc, sauf si vous avez réellement besoin le type de l'objet (pour quelque raison que ce soit), à l'aide deisinstance()
est préféré autype()
.Le deuxième paramètre de
isinstance()
accepte également un tuple de types, de sorte qu'il est possible de vérifier plusieurs types à la fois.isinstance
sera alors retourner la valeur true si l'objet est d'un de ces types:is
au lieu de==
que les types sont des singletonsisinstance
est la forme préférée de toute façon, donc ni==
ouis
doivent être utilisées.type
est la meilleure réponse. Il ya des moments oùisinstance
est la meilleure réponse et il ya des moments où le duck-typing est la meilleure réponse. Il est important de connaître toutes les options afin que vous puissiez choisir ce qui est le plus approprié pour la situation.type(foo) is SomeType
serait mieux queisinstance(foo, SomeType)
.type( param ) in ( list, tuple )
dans le passé, lorsque l'on travaille avec différents types de paramètres, où une approche complètement différente était nécessaire en fonction du type.type(x) is X
surisinstance(x, X)
. Même l'exemple dans votre dernier commentaire est mieux écrit queisinstance(param, (list, tuple))
. PEP 8 explicitement décourage l'utilisation detype(x) is X
.isinstance
pour votre cas d'utilisation en cochant (pour une gamme de types), et avec comme nettoyer une syntaxe, qui a le grand avantage que vous pouvez capturer des sous-classes. quelqu'un à l'aide deOrderedDict
détesterais votre code à l'échec parce qu'il accepte pur dicts.type(x)
estZ
etZ
est un sous-type deY
(ce qui signifie que chaque instance deZ
est aussi une instance deY
mais le type de l'instance n'est pas identique àY
).isinstance()
dans mon projet et a été momentanément trébucher jusqu'à ce que j'ai réalisé queisinstance(True, int)
rendementsTrue
.True
est de typebool
etbool
est un sous-type deint
.'bool' in str(type())
à mon expression Booléenne.collections.namedtuple
:type(name) is str
que des noms d'attributs qui ne sont pas des chaînes de caractères (exactement) n'ont pas de sens, et sont probablement une erreur. Mais pour vérifierint
s qui ne sont pasbool
s, vous voulez faireisinstance(x, int) and not isinstance(x, bool)
, afin de ne pas exclureint
sous-classes, mais d'exclurebool
. Notez quebool
n'est pas subclassable, donctype(x) is not bool
fonctionne de la même façon, mais qui seraient incompatibles.Vous pouvez le faire en utilisant
type()
:Il pourrait être plus Pythonic d'utiliser un
try
...except
bloc. De cette façon, si vous avez une classe qui charlatans comme une liste, ou des charlatans comme un dict, il va se comporter correctement indépendamment de ce type de vraiment est.Pour clarifier, la méthode préférée de "faire la différence" entre les types de variables est avec quelque chose appelé duck-typing: tant que les méthodes (et les types de retour) qu'une variable répond à sont ce que votre sous-routine s'attend, la traiter comme vous l'attendez. Par exemple, si vous avez une classe qui surcharge le support des opérateurs avec
getattr
etsetattr
, mais utilise une drôle de système interne, il serait approprié pour qu'il se comporte comme un dictionnaire si c'est ce qu'elle essaie de les imiter.L'autre problème avec la
type(A) is type(B)
vérification, c'est que siA
est une sous-classe deB
, il évalue àfalse
lorsque, par programmation, vous espérez il seraittrue
. Si un objet est une sous-classe d'une liste, il devrait fonctionner comme une liste: vérification du type tel que présenté dans l'autre réponse de l'en empêcher. (isinstance
va fonctionner, cependant).try
...except
est une bonne solution lorsque vous voulez traiter avec des erreurs, mais pas au moment de décider sur le comportement en fonction de leur type.Sur les instances de l'objet, vous avez également la:
attribut. Voici un exemple de prise de Python 3.3 console
Méfiez-vous qu'en python 3.x et en Nouvelle-classes de Style (aviable éventuellement à partir de la version 2.6 de Python) la classe et le genre ont été fusionnés, ce qui peut parfois mener à des résultats inattendus. Principalement pour cette raison, ma façon préférée de tests types/classes est à la isinstance construit en fonction.
__class__
est OK surtout sur Python 2.x, les seuls objets en Python qui n'ont pas__class__
attribut sont des classes de style autant que je sache. Je ne comprends pas votre Python 3 concernent, en passant, sur cette version, juste à chaque objet a une__class__
attribut qui pointe vers la classe.Déterminer le type d'un objet Python
Déterminer le type d'un objet avec
type
Bien que cela fonctionne, d'éviter le double soulignement des attributs comme
__class__
- ils ne sont pas sémantiquement public, et, peut-être pas dans ce cas, les fonctions internes ont généralement un meilleur comportement.vérification de type
Bien, c'est une autre question, ne pas utiliser de type - utilisation
isinstance
:Ce couvre le cas où votre utilisateur peut être en train de faire quelque chose d'intelligent et raisonnable de le subclassing
str
- selon le principe de Liskov Substitution, vous voulez être en mesure d'utiliser la sous-classe des instances sans casser votre code etisinstance
prend en charge cette.Utiliser Des Abstractions
Encore mieux, vous pouvez regarder pour une Classe de Base Abstraite
collections
ounumbers
:Ou tout Simplement Ne sont pas explicitement de Type case à
Ou, peut-être le meilleur de tous, l'utilisation de canard-typage, et ne sont pas explicitement de type vérifier votre code. Duck-typing prend en charge Liskov Substitution avec plus d'élégance et de moins de verbosité.
Conclusion
type
à réellement obtenir une instance de la classe.isinstance
explicitement vérifier effectivement les sous-classes ou inscrits abstractions.try
/except
au lieu de vérifier de manière explicite.Vous pouvez utiliser
type()
ouisinstance()
.Être averti que vous pouvez tabasser
list
ou tout autre type par l'affectation d'une variable dans la portée actuelle du même nom.Ci-dessus, nous voyons que
dict
obtient réaffecté à une chaîne, donc le test:...échoue.
Pour contourner ce problème et d'utiliser
type()
avec plus de prudence:dict
chaîne échouera également pour beaucoup d'autres codes, commedict([("key1", "value1"), ("key2", "value2")])
. La réponse à ces types de questions est "Alors ne le faites pas". Ne pas l'ombre builtin type de noms et d'attendre que les choses fonctionnent correctement.être prudent en utilisant isinstance
mais le type
Alors que la question est assez vieux, je suis tombé sur ce tout en trouvant une bonne façon moi-même, et je pense qu'il a encore besoin de clarifier, au moins pour Python 2.x (ne cochez pas sur Python 3, mais la question se pose avec les classiques de classes qui sont partis sur cette version, il n'a probablement pas d'importance).
Ici, je vais essayer de répondre le titre de la question: comment puis-je déterminer le type d'un objet arbitraire? D'autres suggestions à propos de l'utilisation ou de la non utilisation isinstance sont très bien dans beaucoup de commentaires et de réponses, mais je ne suis pas répondre à ces préoccupations.
Le principal problème avec les
type()
approche est que il ne fonctionne pas correctement avec l'ancien style des instances:L'exécution de ce fragment de code donnerait:
Qui, je l'affirme, n'est pas ce que la plupart des gens s'attendent à ce.
La
__class__
approche est la plus proche de justesse, mais il ne fonctionnera pas dans un cas crucial: quand le passé-objet est un vieux style classe (pas un exemple!), depuis ces objets absence de ces attributs.C'est le plus petit bout de code, je pense que satisfait à une telle question légitime de façon cohérente:
Comme un de côté pour les réponses précédentes, il est intéressant de mentionner l'existence de
collections.abc
qui contient plusieurs classes de base abstraites (Occ) qui complètent duck-typing.Par exemple, au lieu d'explicitement vérifier si quelque chose est une liste avec:
vous pourriez, si vous êtes seulement intéressé de voir si l'objet vous permet d'obtenir des objets, les utiliser
collections.abc.Séquence
:si vous êtes strictement intéressé par les objets qui permettent d'obtenir, réglage et la suppression d'éléments (j'.e mutable séquences), vous pourriez opter pour
collections.abc.MutableSequence
.Beaucoup d'autres Notions sont définies,
Mapping
pour les objets qui peuvent être utilisées comme des cartes, desIterable
,Callable
, et cetera. Une liste complète de tous ces peut être vu dans la documentation decollections.abc
.Dans de nombreux cas pratiques au lieu d'utiliser
type
ouisinstance
vous pouvez également utiliser@functools.singledispatch
, qui est utilisé pour définir les fonctions génériques (fonction composée de plusieurs fonctions de mise en œuvre de la même opération pour les différents types).En d'autres termes, vous pouvez l'utiliser lorsque vous avez un code comme le suivant:
Voici un petit exemple de comment cela fonctionne:
De plus, nous pouvons utiliser les classes abstraites pour couvrir plusieurs types à la fois:
type()
est une meilleure solution queisinstance()
, en particulier pour lesbooleans
:True
etFalse
sont seulement des mots-clés qui signifie1
et0
en python. Ainsi,et
fois de retour
True
. Les deux booléens sont un exemple d'un nombre entier.type()
, cependant, est plus intelligent:retourne
False
.En général, vous pouvez extraire une chaîne de caractères de l'objet avec le nom de la classe,
et de l'utiliser à des fins de comparaison,