Cette question semble simple, mais je n'arrive pas à la comprendre. Je sais que vous pouvez vérifier les types de données en python, mais comment définir une condition en fonction du type de données? Par exemple, si je dois écrire un code qui trie dans un dictionnaire/une liste et additionne tous les entiers, comment puis-je isoler la recherche pour ne rechercher que des entiers?
Je suppose qu'un exemple rapide ressemblerait à quelque chose comme ceci:
y = []
for x in somelist:
if type(x) == <type 'int'>: ### <--- psuedo-code line
y.append(x)
print sum(int(z) for z in y)
Donc, pour la ligne 3, comment pourrais-je définir une telle condition?
Que diriez-vous,
if isinstance(x, int):
mais une manière plus propre serait tout simplement
sum(z for z in y if isinstance(z, int))
Il y a un très gros "ça dépend" de la vérification de type en Python. Il existe de nombreuses façons de traiter les types, et tous ont leurs avantages et leurs inconvénients. Avec Python3, plusieurs autres ont émergé.
Les types sont des objets de première classe et vous pouvez les traiter comme n'importe quelle autre valeur. Donc, si vous voulez que le type de quelque chose soit égal à int
, testez-le:
if type(x) == int:
C'est le type de test le plus restrictif: il nécessite l'égalité de type exacte. Souvent, ce n'est pas ce que vous voulez:
float
ne serait pas valide, même si elle se comportait comme un int
à plusieurs fins.int
ou enum
serait rejetée, même si elles sont logiquement des entiers. str
ou unicode
, et les entiers peuvent être (soit)int
ou long
.Notez que l'égalité de type explicite a est utilisée pour les opérations de bas niveau:
slice
. Une vérification explicite est bien plus explicite ici.Variantes
Une comparaison peut également être effectuée avec l'attribut __class__
:
if x.__class__ == int:
Remarque Si une classe définit une propriété __class__
, ce n'est pas la même chose que type(x)
.
Lorsque plusieurs classes doivent être vérifiées, l'utilisation d'une dict
pour répartir les actions est plus extensible et peut être plus rapide (types ≥5-10) que les vérifications explicites. Ceci est particulièrement utile pour les conversions et la sérialisation:
dispatch_dict = {float: round, str: int, int: lambda x: x}
def convert(x):
converter = self.dispatch_dict[type(x)] # lookup callable based on type
return converter(x)
Le test de type idiomatique utilise la variable isinstance
builtin :
if isinstance(x, int):
Cette vérification est à la fois exacte et performante. C'est le plus souvent ce que les gens veulent pour vérifier les types:
int
passerait quand même ce test.isinstance(x, (int, long))
vous donne tous les entiers intégrés.Plus important encore, les inconvénients sont la plupart du temps négligeables:
isinstance(x, list)
lorsqu'une séquence (par exemple, Tuple
) ou même un caractère itérable (par exemple, un generator
) conviendrait également. Cela concerne davantage les bibliothèques à usage général que les scripts ou les applications.Variantes
Si vous avez déjà un type, issubclass
se comporte de la même manière:
if issubclass(x_type, int):
Python a un concept de classes de base abstraites . En gros, ils expriment le sens des types, pas leur hiérarchie:
if isinstance(x, numbers.Real): # accept anything you can sum up like a number
En d'autres termes, le type (x) ne fait pas nécessairement hériter de numbers.Real
mais doit se comporter comme ce dernier. C'est quand même un concept très complexe et difficile:
int
la plupart du temps.Cependant, il est incroyablement utile pour les bibliothèques génériques et les abstractions.
dict
vous limite à un type spécifique en mémoire. En revanche, collections.abc.Mapping
inclut également les wrappers de base de données, les grands dictionnaires sauvegardés sur disque, les conteneurs lazy, ... - et dict
.collections.abc.Iterable
, ils fonctionnent tous dans une boucle for
.Bien que cela ne soit généralement pas nécessaire pour les scripts à jeter, je vous recommande fortement de l'utiliser pour tout ce qui vit au-delà de quelques versions de Python.
La manière idiomatique de traiter les types n’est pas de les tester, mais de supposer qu’ils sont compatibles. Si vous attendez déjà des types incorrects dans votre entrée, ignorez tout ce qui n'est pas compatible:
try:
ix = int(x)
except (ValueError, TypeError):
continue # not compatible with int, try the next one
else:
a.append(ix)
Ce n'est pas réellement une vérification de type, mais sert généralement la même intention.
float
à int
.int
.L'inconvénient majeur est qu'il s'agit d'une transformation explicite.
str
contenant un littéral.float
à int
quand vous avez juste besoin de chiffres.La conversion est un outil efficace pour certains cas d'utilisation spécifiques. Cela fonctionne mieux si vous savez approximativement quelle est votre contribution et si vous devez donner des garanties quant à votre production.
La meilleure chose à faire est de vous assurer que vous n'avez jamais à vérifier le type en premier lieu. C'est un peu une méta-sujet, car cela dépend fortement du cas d'utilisation.
Ici, la source de somelist
n'aurait jamais dû y mettre des non-nombres.
permettez-moi de déclarer la variable x de type int
x = 2
if type(x) == type(1) or isinstance(x, int):
# do something
Les deux fonctionnent bien.