Immutable vs Mutable types

前端 未结 16 1659
感情败类
感情败类 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:44

    It would seem to me that you are fighting with the question what mutable/immutable actually means. So here is a simple explenation:

    First we need a foundation to base the explenation on.

    So think of anything that you program as a virtual object, something that is saved in a computers memory as a sequence of binary numbers. (Don't try to imagine this too hard, though.^^) Now in most computer languages you will not work with these binary numbers directly, but rather more you use an interpretation of binary numbers.

    E.g. you do not think about numbers like 0x110, 0xaf0278297319 or similar, but instead you think about numbers like 6 or Strings like "Hello, world". Never the less theses numbers or Strings are an interpretation of a binary number in the computers memory. The same is true for any value of a variable.

    In short: We do not program with actual values but with interpretations of actual binary values.

    Now we do have interpretations that must not be changed for the sake of logic and other "neat stuff" while there are interpretations that may well be changed. For example think of the simulation of a city, in other words a program where there are many virtual objects and some of these are houses. Now may these virtual objects (the houses) be changed and can they still be considered to be the same houses? Well of course they can. Thus they are mutable: They can be changed without becoming a "completely" different object.

    Now think of integers: These also are virtual objects (sequences of binary numbers in a computers memory). So if we change one of them, like incrementing the value six by one, is it still a six? Well of course not. Thus any integer is immutable.

    So: If any change in a virtual object means that it actually becomes another virtual object, then it is called immutable.

    Final remarks:

    (1) Never mix up your real-world experience of mutable and immutable with programming in a certain language:

    Every programming language has a definition of its own on which objects may be muted and which ones may not.

    So while you may now understand the difference in meaning, you still have to learn the actual implementation for each programming language. ... Indeed there might be a purpose of a language where a 6 may be muted to become a 7. Then again this would be quite some crazy or interesting stuff, like simulations of parallel universes.^^

    (2) This explenation is certainly not scientific, it is meant to help you to grasp the difference between mutable and immutable.

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

    In Python, there's a easy way to know:

    Immutable:

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

    Mutable:

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

    And:

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

    So I think built-in function is also immutable in Python.

    But I really don't understand how float works:

    >>> 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
    

    It's so weird.

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

    First of all, whether a class has methods or what it's class structure is has nothing to do with mutability.

    ints and floats are immutable. If I do

    a = 1
    a += 5
    

    It points the name a at a 1 somewhere in memory on the first line. On the second line, it looks up that 1, adds 5, gets 6, then points a at that 6 in memory -- it didn't change the 1 to a 6 in any way. The same logic applies to the following examples, using other immutable types:

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

    For mutable types, I can do thing that actallly change the value where it's stored in memory. With:

    d = [1, 2, 3]
    

    I've created a list of the locations of 1, 2, and 3 in memory. If I then do

    e = d
    

    I just point e to the same list d points at. I can then do:

    e += [4, 5]
    

    And the list that both e and d points at will be updated to also have the locations of 4 and 5 in memory.

    If I go back to an immutable type and do that with a tuple:

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

    Then f still only points to the original tuple -- you've pointed g at an entirely new tuple.

    Now, with your example of

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

    Where you pass

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

    (which is a tuple of tuples) as val, you're getting an error because tuples don't have a .clear() method -- you'd have to pass dict(d) as val for it to work, in which case you'll get an empty SortedKeyDict as a result.

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

    The goal of this answer is to create a single place to find all the good ideas about how to tell if you are dealing with mutating/nonmutating (immutable/mutable), and where possible, what to do about it? There are times when mutation is undesirable and python's behavior in this regard can feel counter-intuitive to coders coming into it from other languages.

    As per a useful post by @mina-gabriel:

    • Books to read that might help: "Data Structures and Algorithms in Python"
    • Excerpt from that book that lists mutable/immutable types: mutable/imutable types image

    Analyzing the above and combining w/ a post by @arrakëën:

    What cannot change unexpectedly?

    • scalars (variable types storing a single value) do not change unexpectedly
      • numeric examples: int(), float(), complex()
    • there are some "mutable sequences":
      • str(), tuple(), frozenset(), bytes()

    What can?

    • list like objects (lists, dictionaries, sets, bytearray())
    • a post on here also says classes and class instances but this may depend on what the class inherits from and/or how its built.

    by "unexpectedly" I mean that programmers from other languages might not expect this behavior (with the exception or Ruby, and maybe a few other "Python like" languages).

    Adding to this discussion:

    This behavior is an advantage when it prevents you from accidentally populating your code with mutliple copies of memory-eating large data structures. But when this is undesirable, how do we get around it?

    With lists, the simple solution is to build a new one like so:

    list2 = list(list1)

    with other structures ... the solution can be trickier. One way is to loop through the elements and add them to a new empty data structure (of the same type).

    functions can mutate the original when you pass in mutable structures. How to tell?

    • There are some tests given on other comments on this thread but then there are comments indicating these tests are not full proof
    • object.function() is a method of the original object but only some of these mutate. If they return nothing, they probably do. One would expect .append() to mutate without testing it given its name. .union() returns the union of set1.union(set2) and does not mutate. When in doubt, the function can be checked for a return value. If return = None, it does not mutate.
    • sorted() might be a workaround in some cases. Since it returns a sorted version of the original, it can allow you to store a non-mutated copy before you start working on the original in other ways. However, this option assumes you don't care about the order of the original elements (if you do, you need to find another way). In contrast .sort() mutates the original (as one might expect).

    Non-standard Approaches (in case helpful): Found this on github published under an MIT license:

    • github repository under: tobgu named: pyrsistent
    • What it is: Python persistent data structure code written to be used in place of core data structures when mutation is undesirable

    For custom classes, @semicolon suggests checking if there is a __hash__ function because mutable objects should generally not have a __hash__() function.

    This is all I have amassed on this topic for now. Other ideas, corrections, etc. are welcome. Thanks.

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