una tupla tipos que mutables metodos listas lista inmutables inmutable elementos datos anidadas agregar python list tuples immutability

tupla - python tipos de datos mutables e inmutables



¿Por qué las tuplas contienen elementos mutables? (8)

Si una tupla es inmutable, ¿por qué puede contener elementos mutables?

Aparentemente es una contradicción que cuando un elemento mutable como una lista se modifica, la tupla a la que pertenece se mantiene inmutable.


En primer lugar, la palabra "inmutable" puede significar muchas cosas diferentes para diferentes personas. Me gusta especialmente cómo Eric Lippert clasificó la inmutabilidad en su publicación de blog . Allí, enumera estos tipos de inmutabilidad:

  • Inmutabilidad Realio-trulio
  • Inmutabilidad de escritura única
  • Inmutabilidad de paletas
  • Inmutabilidad superficial vs profunda
  • Fachadas inmutables
  • Inmutabilidad observacional

Estos se pueden combinar de varias maneras para crear aún más tipos de inmutabilidad, y estoy seguro de que existen más. El tipo de inmutabilidad que pareces interesado en la inmutabilidad profunda (también conocida como transitiva), en la que los objetos inmutables solo pueden contener otros objetos inmutables.

El punto clave de esto es que la inmutabilidad profunda es solo una de muchas, muchas clases de inmutabilidad. Puede adoptar el tipo que prefiera, siempre que sepa que su noción de "inmutable" probablemente difiera de la noción de "inmutable" de otra persona.


Esa es una excelente pregunta.

La idea clave es que las tuplas no tienen forma de saber si los objetos dentro de ellas son mutables. Lo único que hace que un objeto sea mutable es tener un método que altere sus datos. En general, no hay forma de detectar esto.

Otra idea es que los contenedores de Python en realidad no contienen nada. En cambio, mantienen referencias a otros objetos. Del mismo modo, las variables de Python no son como variables en los lenguajes compilados; en cambio, los nombres de variables son solo claves en un diccionario de espacios de nombres donde están asociados con un objeto correspondiente. Ned Batchhelder explica esto muy bien en su publicación de blog . De cualquier forma, los objetos solo conocen su conteo de referencia; ellos no saben cuáles son esas referencias (variables, contenedores o las partes internas de Python).

En conjunto, estas dos ideas explican su misterio (por qué una tupla inmutable que "contiene" una lista parece cambiar cuando cambia la lista subyacente). De hecho, la tupla no cambió (todavía tiene las mismas referencias a otros objetos que antes). La tupla no pudo cambiar (porque no tenía métodos de mutación). Cuando la lista cambió, la tupla no fue notificada del cambio (la lista no sabe si se hace referencia a una variable, una tupla u otra lista).

Mientras hablamos sobre el tema, aquí hay algunos otros pensamientos para ayudar a completar su modelo mental de qué son las tuplas, cómo funcionan y su uso previsto:

  1. Las tuplas se caracterizan menos por su inmutabilidad y más por su propósito previsto.
    Las tuplas son la manera en que Python recopila información heterogénea bajo un mismo techo. Por ejemplo, s = (''www.python.org'', 80) reúne una cadena y un número para que el par de host / puerto se pueda pasar como un socket, un objeto compuesto. Visto desde esa perspectiva, es perfectamente razonable tener componentes mutables.

  2. La inmutabilidad va de la mano con otra propiedad, hashability . Pero la capacidad de transferencia no es una propiedad absoluta. Si uno de los componentes de la tupla no es hashable, entonces la tupla general tampoco es apilable. Por ejemplo, t = (''red'', [10, 20, 30]) no es hashable.

El último ejemplo muestra una 2-tupla que contiene una cadena y una lista. La tupla en sí no es mutable (es decir, no tiene ningún método que permita cambiar su contenido). Del mismo modo, la cadena es inmutable porque las cadenas no tienen ningún método de mutación. El objeto de lista tiene métodos de mutación, por lo que se puede cambiar. Esto muestra que la mutabilidad es una propiedad de un tipo de objeto: algunos objetos tienen métodos mutantes y otros no. Esto no cambia solo porque los objetos están anidados.

