I have a list of namedtuples named Books
and am trying to increase the price
field by 20% which does change the value of Books
. I tried to do:
from collections import namedtuple Book = namedtuple('Book', 'author title genre year price instock') BSI = [ 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 = item.price*1.10 print(item.price)
But I keep getting :
Traceback (most recent call last): print(item.price) AttributeError: 'float' object has no attribute 'price'
I understand that I cannot set the fields in a namedtuple. How do I go about updating price
?
I tried to make it into a function:
def restaurant_change_price(rest, newprice): rest.price = rest._replace(price = rest.price + newprice) return rest.price print(restaurant_change_price(Restaurant("Taillevent", "French", "343-3434", "Escargots", 24.50), 25))
but I get an error with replace saying:
rest.price = rest._replace(price = rest.price + newprice) AttributeError: can't set attribute
Can someone let me know why this is happening?
Please note, named tuples are immutable, so you cannot manipulate them.
@Antimony: pickle handles namedtuple classes just fine; classes defined in a function local namespace not so much.
Moreover, as namedtuple instances do not have per-instance dictionaries, they are lightweight and require no more memory than regular tuples. This makes them faster than dictionaries.
NamedTuple can return the values with keys as OrderedDict type object. To make it OrderedDict, we have to use the _asdict() method.
In Python >= 3.7 you can use dataclass decorator with the new variable annotations feature to produce mutable record types:
from dataclasses import dataclass @dataclass class Book: author: str title: str genre: str year: int price: float instock: int BSI = [ 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.66 New price for 'Harry Potter and the Sorcerer's Stone' book is 5.26
Named tuples are immutable, so you cannot manipulate them.
If you want something mutable, you can use recordtype
.
from recordtype import recordtype Book = 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.
You may also keep using namedtuple
with using the _replace()
method.
from collections import namedtuple Book = 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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With