namedtuple._replace() doesn't work as described in the documentation
Asked Answered
A

5

66

I was having trouble implementing namedtuple._replace(), so I copied the code right off of the documentation:

Point = namedtuple('Point', 'x,y')

p = Point(x=11, y=22)

p._replace(x=33)

print p

and I got:

Point(x=11, y=22)

instead of:

Point(x=33, y=22)

as is shown in the doc.

I'm using Python 2.6 on Windows 7

What's going on?

Arkhangelsk answered 30/1, 2010 at 0:3 Comment(2)
This works the same way as str.replace() does. Both strings and named tuples are immutable, so their replacement methods produce new values while leaving the old value unchanged. The solution to your problem is to save the new result to a variable.Asta
Great question if for no other reason than that everybody wanting to "modify" a namedtuple is going to trip over this at some point.Selfdelusion
S
127

Yes it does, it works exactly as documented.

._replace returns a new namedtuple, it does not modify the original, so you need to write this:

p = p._replace(x=33)

See here: somenamedtuple._replace(kwargs) for more information.

Steelworker answered 30/1, 2010 at 0:7 Comment(1)
Good thing to note from the documentation: I was wary of using an underscore-prefixed method since that's typically done to indicate the method is private. However in this case it's done to avoid conflicts with the namedtuple's fields (which might include something called replace), so this is safe to use. There's an ._asdict() method which works similarly.Ambience
G
21

A tuple is immutable. _replace() returns a new tuple with your modifications:

p = p._replace(x=33)
Gantlet answered 30/1, 2010 at 0:7 Comment(0)
S
13

namedtuple._replace() returns a new tuple; the original is unchanged.

Symonds answered 30/1, 2010 at 0:7 Comment(0)
N
6

It looks to me as if namedtuple is immutable, like its forebear, tuple.

>>> from collections import namedtuple
>>> Point = namedtuple('Point', 'x,y')
>>>
>>> p = Point(x=11, y=22)
>>>
>>> p._replace(x=33)
Point(x=33, y=22)
>>> print(p)
Point(x=11, y=22)
>>> p = p._replace(x=33)
>>> print(p)
Point(x=33, y=22)

NamedTuple._replace returns a new NamedTuple of the same type but with values changed.

Napoleon answered 30/1, 2010 at 0:11 Comment(1)
FWIW, the method name was inspired by str.replace() which has a remarkably similar pattern of use :-) s='the quick brown fox'; s=s.replace('quick', 'slow')Asta
G
1

But YES, you are right: in the 'official' documentation, they forgot to assign the replaced tuple to a variable: https://docs.python.org/3/library/collections.html?highlight=collections#collections.namedtuple

p._replace(x=33)

instead of

p1 = p._replace(x33)
Gondola answered 29/10, 2021 at 13:0 Comment(1)
The official documentation shows that when you run p._replace(x=33) on the interactive Python prompt, it outputs the new tuple to screen. They didn't forget anything, this is perfectly fine interactive use. The next line shows a more complex bit of code where the return value is assigned to something.Crass

© 2022 - 2024 — McMap. All rights reserved.