Tipos inmutables vs mutables

Estoy confundido sobre lo que es un tipo inmutable. Sé que el float El objeto se considera inmutable, con este tipo de ejemplo de mi libro:

class RoundFloat(float):
    def __new__(cls, val):
        return float.__new__(cls, round(val, 2))

¿Se considera esto inmutable debido a la estructura / jerarquía de clases? float está en la parte superior de la clase y es su propia llamada al método. Similar a este tipo de ejemplo (aunque mi libro dice dict es mutable):

class SortedKeyDict(dict):
    def __new__(cls, val):
        return dict.__new__(cls, val.clear())

Mientras que algo mutable tiene métodos dentro de la clase, con este tipo de ejemplo:

class SortedKeyDict_a(dict):
    def example(self):
        return self.keys()

Además, para el último class(SortedKeyDict_a), si le paso este tipo de conjunto:

d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))

sin llamar al example método, devuelve un diccionario. los SortedKeyDict con __new__ lo marca como un error. Intenté pasar enteros al RoundFloat clase con __new__ y no marcó ningún error.

preguntado el 08 de noviembre de 11 a las 19:11

También puedes echarle un vistazo Enumere la asignación con [:] y python cuando usar copy.copy que también respondí para obtener más información sobre mutabilidad. -

17 Respuestas

¿Qué? ¿Los flotadores son inmutables? Pero no puedo hacer

x = 5.0
x += 7.0
print x # 12.0

¿No es eso "mut" x?

Bueno, estás de acuerdo en que las cadenas son inmutables, ¿verdad? Pero puedes hacer lo mismo.

s = 'foo'
s += 'bar'
print s # foobar

El valor de la variable cambia, pero cambia al cambiar a qué se refiere la variable. Un tipo mutable puede cambiar de esa manera, y puede Además, cambiar "en su lugar".

Aquí está la diferencia.

x = something # immutable type
print x
func(x)
print x # prints the same thing

x = something # mutable type
print x
func(x)
print x # might print something different

x = something # immutable type
y = x
print x
# some statement that operates on y
print x # prints the same thing

x = something # mutable type
y = x
print x
# some statement that operates on y
print x # might print something different

Ejemplos concretos

x = 'foo'
y = x
print x # foo
y += 'bar'
print x # foo

x = [1, 2, 3]
y = x
print x # [1, 2, 3]
y += [3, 2, 1]
print x # [1, 2, 3, 3, 2, 1]

def func(val):
    val += 'bar'

x = 'foo'
print x # foo
func(x)
print x # foo

def func(val):
    val += [3, 2, 1]

x = [1, 2, 3]
print x # [1, 2, 3]
func(x)
print x # [1, 2, 3, 3, 2, 1]

Respondido el 26 de junio de 13 a las 12:06

Lo que explicas significa para mí: las variables mutables se pasan por referencia, las variables inmutables se pasan por valor. Es esto correcto ? - Lorenz Meyer

Casi, pero no exactamente. Técnicamente, todas las variables se pasan por referencia en Python, pero tienen una semántica más como pasar por valor en C.Un contraejemplo de su analogía es si lo hace def f(my_list): my_list = [1, 2, 3]. Con el paso por referencia en C, el valor del argumento podría cambiar llamando a esa función. En Python, esa función no hace nada. def f(my_list): my_list[:] = [1, 2, 3] haría algo. - Morningstar

Los tipos mutables se pueden cambiar en su lugar. Los tipos inmutables no pueden cambiar de lugar. Esa es la forma en que Python ve el mundo. No importa cómo se pasen las variables a las funciones. - chaouche

La diferencia clave entre la semántica de Python y la semántica de paso por referencia de C ++ es que la asignación no es una mutación en Python y está en C ++. (Pero, por supuesto, eso es complicado por el hecho de que la asignación aumentada, como a += b a veces is mutación. Y el hecho de que la asignación a una parte de un objeto más grande a veces significa la mutación de ese objeto más grande, pero nunca la mutación de la parte, por ejemplo, a[0] = b no muta a[0], pero probablemente mute a... Por eso puede ser mejor no intentar poner las cosas en términos de C ++ y, en cambio, describir lo que hace Python en sus propios términos ...) - abarnert

