pythonic moyen de convertir des variables à la liste
J'ai une fonction dont l'argument d'entrée peut être soit un élément ou une liste d'éléments. Si cet argument est un élément unique alors je l'ai mis dans une liste afin que je puisse effectuer une itération sur l'entrée de manière cohérente.
Actuellement j'ai ceci:
def my_func(input):
if not isinstance(input, list): input = [input]
for e in input:
...
Je travaille avec une API existante, donc je ne peux pas changer les paramètres d'entrée. À l'aide de isinstance() se sent hacky, donc, il y a un bon façon de le faire?
re: bonne. En Python l'habitude terme est "Pythonic'. Il reconnaît qu'il y a de nombreuses façons de faire quelque chose, mais que certains sont plus dans l'esprit de la langue.
OriginalL'auteur hoju | 2009-09-13
Vous devez vous connecter pour publier un commentaire.
J'aime Andrei Vajna la suggestion de
hasattr(var,'__iter__')
. Remarque ces résultats à partir de quelques exemples de types de Python:Cela a l'avantage de traiter une chaîne de caractères comme un non-itératif - les cordes sont dans une zone grise, comme parfois, vous voulez les traiter comme un élément, d'autres fois comme une séquence de caractères.
Noter que dans Python 3 la
str
type ne ont la__iter__
attribut et cela ne fonctionne pas:Mon commentaire sur la réponse de Pierre a la première. Ha! 😛
OriginalL'auteur PaulMcG
Généralement, les cordes (plaine et unicode) sont les seuls iterables que vous souhaitez néanmoins considérer comme des "éléments" -- le
basestring
builtin existe SPÉCIFIQUEMENT pour vous permettre de tester deux types de chaînes de caractères avecisinstance
, il est donc très grotty pour ce cas particulier;-).Donc mon approche suggérée pour le cas le plus général est:
C'est LA façon de traiter CHAQUE objet iterable à l'EXCEPTION des cordes comme une liste directement, des chaînes et des nombres et d'autres non-iterables comme des scalaires (normalisée en un seul élément de la liste).
Je suis explicitement de faire une liste de chaque type d'objet iterable donc vous SAVEZ que vous pouvez effectuer sur TOUS les types de liste de truc de tri, une itération plus d'une fois, l'ajout ou la suppression d'éléments pour faciliter l'itération, etc, le tout sans modifier l'entrée EFFECTIVE de la liste (si la liste en effet, il a été;-). Si vous n'avez besoin que d'une seule plaine
for
boucle alors que la dernière étape est inutile (et en effet, peu utile si par exemple, l'entrée est un énorme fichier ouvert) et je vous suggère un générateur auxiliaire à la place:maintenant à chacun de vos fonctions ayant besoin d'un tel argument de normalisation, il vous suffit d'utiliser:
Vous pouvez utiliser un auxiliaire de normalisation-même dans l'autre cas (où vous avez besoin d'une liste réelle pour d'autres fins malveillantes); en fait, dans ces (rares) cas, il vous suffit de faire:
de sorte que l' (forcément) un peu de poils de normalisation logique est tout en UN seul endroit, juste ce qu'il faut!-)
iter(input)
et en ignorant son résultat n'est pas un gaspillage de ressources? Ne serait pas mieux si vous voulez seulement vérifier l'existence de l'__iter__
attribut?je ne pense pas que c'est cher, peut-être un appel de fonction qui va faire presque la même, ce qui vous suggérer et aussi il ne repose pas sur la vérification de l'attribut de la magie
__iter__
try
/iter(x)
/except
n'est pas particulièrement coûteux. ET,iter(x)
réussit pour un objet w/o__iter__
(e.g un objet w/adapté__getitem__
accepter des touches numériques, mais pas de__iter__
).C'est si utile que je voudrais qu'il faisait partie de la bibliothèque standard.
OriginalL'auteur Alex Martelli
Tout d'abord, il n'existe pas de méthode générale que pourrait dire un "élément unique" à partir de "liste des éléments" puisque, par définition, la liste peut être un élément d'une autre liste.
Je dirais que vous avez besoin pour définir les types de données que vous pourriez avoir, de sorte que vous pourriez avoir:
list
contre quoi que ce soit d'autreisinstance(input, list)
(de sorte que votre exemple est correct)basestring
en Python 2.x,str
en Python 3.x)isinstance(myvar, collections.Sequence) and not isinstance(myvar, str)
int
,str
,MyClass
isinstance(input, (int, str, MyClass))
.
OriginalL'auteur ilya n.
Vous pouvez mettre * avant votre argument, de cette façon vous aurez toujours obtenir un n-uplet:
Mais qui va vous forcer à appeler votre fonction avec des paramètres variables, je ne sais pas si c'est acceptable pour vous.
Ho oui désolé je n'avais pas vu la partie où il dit qu'il travaillait sur une api. de ma faute.
OriginalL'auteur attwad
Vous pouvez le faire directement à l'aide de comparaisons de type
type()
.Cependant, la façon dont vous l'avez permettra tout type dérivé de la
list
type à être passé à travers. Ainsi, la prévention de la les types dérivés accidentellement d'être enveloppé.list
, par exemple, votretype()
base de comparaison permettra de rompre immédiatement.isinstance()
plus proche de ce que l'OP veut.Exactement, j'ai été de donner des solutions, mais mon "toutefois" remarque lui dit que son chemin est encore mieux.
OriginalL'auteur Soviut
Votre approche me semble bon pour moi.
Il est similaire à la façon dont vous utilisez
atom?
en Lisp lorsque vous parcourez les listes et vérification de l'élément en cours pour voir si c'est une liste ou pas, parce que si c'est une liste que vous souhaitez traiter ses éléments, trop.Donc, oui, ne vois rien de mal à cela.
OriginalL'auteur Andrei Vajna II
Qui est un ok de façon à le faire (n'oubliez pas d'inclure des n-uplets).
Cependant, vous pouvez également envisager si l'argument est un __iter__ méthode ou __getitem__ méthode. (notez que les chaînes ont __getitem__ au lieu de __iter__.)
C'est probablement le plus général exigence pour une liste type que la seule vérification du type.
OriginalL'auteur Unknown
Cela semble être un moyen raisonnable de le faire. Vous êtes désireux de tester si l'élément est une liste, et cela permet d'avoir directement. Cela devient encore plus compliqué si vous voulez soutenir d'autres " liste des types de données, trop, par exemple:
ou, plus généralement, de l'abstrait à la question:
mais encore une fois, en résumé, votre méthode est simple et correcte, ce qui semble bon pour moi!
hasattr(a, '__iter__')
pour voir si c'est une "liste" type de données.-1. Iterables n'ont pas nécessairement une len, ils ne sont pas nécessairement fini.
OriginalL'auteur Peter