Façon plus élégante de déclarer plusieurs variables en même temps

Pour déclarer plusieurs variables en "même temps", je ferais:

a, b = True, False

Mais si je devais déclarer beaucoup plus de variables, cela devient de moins en moins élégant:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True

Y a-t-il un moyen meilleur / élégant / pratique de le faire?

Merci d'avance!

Modifier:

Cela doit être très basique, mais si j'ai utilisé une liste ou un tuple pour stocker les variables, comment devrais-je m'approcher pour que je sois utile puisque:

aList = [a,b]

N'Est pas valide, il faudrait que je faire:

a, b = True, True

Ou qu'est-ce que je manque?

100
demandé sur alain.janinm 2011-03-31 08:28:09

8 réponses

Comme d'autres l'ont suggéré, il est peu probable que l'utilisation de 10 variables locales différentes avec des valeurs booléennes soit la meilleure façon d'écrire votre routine (surtout si elles ont vraiment des noms à une lettre:)

Selon ce que vous faites, il peut être logique d'utiliser un dictionnaire à la place. Par exemple, si vous souhaitez configurer des valeurs prédéfinies booléennes pour un ensemble d'indicateurs d'une lettre, vous pouvez le faire:

>>> flags = dict.fromkeys(["a", "b", "c"], True)
>>> flags.update(dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Si vous préférez, vous pouvez également le faire avec une seule affectation déclaration:

>>> flags = dict(dict.fromkeys(["a", "b", "c"], True),
...              **dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Le deuxième paramètre de dict n'est pas entièrement conçu pour cela: il est vraiment destiné à vous permettre de remplacer des éléments individuels du dictionnaire en utilisant des arguments de mots clés comme d=False. Le code ci-dessus fait exploser le résultat de l'expression suivant ** dans un ensemble d'arguments de mots clés qui sont passés à la fonction appelée. C'est certainement un moyen fiable de créer des dictionnaires, et les gens semblent au moins accepter cet idiome, mais je soupçonne que certains peuvent le considérer comme Unpythonic. </disclaimer>


Une autre approche, qui est probablement la plus intuitive Si vous utilisez fréquemment Ce modèle, consiste à définir vos données comme une liste de valeurs de drapeau (True, False) mappé aux noms de drapeau (chaînes de caractères simples). Vous transformez ensuite cette définition de données en un dictionnaire inversé qui mappe les noms des indicateurs aux valeurs des indicateurs. Cela peut être fait assez succinctement avec une compréhension de liste imbriquée, Mais voici un très lisible mise en œuvre:

>>> def invert_dict(inverted_dict):
...     elements = inverted_dict.iteritems()
...     for flag_value, flag_names in elements:
...         for flag_name in flag_names:
...             yield flag_name, flag_value
... 
>>> flags = {True: ["a", "b", "c"], False: ["d", "e"]}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

La fonction invert_dict est un générateur de fonction. Il génère, ou rendements ce qui signifie qu'il à plusieurs reprises renvoie les valeurs de - paires clé-valeur. Ces paires clé-valeur sont l'inverse du contenu des deux éléments de la première flags dictionnaire. Ils sont introduits dans le constructeur dict. Dans ce cas, le constructeur dict fonctionne différemment d'en haut car il est alimenté par un itérateur plutôt que par un dictionnaire comme argument.


En S'appuyant sur le commentaire de @Chris Lutz: si vous utilisez vraiment ceci pour les valeurs à caractère unique, vous pouvez réellement faire

>>> flags = {True: 'abc', False: 'de'}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Cela fonctionne parce que les chaînes Python sont itérable, ce qui signifie qu'ils peuvent être déplacés valeur par valeur. Dans le cas d'une chaîne, les valeurs sont les caractères individuels de la chaîne. Donc, quand ils sont interprétés comme itérables, comme dans ce cas où ils sont utilisés dans un for loop, ['a', 'b', 'c'] et 'abc' sont effectivement équivalents. Un autre exemple serait quand ils sont passés à une fonction qui prend un itérable, comme tuple.

Personnellement, je ne le ferais pas parce qu'il ne lit pas intuitivement: quand je vois une chaîne, je m'attends à ce qu'elle soit utilisée comme une seule valeur plutôt que comme une liste. Donc, je regarde la première ligne et je pense " Ok, donc il y a un vrai drapeau et un faux drapeau."Donc, bien que ce soit une possibilité, Je ne pense pas que ce soit la voie à suivre. Sur le à la hausse, cela peut aider à expliquer plus clairement les concepts d'itérables et d'itérateurs.


Définir la fonction invert_dict de telle sorte qu'elle renvoie réellement un dictionnaire n'est pas une mauvaise idée non plus; Je ne l'ai pas fait la plupart du temps parce que cela n'aide pas vraiment à expliquer comment fonctionne la routine.


Apparemment, Python 2.7 a des compréhensions de dictionnaire, ce qui constituerait un moyen extrêmement concis d'implémenter cette fonction. Ceci est laissé comme un exercice au lecteur, puisque je Python 2.7 n'est pas installé:)

Vous pouvez également combiner certaines fonctions du module toujours polyvalent itertools . Comme on dit, Il y a plus d'une façon de le faire. Attends, les pythons ne disent pas ça. Eh bien, c'est vrai de toute façon dans certains cas. Je suppose que Guido nous a donné des compréhensions de dictionnaire de sorte qu'il y aurait une façon évidente de le faire.

40
répondu intuited 2011-03-31 06:38:09
a, b, c, d, e, g, h, i, j = (True,)*9
f = False
184
répondu Shariq 2012-10-24 22:55:21

Utilisez une liste / dictionnaire ou définissez votre propre classe pour encapsuler les éléments que vous définissez, mais si vous avez besoin de toutes ces variables, vous pouvez le faire:

a = b = c = d = e = g = h = i = j = True
f = False
43
répondu yan 2011-03-31 04:31:43

Ceci est une élaboration sur @ Jeff M et mes commentaires.

Quand vous faites ceci:

a, b = c, d

Il fonctionne avec tuple emballage et déballage. Vous pouvez séparer les étapes d'emballage et de déballage:

_ = c, d
a, b = _

La première ligne crée un tuple appelé _, qui dispose de deux éléments, le premier avec la valeur de c et la seconde avec la valeur de d. La deuxième ligne décompresse le tuple _ dans les variables a et b. Cela décompose votre énorme ligne:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True, True, True, True

En deux lignes plus petites:

_ = True, True, True, True, True, False, True, True, True, True
a, b, c, d, e, f, g, h, i, j = _

Il vous donnera exactement le même résultat que la première ligne (y compris la même exception si vous ajoutez des valeurs ou des variables à une partie mais oubliez de mettre à jour l'autre). Cependant, dans ce cas précis, la réponse de yan est peut-être la meilleure.

Si vous avez une liste de valeurs, vous pouvez toujours les décompresser. Vous avez juste à le convertir en un tuple d'abord. Par exemple, ce qui suit affectera une valeur comprise entre 0 et 9 à chaque de a à j, respectivement:

a, b, c, d, e, f, g, h, i, j = tuple(range(10))

EDIT: astuce soignée pour les assigner tous comme true sauf l'élément 5 (variable f):

a, b, c, d, e, f, g, h, i, j = tuple(x != 5 for x in range(10))
8
répondu Chris Lutz 2017-05-23 12:02:53

Quand les gens suggèrent "utiliser une liste ou un tuple ou une autre structure de données", ce qu'ils disent, c'est que, lorsque vous avez beaucoup de valeurs différentes qui vous intéressent, les nommer séparément en tant que variables locales peut ne pas être la meilleure façon de faire les choses.

Au lieu de cela, vous pouvez les rassembler dans une structure de données plus grande qui peut être stockée dans une seule variable locale.

Intuition a montré comment vous pouvez utiliser un dictionnaire pour cela, et Chris Lutz a montré comment utiliser un tuple pour le stockage temporaire avant le déballage en variables séparées, mais une autre option à considérer est d'utiliser collections.namedtuple pour regrouper les valeurs de manière plus permanente.

Donc, vous pourriez faire quelque chose comme:

# Define the attributes of our named tuple
from collections import namedtuple
DataHolder = namedtuple("DataHolder", "a b c d e f g")

# Store our data
data = DataHolder(True, True, True, True, True, False, True)

# Retrieve our data
print(data)
print(data.a, data.f)

Le code réel utiliserait, espérons-le, des noms plus significatifs que "DataHolder" et les lettres de l'alphabet, bien sûr.

5
répondu ncoghlan 2011-03-31 05:17:00

Quel est le problème , en fait ?

Si vous avez vraiment besoin ou envie, 10 un, b, c, d, e, f, g, h, j', j , il n'y aura pas d'autre possibilité, à un moment ou à un autre, d'écrire un et écrire b et écrire c.....

Si les valeurs sont toutes différentes, vous serez obligé d'écrire par exemple

a = 12
b= 'sun'
c = A() #(where A is a class)
d = range(1,102,5)
e = (line in filehandler if line.rstrip())
f = 0,12358
g = True
h = random.choice
i = re.compile('^(!=  ab).+?<span>')
j = [78,89,90,0]

C'est-à-dire la définition de la "variables" individuellement.

, Ou , en utilisant une autre écriture, pas besoin d'utiliser _ :

a,b,c,d,e,f,g,h,i,j =\
12,'sun',A(),range(1,102,5),\
(line for line in filehandler if line.rstrip()),\
0.12358,True,random.choice,\
re.compile('^(!=  ab).+?<span>'),[78,89,90,0]

Ou

a,b,c,d,e,f,g,h,i,j =\
(12,'sun',A(),range(1,102,5),
 (line for line in filehandler if line.rstrip()),
 0.12358,True,random.choice,
 re.compile('^(!=  ab).+?<span>'),[78,89,90,0])

.

Si certains d'entre eux doivent avoir la même valeur, est le problème qu'il est trop long d'écrire

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True 

?

Alors vous pouvez écrire:

a=b=c=d=e=g=h=i=k=j=True
f = False

.

Je ne comprends pas quel est exactement votre problème. Si vous voulez écrire un code, vous êtes obligé d'utiliser les caractères requis par l'écriture des instructions et des définitions. Quoi d'autre ?

Je me demande si votre question n'est pas le signe que vous avez mal compris quelque chose.

Quand on écrit a = 10 , on ne crée pas de variable dans le sens de "morceau de mémoire dont la valeur peut changer". Cette instruction:

  • Soit déclenche la création d'un objet de type integer et la valeur 10, et la fixation d'un nom 'a' avec cet objet dans l'espace de noms courant

  • Ou réattribuer le nom ' a ' dans l'espace de noms à l'objet 10 (parce que ' a ' a été précédemment lié à un autre objet)

Je dis cela parce que je ne vois pas l'utilité de définir 10 identifiants a, b,C... pointant vers faux ou vrai. Si ces valeurs ne changent pas pendant l'exécution, pourquoi 10 identifiants? Et s'ils changent, pourquoi définir les identifiants en premier ?, ils seront créés en cas de besoin s'ils ne sont pas préalablement définis

Votre question me semble bizarre

4
répondu eyquem 2011-03-31 08:24:30

On dirait que vous approchez votre problème de la mauvaise façon de moi.

Réécrire votre code pour utiliser un tuple ou écrire une classe pour stocker toutes les données.

2
répondu richo 2011-03-31 04:35:27

J'aime la meilleure réponse votée; cependant, il a des problèmes avec la liste comme indiqué.

  >> a, b = ([0]*5,)*2
  >> print b
  [0, 0, 0, 0, 0]
  >> a[0] = 1
  >> print b
  [1, 0, 0, 0, 0]

C'est discutée en détails (ici), mais l'essentiel est que a et b sont le même objet a is b retourner True (même pour id(a) == id(b)). Par conséquent, si vous modifiez un index, vous modifiez l'index des a et b, car ils sont liés. Pour résoudre ce problème, vous pouvez faire (source)

>> a, b = ([0]*5 for i in range(2))
>> print b
[0, 0, 0, 0, 0]
>> a[0] = 1
>> print b
[0, 0, 0, 0, 0]

Cela peut ensuite être utilisé comme une variante de la réponse sommet, qui a les résultats intuitifs "souhaités"

>> a, b, c, d, e, g, h, i = (True for i in range(9))
>> f = (False for i in range(1)) #to be pedantic
0
répondu Novice C 2016-09-21 20:30:19