Encontré esta respuesta engañosa porque no usa id (), que es esencial para comprender lo que significa inmutable. - pawel_winzig

Tienes que entender que Python representa todos sus datos como objetos. Algunos de estos objetos, como listas y diccionarios, son mutables, lo que significa que puede cambiar su contenido sin cambiar su identidad. Otros objetos como enteros, flotantes, cadenas y tuplas son objetos que no se pueden cambiar. Una forma fácil de entenderlo es si echa un vistazo a la identificación de un objeto.

A continuación, verá una cadena que es inmutable. No se puede cambiar su contenido. Levantará un TypeError si intenta cambiarlo. Además, si asignamos contenido nuevo, se crea un objeto nuevo en lugar de modificar el contenido.

>>> s = "abc"
>>> id(s)
4702124
>>> s[0] 
'a'
>>> s[0] = "o"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> s = "xyz"
>>> id(s)
4800100
>>> s += "uvw"
>>> id(s)
4800500

Puede hacerlo con una lista y no cambiará la identidad de los objetos.

>>> i = [1,2,3]
>>> id(i)
2146718700
>>> i[0] 
1
>>> i[0] = 7
>>> id(i)
2146718700

Para leer más sobre el modelo de datos de Python, puede echar un vistazo a la referencia del lenguaje Python:

Respondido el 30 de junio de 21 a las 01:06

+1 Para el enlace a los documentos de Python. Sin embargo, me tomó un tiempo hasta que me di cuenta de que hoy necesitas diferenciar entre Python 2 y 3; actualicé la respuesta para enfatizar eso. - Benjamín

Tipo inmutable común:

  1. números: int(), float(), complex()
  2. secuencias inmutables: str(), tuple(), frozenset(), bytes()

Tipo mutable común (casi todo lo demás):

  1. secuencias mutables: list(), bytearray()
  2. tipo de conjunto: set()
  3. tipo de mapeo: dict()
  4. clases, instancias de clase
  5. etc.

Un truco para probar rápidamente si un tipo es mutable o no, es usar id() función incorporada.

Ejemplos, usando un entero,

>>> i = 1
>>> id(i)
***704
>>> i += 1
>>> i
2
>>> id(i)
***736 (different from ***704)

usando en la lista,

>>> a = [1]
>>> id(a)
***416
>>> a.append(2)
>>> a
[1, 2]
>>> id(a)
***416 (same with the above id)

Respondido el 14 de enero de 16 a las 04:01

Bien explicado. Me gustó el concepto de verificación por id(). +1. - Parag Tyagi

En realidad, el uso de id() es engañoso aquí. Un objeto dado siempre tendrá la misma identificación durante su vida, pero diferentes objetos que existen en diferentes momentos pueden tener la misma identificación debido a la recolección de basura. - augurar

En caso de que alguien más esté interesado en obtener más información sobre el comentario de @augurar, aquí hay un hilo relacionado que encontré que podría ser de interés: stackoverflow.com/questions/52096582/how-unique-is-pythons-id - Brian Larsen

En primer lugar, si una clase tiene métodos o cuál es su estructura de clases no tiene nada que ver con la mutabilidad.

ints y floats son inmutable. Si lo hago

a = 1
a += 5

Señala el nombre a en un 1 en algún lugar de la memoria en la primera línea. En la segunda línea, busca que 1, agrega 5consigue 6, luego señala a a eso 6 en la memoria - no lo hizo cambiar los 1 a una 6 de cualquier manera. La misma lógica se aplica a los siguientes ejemplos, utilizando otros inmutable tipos:

b = 'some string'
b += 'some other string'
c = ('some', 'tuple')
c += ('some', 'other', 'tuple')

Para mudable tipos, puedo hacer cosas que realmente cambiar el valor donde está almacenado en la memoria. Con:

d = [1, 2, 3]

He creado una lista de las ubicaciones de 1, 2y 3 en memoria. Si entonces lo hago

e = d

Yo solo señalo e de las personas acusadas injustamente llamadas mismo list d apunta a. Entonces puedo hacer:

e += [4, 5]

Y la lista que ambos e y d Los puntos en se actualizarán para tener también las ubicaciones de 4 y 5 en memoria.

Si vuelvo a un inmutable escriba y haga eso con un tuple:

