Dans Python 3 je peux faire ce qui suit (voir aussi PEP3132 on Extended Iterable Unpacking):
a, *b = (1, 2, 3)
# a = 1; b = (2, 3)
Que puis-je faire pour obtenir la même élégance similaire dans Python 2.x?
Je sais que je pourrais utiliser des opérations d'accès et de découpage d'un seul élément, mais je me demande s'il y a une manière plus Pythonique . Mon code jusqu'à présent:
a, b = (1, 2, 3)[0], (1, 2, 3)[1:]
# a = 1; b = (2, 3)
J'ai découvert que le PEP3132 donne quelques exemples pour Python 2.x également:
De nombreux algorithmes nécessitent de diviser une séquence en une paire "premier repos":
first, rest = seq[0], seq[1:]
[...]
De plus, si la valeur de droite n'est pas une liste, mais un itérable, elle doit être convertie en liste avant de pouvoir effectuer un découpage; pour éviter de créer cette liste temporaire, il faut recourir à
it = iter(seq) first = it.next() rest = list(it)
Autres approches données dans les réponses à cette question:
Approche de décompression de la liste des arguments de fonction
nécessite une définition/appel de fonction supplémentaire:
def unpack(first, *rest):
return first, rest
first, rest = unpack( *seq )
Je me demande pourquoi il est implémenté dans les listes d'arguments de la fonction de déballage, mais pas pour le déballage normal des tuples.
Approche par générateur
Crédits . Nécessite également une implémentation de fonction personnalisée. Est un peu plus flexible concernant le nombre de variables d'abord.
def unpack_nfirst(seq, nfirst):
it = iter(seq)
for x in xrange(nfirst):
yield next(it, None)
yield Tuple(it)
first, rest = unpack_nfirst(seq, 1)
Les plus pythoniques seraient probablement ceux mentionnés dans le PEP ci-dessus, je suppose?
J'ai cette petite fonction pratique:
def just(n, seq):
it = iter(seq)
for _ in range(n - 1):
yield next(it, None)
yield Tuple(it)
Par exemple:
a, b, c = just(3, range(5))
print a, b, c
## 0 1 (2, 3, 4)
fonctionne également avec moins d'arguments:
a, b, c = just(3, ['X', 'Y'])
print a, b, c
## X Y ()
En réponse au commentaire, vous pouvez également définir:
def take2(a, *rest): return a, rest
def take3(a, b, *rest): return a, b, rest
def take4(a, b, c, *rest): return a, b, rest
... etc
et utilisez-le comme ceci:
p = (1,2,3)
a, b = take2(*p)
print a, b
## 1 (2, 3)
Je me trompe peut-être mais pour autant que je sache
a, *b = (1, 2, 3)
est juste du sucre syntaxique pour trancher et indexer des tuples. Je le trouve utile mais pas très explicite.
Je ne pense pas qu'il y ait de meilleur moyen que celui que vous avez posté mais voici une alternative en utilisant iter
>>> x = (1,2,3)
>>> i = iter(x)
>>> a,b = next(i), Tuple(i)
>>> a
1
>>> b
(2, 3)
Vous n'êtes pas sûr du contexte, mais qu'en est-il de .pop (0)?
Je vois qu'il y a des tuples dans votre exemple, mais si vous voulez faire le genre de choses que vous faites, les listes seraient plus adaptées, je pense? (À moins qu'il n'y ait une bonne raison pour qu'ils soient immuables, ils ne sont pas donnés dans la question.)
b = [1,2,3]
a = b.pop(0)