0

Please consider this code:

>>> point = namedtuple('point', ('x', 'y'))
>>> p1 = point(3,4)
point(x=3, y=4)
>>> id(p1)
2881782633456  # address in memory

>>> p1._replace(x = 78)
point(x=78, y=4)
>>> id(p1)
2881782633456  # same as before. 

Seems like i mutated the namedtuple in-place i.e. it is a mutable object. But it says everywhere that tuples and namedtuples are both immutable objects. I am confused.

Furthermore, if it is an immutable object, why does it have a _replace method?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Gsbansal10
  • 303
  • 5
  • 12
  • 4
    You didn't even check to see if you'd mutated `p1`. This is the same behavior you'd see with, say, `str.replace`, which also doesn't mutate anything. – user2357112 Jan 06 '19 at 09:11
  • 2
    Methods that mutate the object in-place return `None` by convention; the fact that you see a `point` returned from the method call should suggest that a new object has been created. – jonrsharpe Jan 06 '19 at 09:22

3 Answers3

4

Tuple is definitely immutable. If you print the p1, its same even after _replace function.

>>> point = namedtuple('point', ('x', 'y'))
>>> p1 = point(3,4)
>>> p1
point(x=3, y=4)   #same before _replace
>>> p1._replace(x = 78)
point(x=78, y=4)
>>> p1
point(x=3, y=4)  #same after _replace

why do you have _replace then? It aims to return a new instance of the named tuple replacing specified fields with new values. It does not mutate the actual tuple itself. The operation is short lived.

U13-Forward
  • 69,221
  • 14
  • 89
  • 114
Jim Todd
  • 1,488
  • 1
  • 11
  • 15
1

Because you didn't assign it back, so replace this line:

p1._replace(x = 78)

With:

pi = p1._replace(x = 78)

For it to be different.

U13-Forward
  • 69,221
  • 14
  • 89
  • 114
1

The _replace method creates a new namedtuple, it doesn't mutate the original, so immutability is preserved.

From the docs:

Return a new instance of the named tuple replacing specified fields with new values

snakecharmerb
  • 47,570
  • 11
  • 100
  • 153