f = (1, 2, 3)
g = f
g += (4, 5)

Entonces f todavía solo apunta a la original tuple has señalado g un bronceado completamente nuevo tuple.

Ahora, con tu ejemplo de

class SortedKeyDict(dict):
    def __new__(cls, val):
        return dict.__new__(cls, val.clear())

Por donde pasas

d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))

(el cual es un tuple of tuples) como val, recibes un error porque tuples no tengo un .clear() método - tendrías que pasar dict(d) as val para que funcione, en cuyo caso obtendrá un vacío SortedKeyDict como resultado.

respondido 08 nov., 11:23

Esta es una muy buena explicación. Me encantó esta pregunta y muchas (nuevas) perspectivas interesantes para explicarla. - Científico fallido

Diferencia entre objetos mutables e inmutables

Definiciones

Objeto mutable: Objeto que se puede cambiar después de crearlo.
Objeto inmutable: Objeto que no se puede cambiar después de crearlo.

En Python, si cambia el valor del objeto inmutable, creará un nuevo objeto.

Objetos mutables

Estos son los objetos en Python que son de tipo mutable:

  1. list
  2. Dictionary
  3. Set
  4. bytearray
  5. user defined classes

Objetos inmutables

Estos son los objetos en Python que son de tipo inmutable:

  1. int
  2. float
  3. decimal
  4. complex
  5. bool
  6. string
  7. tuple
  8. range
  9. frozenset
  10. bytes

Algunas preguntas sin respuesta

Preguntas: ¿Es la cuerda un tipo inmutable?
Responder: lo es, pero ¿puedes explicar esto? Prueba 1:

a = "Hello"
a +=" World"
print a

Salida

"Hello World"

En el ejemplo anterior, la cadena se creó una vez como "Hola" y luego se cambió a "Hola mundo". Esto implica que la cadena es de tipo mutable. Pero no lo es cuando comprobamos su identidad para ver si es de tipo mutable o no.

a = "Hello"
identity_a = id(a)
a += " World"
new_identity_a = id(a)
if identity_a != new_identity_a:
    print "String is Immutable"

Salida

String is Immutable

Prueba 2:

a = "Hello World"
a[0] = "M"

Salida

TypeError 'str' object does not support item assignment

Preguntas: ¿Tuple es un tipo inmutable?
Responder: , está. Prueba 1:

tuple_a = (1,)
tuple_a[0] = (2,)
print a

Salida

'tuple' object does not support item assignment

Respondido 13 Jul 20, 23:07

En [46]: a = "Hola" En [47]: id (a) Fuera [47]: 140071263880128 En [48]: a = a.replace ("H", "g") En [49]: a Salida [49]: 'gello' Entrada [50]: id (a) Salida [50]: 140071263881040 - Malware de Argus

¿Le importaría probar el problema de asignación de su artículo con mi ejemplo anterior? Malware de Argus

La asignación de elementos no es un problema en tipos inmutables. En su caso, está cambiando la cadena a, pero en la memoria está asignando una nueva variable. La asignación de elementos en mi caso no cambiará la memoria de la variable como en el caso de una lista o un diccionario. si está reemplazando, está creando una nueva variable que no modifica la variable existente - Anand Tripathi

@ArgusMalware en su caso, dos ID son iguales debido a que el primero reciclado por GC, por lo que el segundo reutiliza la memoria. - Cologler

Si llega a Python desde otro idioma (excepto uno que se parece mucho a Python, como Ruby) e insiste en entenderlo en términos de ese otro idioma, aquí es donde la gente generalmente se confunde:

>>> a = 1
>>> a = 2 # I thought int was immutable, but I just changed it?!

En Python, la asignación no es una mutación en Python.

En C ++, si escribe a = 2estas llamando a.operator=(2), que mutará el objeto almacenado en a. (Y si hay fue ningún objeto almacenado en a, Eso es un error.)

En Python a = 2 no hace nada a lo que fue almacenado en a; solo significa que 2 ahora está almacenado en a en lugar de. (Y si hay fue ningún objeto almacenado en a, esta bien.)


En última instancia, esto es parte de una distinción aún más profunda.

