web-dev-qa-db-fra.com

Pourquoi Python n'a-t-il pas de fonction "aplatir" pour les listes?

Erlang et Ruby sont tous deux fournis avec des fonctions d'aplatissement des tableaux. Cela semble être un outil si simple et utile à ajouter à un langage. On pourrait le faire:

>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> mess.flatten()
[1, 2, 3, 4, 5, 6]

Ou même:

>>> import itertools
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> list(itertools.flatten(mess))
[1, 2, 3, 4, 5, 6]

Au lieu de cela, en Python, il faut passer par la difficulté d'écrire une fonction pour aplatir des tableaux à partir de zéro. Cela me semble idiot, aplatir des tableaux est une chose si courante. C'est comme avoir à écrire une fonction personnalisée pour concaténer deux tableaux.

J'ai googlé cela sans résultat, alors je demande ici; y a-t-il une raison particulière pour laquelle un langage mature comme Python 3, fourni avec cent mille batteries différentes incluses, ne fournit pas une méthode simple d'aplatissement des tableaux? L'idée d'inclure un tel fonction a été discutée et rejetée à un moment donné?

40
Hubro

Les propositions pour une fonction flatten à ajouter à la bibliothèque standard apparaissent de temps en temps sur les listes de diffusion python-dev et python-ideas . Python répondent généralement par les points suivants:

  1. Un aplatissement à un niveau (transformer un itérable d'itérables en un seul itérable) est une expression triviale à une ligne (x for y in z for x in y) Et en tout cas est déjà dans la bibliothèque standard sous le nom itertools.chain.from_iterable .

  2. Quels sont les cas d'utilisation d'un aplatissement multi-niveaux à usage général? Est-ce vraiment assez convaincant pour que la fonction soit ajoutée à la bibliothèque standard?

  3. Comment un aplatissement universel à plusieurs niveaux déciderait-il quand aplatir et quand partir seul? Vous pourriez penser qu'une règle comme "aplatir tout ce qui prend en charge l'interface itérable" fonctionnerait, mais cela conduirait à une boucle infinie pour flatten('a').

Voir par exemple Raymond Hettinger :

Il a été discuté ad nauseam sur comp.lang.python. Les gens semblent plus apprécier d'écrire leurs propres versions d'aplatir que de trouver des cas d'utilisation légitimes qui n'ont pas déjà de solutions triviales.

Un aplatisseur à usage général a besoin d'un moyen de savoir ce qui est atomique et ce qui peut être subdivisé. De plus, il n'est pas évident de savoir comment l'algorithme doit être étendu pour couvrir les entrées avec des structures de données arborescentes avec des données aux nœuds ainsi que les feuilles (précommande, post-commande, traversée de l'ordre, etc.)

37
Gareth Rees

Il vient avec une telle méthode mais il ne l'appelle pas aplatir. Cela s'appelle " chaîne ". Il retourne un itérateur dont vous auriez alors besoin d'utiliser la fonction list () pour le reconvertir en liste. Si vous ne souhaitez pas utiliser un *, vous pouvez utiliser la deuxième version "from_iterator". Cela fonctionne idem dans Python 3. Il échouera si l'entrée de liste n'est pas une liste de listes.

[[1], [2, 3], [3, 4, 5]] #yes
[1, 2, [5, 6]] #no

Il y avait à un moment donné une méthode flatten dans le module compiler.ast, mais elle a été déconseillée en 2.6 puis supprimée en 3.0. La récursivité de profondeur arbitraire, nécessaire pour les listes imbriquées arbitrairement ne fonctionne pas bien avec la profondeur de récursivité maximale conservatrice de Python. Le raisonnement pour la suppression du compilateur était en grande partie dû au fait qu'il s'agissait d'un mess . Le compilateur a été transformé en ast mais l'aplatissement a été laissé de côté.

Une profondeur arbitraire peut être obtenue avec les tableaux de numpy et l'aplatissement de cette bibliothèque.

8
World Engineer