Crear una lista de un solo elemento repetido N veces


523

Quiero crear una serie de listas, todas de diferentes longitudes. Cada lista contendrá el mismo elemento e, repetidas nveces (donde n= longitud de la lista).

¿Cómo creo las listas, sin usar una comprensión de lista [e for number in xrange(n)]para cada lista?

Respuestas:


778

También puedes escribir:

[e] * n

Debe tener en cuenta que si e es, por ejemplo, una lista vacía, obtendrá una lista con n referencias a la misma lista, no n listas vacías independientes.

Pruebas de rendimiento

A primera vista parece que repetir es la forma más rápida de crear una lista con n elementos idénticos:

>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819

Pero espera, no es una prueba justa ...

>>> itertools.repeat(0, 10)
repeat(0, 10)  # Not a list!!!

La función en itertools.repeatrealidad no crea la lista, ¡solo crea un objeto que puede usarse para crear una lista si lo desea! Intentemos eso de nuevo, pero convirtiéndolo en una lista:

>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233

Entonces, si quieres una lista, úsala [e] * n. Si desea generar los elementos perezosamente, use repeat.


23
Es muy poco probable que el rendimiento de crear una lista con elementos idénticos sea un componente crítico del rendimiento de un programa de Python.
Arthur

11
Como se mencionó anteriormente, si e es una lista vacía, [[]] * npuede producir resultados inesperados. Para crear sublistas vacías únicas , use para la comprensión:[[] for i in range(0,n)]
Josiah Yoder

149
>>> [5] * 4
[5, 5, 5, 5]

Tenga cuidado cuando el elemento que se repite es una lista. La lista no será clonada: ¡todos los elementos harán referencia a la misma lista!

>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]

80

Crear una lista de elementos individuales repetidos n veces en Python

Artículos inmutables

Para artículos inmutables, como None, bools, ints, floats, strings, tuples o frozensets, puede hacerlo así:

[e] * 4

Tenga en cuenta que esto solo se usa con elementos inmutables (cadenas, tuplas, congelados,) en la lista, porque todos apuntan al mismo elemento en el mismo lugar en la memoria. Utilizo esto con frecuencia cuando tengo que construir una tabla con un esquema de todas las cadenas, para no tener que dar un mapeo uno a uno altamente redundante.

schema = ['string'] * len(columns)

Artículos mutables

He usado Python durante mucho tiempo ahora, y nunca he visto un caso de uso en el que haría lo anterior con una instancia mutable. En su lugar, para obtener, por ejemplo, una lista, conjunto o dict vacío mutable, debe hacer algo como esto:

list_of_lists = [[] for _ in columns]

El guión bajo es simplemente un nombre de variable desechable en este contexto.

Si solo tiene el número, sería:

list_of_lists = [[] for _ in range(4)]

El _no es realmente especial, pero su verificador de estilo de entorno de codificación probablemente se quejará si no tiene la intención de usar la variable y usar cualquier otro nombre.


Advertencias para usar el método inmutable con elementos mutables:

Tenga cuidado al hacer esto con objetos mutables , cuando cambia uno de ellos, todos cambian porque son todos el mismo objeto:

foo = [[]] * 4
foo[0].append('x')

foo ahora regresa:

[['x'], ['x'], ['x'], ['x']]

Pero con objetos inmutables, puede hacer que funcione porque cambia la referencia, no el objeto:

>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]

>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]

Pero nuevamente, los objetos mutables no son buenos para esto, porque las operaciones en el lugar cambian el objeto, no la referencia:

l = [set()] * 4
>>> l[0] |= set('abc')    
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]

26

Itertools tiene una función solo para eso:

import itertools
it = itertools.repeat(e,n)

Por supuesto, itertoolste da un iterador en lugar de una lista. [e] * nle da una lista, pero, dependiendo de lo que haga con esas secuencias, la itertoolsvariante puede ser mucho más eficiente.


13

Como otros han señalado, el uso del operador * para un objeto mutable duplica las referencias, por lo que si cambia una, las cambiará todas. Si desea crear instancias independientes de un objeto mutable, su sintaxis xrange es la forma más pitónica de hacerlo. Si le molesta tener una variable con nombre que nunca se usa, puede usar la variable de subrayado anónimo.

[e for _ in xrange(n)]

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.