Una variable en un lenguaje como C ++ es una ubicación escrita en la memoria. Si a es un int, eso significa que son 4 bytes en algún lugar que el compilador sabe que se supone que debe interpretarse como un int. Entonces, cuando lo hagas a = 2, cambia lo que está almacenado en esos 4 bytes de memoria de 0, 0, 0, 1 a 0, 0, 0, 2. Si hay otra variable int en otro lugar, tiene sus propios 4 bytes.

Una variable en un lenguaje como Python es el nombre de un objeto que tiene vida propia. Hay un objeto para el número 1, y otro objeto para el número 2. Y a no son 4 bytes de memoria que se representan como un int, es solo un nombre que apunta al 1 objeto. No tiene sentido para a = 2 convertir el número 1 en el número 2 (eso le daría a cualquier programador de Python demasiado poder para cambiar el funcionamiento fundamental del universo); lo que hace en cambio es simplemente hacer a Olvida el 1 objeto y apunte al 2 objeto en su lugar.


Entonces, si la asignación no es una mutación, ¿qué is una mutación?

  • Llamar a un método que está documentado para mutar, como a.append(b). (Tenga en cuenta que estos métodos casi siempre regresan None). Los tipos inmutables no tienen tales métodos, los tipos mutables generalmente sí.
  • Asignar a una parte del objeto, como a.spam = b or a[0] = b. Los tipos inmutables no permiten la asignación a atributos o elementos, los tipos mutables suelen permitir uno u otro.
  • A veces, se usa una asignación aumentada, como a += b, a veces no. Los tipos mutables suelen mutar el valor; los tipos inmutables nunca lo hacen, y en su lugar te dan una copia (calculan a + b, luego asigne el resultado a a).

Pero si la asignación no es una mutación, ¿cómo es la asignación a una parte de la mutación del objeto? Ahí es donde se vuelve complicado. a[0] = b no mutar a[0] (de nuevo, a diferencia de C ++), pero mutar a (a diferencia de C ++, excepto indirectamente).

Todo esto es por lo que probablemente sea mejor no para intentar poner la semántica de Python en términos de un lenguaje al que está acostumbrado y, en cambio, aprender la semántica de Python en sus propios términos.

Respondido 13 Abr '15, 14:04

Di un = 'hola'. a [0] = 'f' tendrá 'print a' print out 'fi' (¿Estoy en lo cierto hasta ahora?), así que cuando dices que no muta a [0], sino a, ¿qué significa eso? ? ¿Un [n] también tiene su propio lugar ahora, y cambiar su valor lo apunta a un valor diferente? - Daniel Springer

Si un objeto es mutable o no depende de su tipo. Esto no depende de si tiene o no ciertos métodos, ni de la estructura de la jerarquía de clases.

Los tipos definidos por el usuario (es decir, las clases) son generalmente mutables. Hay algunas excepciones, como las subclases simples de un tipo inmutable. Otros tipos inmutables incluyen algunos tipos integrados como int, float, tuple y str, así como algunas clases de Python implementadas en C.

Una explicación general de el capítulo "Modelo de datos" en la Referencia del lenguaje Python ":

El valor de algunos objetos puede cambiar. Se dice que los objetos cuyo valor puede cambiar son mutables; los objetos cuyo valor es inmutable una vez creados se denominan inmutables.

(El valor de un objeto contenedor inmutable que contiene una referencia a un objeto mutable puede cambiar cuando se cambia el valor de este último; sin embargo, el contenedor aún se considera inmutable, porque la colección de objetos que contiene no se puede cambiar. Por lo tanto, la inmutabilidad no es estrictamente lo mismo que tener un valor inmutable, es más sutil).

La mutabilidad de un objeto está determinada por su tipo; por ejemplo, los números, cadenas y tuplas son inmutables, mientras que los diccionarios y las listas son mutables.

Respondido el 20 de junio de 20 a las 12:06

+1 Sin embargo, tenga en cuenta que solo algunos tipos de extensión (es posible que desee revisar su definición de eso, todos los tipos integrados de Python se implementan en C) son inmutables. Otros (la mayoría, me atrevería a decir) son perfectamente mutables. - usuario395760

@delnan ¿Cómo llamas? "tipos de extensiones" ? - eyquem

@eyquem: utilicé el término "tipos de extensión" incorrectamente en mi respuesta, y delnan se refería a eso. Después de su comentario, revisé mi respuesta y evité usar este término. - taleinat

