Crear Lista de un Solo Elemento Repetido n Veces en Python


Sé que una comprensión de lista hará esto, pero me preguntaba si hay un aún más corto (y más Pitónico?) enfoque.

Quiero crear una serie de listas, todas de longitud variable. Cada lista contendrá el mismo elemento e, repetido n veces (donde n = longitud de la lista). ¿Cómo puedo crear las listas, sin hacer

[e for number in xrange(n)]

Para cada lista?

Author: sohnryang, 2010-08-11

6 answers

También puedes escribir:

[e] * n

Debe tener en cuenta que si e es, por ejemplo, una lista vacía, obtiene 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 itertools.repeat en realidad no crea la lista, solo crea un objeto que se puede utilizar para crear una lista si lo desea! Vamos a intentarlo de nuevo, pero convirtiendo a una lista:

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

Así que si quieres una lista, usa [e] * n. Si desea generar los elementos perezosamente, utilice repeat.

 526
Author: Mark Byers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-11 14:21:25
>>> [5] * 4
[5, 5, 5, 5]

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

>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]
 107
Author: Jeff O'Neill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-21 14:50:50

Crear una Lista de Ítems Repetidos n Veces en Python

Elementos inmutables

Para elementos inmutables, como Ninguno, cadenas, tuplas o frozensets, puede hacerlo de la siguiente manera:

[e] * 4

Tenga en cuenta que esto es mejor solo se utiliza con elementos inmutables (cadenas, tuplas, frozensets, ) en la lista, porque todos apuntan al mismo elemento en el mismo lugar en la memoria. Uso esto con frecuencia cuando tengo que construir una tabla con un esquema de todas las cadenas, por lo que no tengo para dar un mapeo de uno a uno.

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

Elementos mutables

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

list_of_lists = [[] for _ in columns]

El subrayado es simplemente un nombre de variable desechable en este contexto.

Si solo tienes el número, eso sería: {[16]]}

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

El _ no es realmente especial, pero su comprobador 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 los 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 de nuevo, 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'])]
 45
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 14:20:43

Itertools tiene una función solo para eso:

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

Por supuesto itertools te da un iterador en lugar de una lista. [e] * n te da una lista, pero, dependiendo de lo que hagas con esas secuencias, la variante itertools puede ser mucho más eficiente.

 20
Author: Jochen Ritzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-04 14:14:06

Como otros han señalado, el uso del operador * para un objeto mutable duplica las referencias, por lo que si cambia uno, las cambia 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)]
 10
Author: W.P. McNeill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-27 17:53:32
[e] * n

Debería funcionar

 7
Author: Mad Scientist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-11 14:06:23