Recuerda dos cosas Primero, la inmutabilidad no es magia, es simplemente la ausencia de métodos mutantes. En segundo lugar, los objetos no saben a qué variables o contenedores se refieren: solo conocen el recuento de referencias.

Espero, esto fue útil para ti :-)


Eso es porque las tuplas no contienen listas, cadenas o números. Contienen referencias a otros objetos . 1 La imposibilidad de cambiar la secuencia de referencias que contiene una tupla no significa que no pueda mutar los objetos asociados con esas referencias. 2

1. 1
2. 2


No puedes cambiar la id de sus artículos. Por lo tanto, siempre contendrá los mismos elementos.

$ python >>> t = (1, [2, 3]) >>> id(t[1]) 12371368 >>> t[1].append(4) >>> id(t[1]) 12371368


Según tengo entendido, esta pregunta debe reformularse como una pregunta sobre las decisiones de diseño: ¿por qué los diseñadores de Python eligieron crear un tipo de secuencia inmutable que pueda contener objetos mutables?

Para responder a esta pregunta, debemos pensar en el propósito de las tuples : sirven como secuencias rápidas y de propósito general . Con esto en mente, se vuelve bastante obvio por qué las tuplas son inmutables pero pueden contener objetos mutables. Esto es:

  1. Las tuplas son rápidas y eficientes en cuanto a la memoria: las tuplas son más rápidas de crear que las listas porque son inmutables. La inmutabilidad significa que las tuplas se pueden crear como constantes y cargarse como tales, utilizando plegado constante . También significa que son más rápidos y más eficientes en la memoria para crear porque no hay necesidad de sobreasignación, etc. Son un poco slower que las listas de acceso a elementos aleatorios, pero más rápido para desempacar (al menos en mi máquina). Si las tuplas fueran mutables, entonces no serían tan rápidas para propósitos como estos.

  2. Las tuplas son de propósito general : las tuplas deben poder contener cualquier tipo de objeto. Están acostumbrados a (rápidamente) hacer cosas como listas de argumentos de longitud variable (a través del operador * en las definiciones de funciones). Si las tuplas no pudieran contener objetos mutables, serían inútiles para cosas como esta. Python tendría que usar listas, lo que probablemente desaceleraría las cosas, y ciertamente sería menos eficiente con la memoria.

Como ve, para cumplir su propósito, las tuplas deben ser inmutables, pero también deben poder contener objetos mutables. Si los diseñadores de Python querían crear un objeto inmutable que garantizara que todos los objetos que "contiene" también son inmutables, tendrían que crear un tercer tipo de secuencia. La ganancia no vale la complejidad extra.


Una razón es que no hay una forma general en Python para convertir un tipo mutable en uno inmutable (vea el PEP 351 rechazado y la discusión vinculada para saber por qué fue rechazado). Por lo tanto, sería imposible poner varios tipos de objetos en tuplas si tuviera esta restricción, incluyendo casi cualquier objeto creado por el usuario que no sea apilable.

La única razón por la que los diccionarios y los conjuntos tienen esta restricción es que requieren que los objetos sean aptos para el hash, ya que se implementan internamente como tablas hash. Pero tenga en cuenta que, irónicamente, los diccionarios y los conjuntos no son inmutables (o hashable). Las tuplas no usan el hash de un objeto, por lo que su mutabilidad no importa.


Una tupla es inmutable en el sentido de que la tupla en sí misma no puede expandirse o contraerse, no que todos los elementos que contienen son inmutables. De lo contrario, las tuplas son aburridas.


Voy a dar un paso aquí y decir que la parte relevante aquí es que si bien puede cambiar el contenido de una lista, o el estado de un objeto, contenido dentro de una tupla, lo que no puede cambiar es que el objeto o la lista está ahí. Si tuviera algo que dependiera de que la cosa [3] fuera una lista, incluso si está vacía, entonces podría ver que esto es útil.