Un objeto mutable debe tener al menos un método capaz de mutar el objeto. Por ejemplo, el list el objeto tiene el append método, que en realidad mutará el objeto:

>>> a = [1,2,3]
>>> a.append('hello') # `a` has mutated but is still the same object
>>> a
[1, 2, 3, 'hello']

pero la clase float no tiene ningún método para mutar un objeto flotante. Tu puedes hacer:

>>> b = 5.0 
>>> b = b + 0.1
>>> b
5.1

pero el = operando no es un método. Simplemente crea un vínculo entre la variable y lo que esté a su derecha, nada más. Nunca cambia ni crea objetos. Es una declaración de lo que apuntará la variable, desde ahora.

Cuando tu lo hagas b = b + 0.1 los = operando vincula la variable a un nuevo flotante, que se crea con el resultado de 5 + 0.1.

Cuando asigna una variable a un objeto existente, mutable o no, el = operando vincula la variable a ese objeto. Y no pasa nada mas

En cualquier caso, el = solo haz el enlace. No cambia ni crea objetos.

Cuando tu lo hagas a = 1.0,la = operando no es el que crea el flotante, sino el 1.0 parte de la línea. En realidad cuando escribes 1.0 es una taquigrafía para float(1.0) una llamada al constructor que devuelve un objeto flotante. (Esa es la razón por la que si escribe 1.0 y presiona enter, obtienes el "eco" 1.0 impreso a continuación; ese es el valor de retorno de la función constructora que llamaste)

Ahora si b es un flotador y le asignas a = b, ambas variables apuntan al mismo objeto, pero en realidad las variables no pueden comunicarse entre sí, porque el objeto es inmutable, y si lo hace b += 1, ahora b apuntar a un nuevo objeto, y a sigue apuntando al viejo y no puede saber qué b está apuntando a.

pero si c es, digamos, un listy le asignas a = c, ahora a y c puede "comunicar", porque list es mutable, y si lo haces c.append('msg'), luego solo comprobando a recibes el mensaje.

(Por cierto, cada objeto tiene un número de identificación único asociado, que puede obtener con id(x). Entonces puede verificar si un objeto es el mismo o no verificar si su identificación única ha cambiado).

Respondido el 04 de enero de 14 a las 05:01

Una clase es inmutable si cada objeto de esa clase tiene un valor fijo en la instanciación que no puede DESPUÉS ser cambiado

En otra palabra, cambia todo el valor de esa variable. (name) o déjalo solo.

Ejemplo:

my_string = "Hello world" 
my_string[0] = "h"
print my_string 

esperabas que esto funcionara e imprimiera hola mundo pero esto arrojará el siguiente error:

Traceback (most recent call last):
File "test.py", line 4, in <module>
my_string[0] = "h"
TypeError: 'str' object does not support item assignment

El intérprete dice: no puedo cambiar el primer carácter de esta cadena

tendrás que cambiar todo string para que funcione:

my_string = "Hello World" 
my_string = "hello world"
print my_string #hello world

mira esta tabla:

enter image description here

fuente

Respondido 06 Abr '16, 20:04

¿Cómo se pueden modificar los componentes de una cadena de Python de una manera más concisa de lo que mostró anteriormente? - Luke Davis

@LukeDavis que podrías hacer my_string = 'h' + my_string[1:]. Esto generará una nueva cadena llamada my_string, y la my_string original desaparecerá (print id(my_string) para ver esto). Por supuesto, eso no es muy flexible, para el caso más general, podría convertir a lista y viceversa: l = list(my_string) l[0] = 'h' my_string = ''.join(l) - danios

Me parece que estás luchando con la pregunta de qué significa realmente mutable / inmutable. Así que aquí hay una explicación simple:

Primero necesitamos una base en la que basar la explicación.

Así que piense en cualquier cosa que programe como un objeto virtual, algo que se guarda en la memoria de una computadora como una secuencia de números binarios. (Sin embargo, no trate de imaginarse esto demasiado. ^^) Ahora, en la mayoría de los lenguajes informáticos, no trabajará con estos números binarios directamente, sino que utilizará una interpretación de números binarios.

