# [Tutor] <var:data> value changes

Bob Gailer bgailer at alum.rpi.edu
Thu May 13 10:43:05 EDT 2004

```At 08:04 AM 5/13/2004, denis wrote:
>Hello,
>
>Some comments and corrections about the previous message (thanks to Magnus &
>Danny) pointed Python's feature called interning: the first aspect of this
>feature is that integers in range(-5,100) (I didn't know about negative
>ones) are generated and stored as data by python; the second is that they
>won't
>be duplicated, but used 'in place' instead, each time the value is needed:
>
> >>> x=1; y=1 ; x is y
>True
> >>> x = -1; y = -1 ; x is y
>True
>
>This means that x and y are at the same memory location, in other words 'x'
>and 'y' are aliases:
>
> >>> id(x); id(y)
>7678960
>7678960
>
>Now, let's (try and) check this does not with out-of-range (sic!) values:
>
> >>> x=100; y=100 ; x is y
>True
> >>> x=1000; y=1000 ; x is y
>True
>
>What's up ? (I've really been surprised!) A more careful trial:
>
> >>> x=1000
> >>> y=1000
> >>> x is y
>False

Put these lines in a module and run it Output is True:
x=1000
y=1000
print x is y

> >>> x=100
> >>> y=100
> >>> x is y
>False
> >>> x=99
> >>> y=99
> >>> x is y
>True
>
>This difference of result shows that two 'equivalent' syntactic forms aren't
>processed the same way. I guess that, on optimisation ground, a short-term
>interning is done for multi-assignment lines (what about "x,y = a,a"?). How
>long does it last ? Is it further available ?
>
> >>> x=100; y=100 ; x is y
>True
> >>> z=100 ; x is z; y is z
>False
>False
>
>
> >>> x='a'
> >>> y='a'
> >>> x is y
>True
> >>> x='1'
> >>> y='1'
> >>> x is y
>True
> >>> x='Freude, schöner Götterfunken,..."
>SyntaxError: EOL while scanning single-quoted string    # ¤\$%#~!!!
> >>> x='Freude, schöner Götterfunken,...'
> >>> y='Freude, schöner Götterfunken,...'
> >>> x is y
>False
> >>> x='Freude, schöner Götterfunken,...'; y='Freude, schöner
>Götterfunken,...' ; x is y  # this was one single line in IDLE
>True
>
>As expected, basic interning is available for small strings (what are the
>criteria?); and the short-term interning form works too.
>
> >>> x=('a')
> >>> y=('a')
> >>> x is y
>True
>
> >>> x=['a']
> >>> y=['a']
> >>> x is y
>False
> >>> x=['a']; y=['a'] ; x is y
>False
> >>> x=[]; y=[] ; x is y
>False
> >>> x=[True]; y=[True] ; x is y
>False
>
>Very probable conclusion : yes for immutables, no for mutables. It doesn't
>even work for empty lists or built-in constants.
>
>
>
>Now, I really want to explore this difference deeper. First, let's enlarge x
>a bit:
>
> >>> x+=[False]
> >>> x
>[True, False]
> >>> x+='a'
> >>> x
>[True, False, 'a']
> >>> a='ciao!'
> >>> x+=[a]
> >>> x
>[True, False, 'a', 'ciao!']
> >>> x+=1
>
>Traceback (most recent call last):
>   File "<pyshell#69>", line 1, in -toplevel-
>     x+=1
>TypeError: argument to += must be iterable
>
>I typed the last line just for fun, but I am surprised that python accepts
>x+='a', as
>'a' is no list, and refuses x+=1 (?). I would expect to be obliged to write
>x.append(item) for both strings and numbers, as both are immutable --but
>strings are sequences (what about tuples?). And with a dictionary ?
>
> >>> d={}
> >>> x+=d
> >>> x
>[True, False, 'a', 'ciao!']    # no success ;-(
> >>> x+=[d]
> >>> x
>[True, False, 'a', 'ciao!', {}]    # :-)
> >>> d={1:'un', 2:'deux'}
> >>> x+=d
> >>> x
>[True, False, 'a', 'ciao!', {}, 1, 2]    # the keys, only!
> >>> x+= [d]
> >>> x
>[True, False, 'a', 'ciao!', {}, 1, 2, {1: 'un', 2: 'deux'}]
>
>Well, interesting, isn't it? You can, as a choice, append to a list either a
>dictionary's keys or its key:value pairs, both without even explicitely
>calling the append() method.
>
> >>> id(x)
>10763120
> >>> for i in range(len(x)):
>         print id(x[i])        # items' addresses
>504028992
>504028976
>6759872
>10763168
>10790352
>7678960
>7677952
>10639664
> >>> id(1);id(2)
>7678960
>7677952    # right!
> >>> id(d)
>10639664     # right again!
>
>True and False are rather close, but not aside; 1 and 2 are strangely far
>(?). All items are separated from the list, they're not "in" the list. Which
>means, as expected, that the list holds its elements' addresses -- only its
>
> >>> id(d)
>10639664
> >>> for i in range(len(d)):
>         print id(d.keys()[i])    # keys' addresses
>7678960
>7677952
> >>> for i in range(len(d)):
>         print id(d[d.keys()[i]])    # values' ones
>10763872
>10762944
>
>It also clear that for a dictionary the dict. itself, its keys and its
>values are totally separated.
>Just as a recall about value changes by immutable types:
>
> >>> t='Freude, schöner Götterfunken,...' ; id(t)
>6742216
> >>> t='Ô joie, divine étincelle de beauté...' ; id(t)
>10781656
>
>The (whole) variable's address changes. What happens when I change x, now?
>There are two kinds of changes:
>
> >>> id(x); id(x[3])
>10763120
>10763168
>
> >>> x[3]='olà!'    # first --I mean zeroth: partial change
> >>> id(x); id(x[3])
>10763120
>10764064
>
> >>> x=[1,'a',d]    # first: global change
>
> >>> id(x)
>10763216
>
>By immutable types, only the item(s) changed move(s) when they're directly
>[Just as foretaste (?) on this topic...]
>
>denis
>
>
>
>
>
>
>_______________________________________________
>Tutor maillist  -  Tutor at python.org
>http://mail.python.org/mailman/listinfo/tutor

Bob Gailer
bgailer at alum.rpi.edu
303 442 2625 home
720 938 2625 cell

```