Immutable vs Mutable types

前端 未结 16 1684
感情败类
感情败类 2020-11-21 05:51

I\'m confused on what an immutable type is. I know the float object is considered to be immutable, with this type of example from my book:

class         


        
相关标签:
16条回答
  • 2020-11-21 06:26

    Difference between Mutable and Immutable objects

    Definitions

    Mutable object: Object that can be changed after creating it.
    Immutable object: Object that cannot be changed after creating it.

    In python if you change the value of the immutable object it will create a new object.

    Mutable Objects

    Here are the objects in Python that are of mutable type:

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

    Immutable Objects

    Here are the objects in Python that are of immutable type:

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

    Some Unanswered Questions

    Questions: Is string an immutable type?
    Answer: yes it is, but can you explain this: Proof 1:

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

    Output

    "Hello World"
    

    In the above example the string got once created as "Hello" then changed to "Hello World". This implies that the string is of the mutable type. But it is not when we check its identity to see whether it is of a mutable type or not.

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

    Output

    String is Immutable
    

    Proof 2:

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

    Output

    TypeError 'str' object does not support item assignment
    

    Questions: Is Tuple an immutable type?
    Answer: yes, it is. Proof 1:

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

    Output

    'tuple' object does not support item assignment
    
    0 讨论(0)
  • 2020-11-21 06:27

    Common immutable type:

    1. numbers: int(), float(), complex()
    2. immutable sequences: str(), tuple(), frozenset(), bytes()

    Common mutable type (almost everything else):

    1. mutable sequences: list(), bytearray()
    2. set type: set()
    3. mapping type: dict()
    4. classes, class instances
    5. etc.

    One trick to quickly test if a type is mutable or not, is to use id() built-in function.

    Examples, using on integer,

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

    using on list,

    >>> a = [1]
    >>> id(a)
    ***416
    >>> a.append(2)
    >>> a
    [1, 2]
    >>> id(a)
    ***416 (same with the above id)
    
    0 讨论(0)
  • 2020-11-21 06:32

    A mutable object has to have at least a method able to mutate the object. For example, the list object has the append method, which will actually mutate the object:

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

    but the class float has no method to mutate a float object. You can do:

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

    but the = operand is not a method. It just make a bind between the variable and whatever is to the right of it, nothing else. It never changes or creates objects. It is a declaration of what the variable will point to, since now on.

    When you do b = b + 0.1 the = operand binds the variable to a new float, wich is created with te result of 5 + 0.1.

    When you assign a variable to an existent object, mutable or not, the = operand binds the variable to that object. And nothing more happens

    In either case, the = just make the bind. It doesn't change or create objects.

    When you do a = 1.0, the = operand is not wich create the float, but the 1.0 part of the line. Actually when you write 1.0 it is a shorthand for float(1.0) a constructor call returning a float object. (That is the reason why if you type 1.0 and press enter you get the "echo" 1.0 printed below; that is the return value of the constructor function you called)

    Now, if b is a float and you assign a = b, both variables are pointing to the same object, but actually the variables can't comunicate betweem themselves, because the object is inmutable, and if you do b += 1, now b point to a new object, and a is still pointing to the oldone and cannot know what b is pointing to.

    but if c is, let's say, a list, and you assign a = c, now a and c can "comunicate", because list is mutable, and if you do c.append('msg'), then just checking a you get the message.

    (By the way, every object has an unique id number asociated to, wich you can get with id(x). So you can check if an object is the same or not checking if its unique id has changed.)

    0 讨论(0)
  • 2020-11-21 06:34

    One way of thinking of the difference:

    Assignments to immutable objects in python can be thought of as deep copies, whereas assignments to mutable objects are shallow

    0 讨论(0)
  • 2020-11-21 06:35

    If you're coming to Python from another language (except one that's a lot like Python, like Ruby), and insist on understanding it in terms of that other language, here's where people usually get confused:

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

    In Python, assignment is not mutation in Python.

    In C++, if you write a = 2, you're calling a.operator=(2), which will mutate the object stored in a. (And if there was no object stored in a, that's an error.)

    In Python, a = 2 does nothing to whatever was stored in a; it just means that 2 is now stored in a instead. (And if there was no object stored in a, that's fine.)


    Ultimately, this is part of an even deeper distinction.

    A variable in a language like C++ is a typed location in memory. If a is an int, that means it's 4 bytes somewhere that the compiler knows is supposed to be interpreted as an int. So, when you do a = 2, it changes what's stored in those 4 bytes of memory from 0, 0, 0, 1 to 0, 0, 0, 2. If there's another int variable somewhere else, it has its own 4 bytes.

    A variable in a language like Python is a name for an object that has a life of its own. There's an object for the number 1, and another object for the number 2. And a isn't 4 bytes of memory that are represented as an int, it's just a name that points at the 1 object. It doesn't make sense for a = 2 to turn the number 1 into the number 2 (that would give any Python programmer way too much power to change the fundamental workings of the universe); what it does instead is just make a forget the 1 object and point at the 2 object instead.


    So, if assignment isn't a mutation, what is a mutation?

    • Calling a method that's documented to mutate, like a.append(b). (Note that these methods almost always return None). Immutable types do not have any such methods, mutable types usually do.
    • Assigning to a part of the object, like a.spam = b or a[0] = b. Immutable types do not allow assignment to attributes or elements, mutable types usually allow one or the other.
    • Sometimes using augmented assignment, like a += b, sometimes not. Mutable types usually mutate the value; immutable types never do, and give you a copy instead (they calculate a + b, then assign the result to a).

    But if assignment isn't mutation, how is assigning to part of the object mutation? That's where it gets tricky. a[0] = b does not mutate a[0] (again, unlike C++), but it does mutate a (unlike C++, except indirectly).

    All of this is why it's probably better not to try to put Python's semantics in terms of a language you're used to, and instead learn Python's semantics on their own terms.

    0 讨论(0)
  • A class is immutable if each object of that class has a fixed value upon instantiation that cannot SUBSEQUENTLY be changed

    In another word change the entire value of that variable (name) or leave it alone.

    Example:

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

    you expected this to work and print hello world but this will throw the following 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
    

    The interpreter is saying : i can't change the first character of this string

    you will have to change the whole string in order to make it works:

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

    check this table:

    source

    0 讨论(0)
提交回复
热议问题