Por ejemplo, no piensa en números como 0x110, 0xaf0278297319 o similares, sino que piensa en números como 6 o cadenas como "Hola, mundo". Sin embargo, estos números o cadenas son una interpretación de un número binario en la memoria de la computadora. Lo mismo es cierto para cualquier valor de una variable.

En breve: We no programa con valores reales pero con interpretaciones de valores binarios reales.

Ahora tenemos interpretaciones que no deben cambiarse por el bien de la lógica y otras "cosas interesantes", mientras que hay interpretaciones que bien pueden cambiarse. Por ejemplo, piense en la simulación de una ciudad, es decir, un programa donde hay muchos objetos virtuales y algunos de ellos son casas. Ahora bien, ¿se pueden cambiar estos objetos virtuales (las casas) y todavía se pueden considerar las mismas casas? Bueno, por supuesto que pueden. Por lo tanto, son mutables: se pueden cambiar sin convertirse en un objeto "completamente" diferente.

Ahora piense en números enteros: estos también son objetos virtuales (secuencias de números binarios en la memoria de una computadora). Entonces, si cambiamos uno de ellos, como incrementar el valor seis por uno, ¿sigue siendo un seis? Bueno, por supuesto que no. Por tanto, cualquier número entero es inmutable.

De modo que: Si cualquier cambio en un objeto virtual significa que en realidad se convierte en otro objeto virtual, entonces se llama inmutable.

Observaciones finales:

(1) Nunca mezcle su experiencia del mundo real de mutable e inmutable con la programación en un determinado lenguaje:

Cada lenguaje de programación tiene una definición propia sobre qué objetos pueden silenciarse y cuáles no.

Entonces, si bien ahora puede comprender la diferencia de significado, aún debe aprender la implementación real para cada lenguaje de programación. ... De hecho, podría haber un propósito de un lenguaje donde un 6 puede ser silenciado para convertirse en un 7. Entonces, nuevamente, esto sería algo bastante loco o interesante, como simulaciones de universos paralelos. ^^

(2) Esta explicación ciertamente no es científica, está destinada a ayudarlo a comprender la diferencia entre mutable e inmutable.

Respondido el 24 de junio de 16 a las 13:06

El objetivo de esta respuesta es crear un lugar único para encontrar todas las buenas ideas sobre cómo saber si se trata de mutantes / no mutantes (inmutables / mutables) y, cuando sea posible, ¿qué hacer al respecto? Hay momentos en los que la mutación no es deseable y el comportamiento de Python en este sentido puede parecer contrario a la intuición para los codificadores que lo utilizan desde otros lenguajes.

Según una publicación útil de @ mina-gabriel:

Analizando lo anterior y combinando con una publicación de @ arrakëën:

¿Qué no puede cambiar inesperadamente?

  • los escalares (tipos de variables que almacenan un solo valor) no cambian inesperadamente
    • ejemplos numéricos: int (), float (), complex ()
  • hay algunas "secuencias mutables":
    • str (), tupla (), frozenset (), bytes ()

¿Qué puede?

  • lista como objetos (listas, diccionarios, conjuntos, bytearray ())
  • una publicación aquí también dice clases e instancias de clase, pero esto puede depender de lo que herede la clase y / o cómo se construya.

por "inesperadamente" me refiero a que los programadores de otros lenguajes podrían no esperar este comportamiento (con la excepción de Ruby, y tal vez algunos otros lenguajes "similares a Python").

Añadiendo a esta discusión:

Este comportamiento es una ventaja cuando le impide completar accidentalmente su código con múltiples copias de grandes estructuras de datos que consumen memoria. Pero cuando esto no es deseable, ¿cómo podemos solucionarlo?

Con las listas, la solución simple es crear una nueva como esta:

lista2 = lista (lista1)

con otras estructuras ... la solución puede ser más complicada. Una forma es recorrer los elementos y agregarlos a una nueva estructura de datos vacía (del mismo tipo).

