Changing values of a list of namedtuples Changing values of a list of namedtuples python-3.x python-3.x

Changing values of a list of namedtuples


Named tuples are immutable, so you cannot manipulate them.

Right way of doing it:

If you want something mutable, you can use recordtype.

from recordtype import recordtypeBook = recordtype('Book', 'author title genre year price instock')books = [   Book('Suzane Collins','The Hunger Games', 'Fiction', 2008, 6.96, 20),   Book('J.K. Rowling', "Harry Potter and the Sorcerer's Stone", 'Fantasy', 1997, 4.78, 12)]for book in books:    book.price *= 1.1    print(book.price)

PS: You may need to pip install recordtype if you don't have it installed.

Bad way of doing it:

You may also keep using namedtuple with using the _replace() method.

from collections import namedtupleBook = namedtuple('Book', 'author title genre year price instock')books = [   Book('Suzane Collins','The Hunger Games', 'Fiction', 2008, 6.96, 20),   Book('J.K. Rowling', "Harry Potter and the Sorcerer's Stone", 'Fantasy', 1997, 4.78, 12)]for i in range(len(books)):    books[i] = books[i]._replace(price = books[i].price*1.1)    print(books[i].price)


In Python >= 3.7 you can use dataclass decorator with the new variable annotations feature to produce mutable record types:

from dataclasses import dataclass@dataclassclass Book:    author: str    title: str    genre: str    year: int    price: float    instock: intBSI = [    Book("Suzane Collins", "The Hunger Games", "Fiction", 2008, 6.96, 20),    Book(        "J.K. Rowling",        "Harry Potter and the Sorcerer's Stone",        "Fantasy",        1997,        4.78,        12,    ),]for item in BSI:    item.price *= 1.10    print(f"New price for '{item.title}' book is {item.price:,.2f}")

Output:

New price for 'The Hunger Games' book is 7.66New price for 'Harry Potter and the Sorcerer's Stone' book is 5.26


This looks like a task for Python's data analysis library, pandas. It's really, really easy to do this sort of thing:

In [6]: import pandas as pdIn [7]: df = pd.DataFrame(BSI, columns=Book._fields)In [8]: dfOut[8]:            author                                  title    genre  year  \0  Suzane Collins                       The Hunger Games  Fiction  2008   1    J.K. Rowling  Harry Potter and the Sorcerers Stone  Fantasy  1997      price  instock  0   6.96       20  1   4.78       12  In [9]: df['price'] *= 100In [10]: dfOut[10]:            author                                  title    genre  year  \0  Suzane Collins                       The Hunger Games  Fiction  2008   1    J.K. Rowling  Harry Potter and the Sorcerer's Stone  Fantasy  1997      price  instock  0    696       20  1    478       12  

Now isn't that just much, much better than labouring with namedtuples?