las funciones pueden mutar el original cuando pasa estructuras mutables. ¿Como decir?

  • Hay algunas pruebas dadas en otros comentarios en este hilo, pero luego hay comentarios que indican que estas pruebas no son pruebas completas.
  • object.function () es un método del objeto original, pero solo algunos de ellos mutan. Si no devuelven nada, probablemente lo hagan. Uno esperaría que .append () mute sin probarlo dado su nombre. .union () devuelve la unión de set1.union (set2) y no muta. En caso de duda, se puede comprobar la función para obtener un valor de retorno. Si return = None, no muta.
  • sorted () podría ser una solución alternativa en algunos casos. Dado que devuelve una versión ordenada del original, puede permitirle almacenar una copia no mutada antes de comenzar a trabajar en el original de otras formas. Sin embargo, esta opción asume que no le importa el orden de los elementos originales (si lo hace, necesita encontrar otra forma). Por el contrario, .sort () muta el original (como era de esperar).

Enfoques no estándar (en caso de que sea útil): Encontré esto en github publicado bajo una licencia del MIT:

  • repositorio de github bajo: tobgu llamado: pyrsistent
  • Qué es: código de estructura de datos persistentes de Python escrito para usarse en lugar de estructuras de datos centrales cuando la mutación no es deseable

Para clases personalizadas, @semicolon sugiere verificar si hay un __hash__ función porque los objetos mutables generalmente no deberían tener una __hash__() función.

Esto es todo lo que he acumulado sobre este tema por ahora. Otras ideas, correcciones, etc. son bienvenidas. Gracias.

respondido 14 mar '17, 17:03

Una forma de pensar en la diferencia:

Las asignaciones a objetos inmutables en Python se pueden considerar como copias profundas, mientras que las asignaciones a objetos mutables son superficiales

Respondido el 04 de enero de 13 a las 14:01

Esto es incorrecto. Todas las asignaciones en Python son por referencia. No hay copia involucrada. - augurar

La respuesta más simple:

Una variable mutable es aquella cuyo valor puede cambiar en su lugar, mientras que en una variable inmutable el cambio de valor no ocurrirá en su lugar. La modificación de una variable inmutable reconstruirá la misma variable.

Ejemplo:

>>>x = 5

Creará un valor 5 referenciado por x

x -> 5

>>>y = x

Esta afirmación hará que y se refiera a 5 de x

x -------------> 5 <----------- y

>>>x = x + y

Como x es un número entero (tipo inmutable) se ha reconstruido.

En la declaración, la expresión en RHS dará como resultado el valor 10 y cuando esto se asigne a LHS (x), x se reconstruirá a 10. Así que ahora

x ---------> 10

y ---------> 5

Respondido 02 Feb 17, 21:02

Mudable significa que puede cambiar / mutar. Inmutable lo contrario.

Algunos tipos de datos de Python son mutables, otros no.

Busquemos cuáles son los tipos que encajan en cada categoría y veamos algunos ejemplos.


Mudable

En Python hay varios tipos mutables:

  • liza

  • dict

  • planificadas

Veamos el siguiente ejemplo para lists.

list = [1, 2, 3, 4, 5]

Si hago lo siguiente para cambiar el primer elemento

list[0] = '!'
#['!', '2', '3', '4', '5']

Funciona bien, ya que las listas son mutables.

Si consideramos esa lista, eso fue cambiado y le asignamos una variable

y = list

Y si cambiamos un elemento de la lista como

list[0] = 'Hello'
#['Hello', '2', '3', '4', '5']

Y si uno imprime y dará

['Hello', '2', '3', '4', '5']

Como ambos list y y se refieren a la misma lista, y la hemos cambiado.


Inmutable

En algunos lenguajes de programación se puede definir una constante como la siguiente

const a = 10

Y si uno llama, daría un error

a = 20

Sin embargo, eso no existe en Python.

En Python, sin embargo, hay varios tipos inmutables:

  • Ninguna

  • bool

  • int

  • flotar

  • str

  • tupla

Veamos el siguiente ejemplo para strings.

Tomando la cuerda a

a = 'abcd'

Podemos obtener el primer elemento con

a[0]
#'a'

Si se intenta asignar un nuevo valor al elemento en la primera posición

a[0] = '!'

Dará un error

El objeto 'str' no admite la asignación de elementos

Cuando uno dice + = a una cadena, como

a += 'e'
#'abcde'

No da error, porque apunta a a una cadena diferente.

Sería lo mismo que el siguiente

a = a + 'f'

Y no cambiar la cuerda.

Algunos pros y contras de ser inmutable

• El espacio en la memoria se conoce desde el principio. No requeriría espacio adicional.

• Por lo general, hace las cosas de manera más eficiente. Encontrar, por ejemplo, el len() de una cadena es mucho más rápido, ya que es parte del objeto cadena.

Respondido el 21 de enero de 21 a las 14:01

No he leído todas las respuestas, pero la respuesta seleccionada no es correcta y creo que el autor tiene la idea de que poder reasignar una variable significa que cualquier tipo de datos es mutable. Ese no es el caso. La mutabilidad tiene que ver con pasar por referencia en lugar de pasar por valor.

Digamos que creaste una lista

a = [1,2]

Si tuvieras que decir:

b = a
b[1] = 3

Aunque reasignó un valor en B, también reasignará el valor en a. Es porque cuando asigna "b = a". Está pasando la "Referencia" al objeto en lugar de una copia del valor. Este no es el caso de cadenas, flotantes, etc. Esto hace que la lista, los diccionarios y similares sean mutables, pero los booleanos, flotantes, etc. inmutables.

Respondido 05 Jul 17, 16:07

En Python, hay una manera fácil de saberlo:

Inmutable:

    >>> s='asd'
    >>> s is 'asd'
    True
    >>> s=None
    >>> s is None
    True
    >>> s=123
    >>> s is 123
    True

Mudable:

>>> s={}
>>> s is {}
False
>>> {} is {}
Flase
>>> s=[1,2]
>>> s is [1,2]
False
>>> s=(1,2)
>>> s is (1,2)
False

Y:

>>> s=abs
>>> s is abs
True

Entonces creo que la función incorporada también es inmutable en Python.

Pero realmente no entiendo cómo funciona el flotador:

>>> s=12.3
>>> s is 12.3
False
>>> 12.3 is 12.3
True
>>> s == 12.3
True
>>> id(12.3)
140241478380112
>>> id(s)
140241478380256
>>> s=12.3
>>> id(s)
140241478380112
>>> id(12.3)
140241478380256
>>> id(12.3)
140241478380256

Es tan raro.

Respondido 03 Jul 16, 20:07

Pero eso claramente no es válido. Porque las tuplas son inmutables. Escribe x = (1, 2) y luego intenta mutar x, no es posible. Una forma que he encontrado para comprobar la mutabilidad es hash, funciona para los objetos incorporados al menos. hash(1) hash('a') hash((1, 2)) hash(True) todo el trabajo, y hash([]) hash({}) hash({1, 2}) no todos funcionan. - punto y coma

@semicolon Para las clases definidas por el usuario, entonces hash() funcionará si el objeto define un __hash__() método, aunque las clases definidas por el usuario son generalmente mutables. - augurar

@augurar Quiero decir que sí, pero nada en Python garantizará nada, porque Python no tiene tipado estático real o garantías formales. Pero el hash El método sigue siendo bastante bueno, porque los objetos mutables generalmente no deberían tener un __hash__() método, ya que convertirlas en claves en un diccionario es peligroso. - punto y coma

@augurar y punto y coma (u otros si lo saben): solución __hash __ () ... ¿el creador de una clase personalizada tiene que agregarla para que esté allí? Si es así, la regla es que, si existe, el objeto debería ser inmutable; si no existe, no podemos decirlo, ya que es posible que el creador simplemente lo haya abandonado. - TMWP

Para objetos inmutables, la asignación crea una nueva copia de valores, por ejemplo.

x=7
y=x
print(x,y)
x=10 # so for immutable objects this creates a new copy so that it doesnot 
#effect the value of y
print(x,y)

Para objetos mutables, la asignación no crea otra copia de valores. Por ejemplo,

x=[1,2,3,4]
print(x)
y=x #for immutable objects assignment doesn't create new copy 
x[2]=5
print(x,y) # both x&y holds the same list

Respondido el 31 de diciembre de 18 a las 04:12

Absolutamente incorrecto. Asignación nunca crea una copia. Por favor lee nedbatchelder.com/text/names.html En el primer caso, x=10 es simplemente otra tarea, mientras x[2] = 5 llama a un método mutador. int objetos simplemente carecen de métodos mutantes, pero la semántica de la asignación de Python no dependen del tipo - juanpa.arrivillaga

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.