Tengo una lista de ejemplares nombrados Books
y estoy tratando de boost el campo de price
en un 20%, lo que cambia el valor de los Books
. Intenté hacer:
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('JK 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)
Pero sigo recibiendo:
Traceback (most recent call last): print(item.price) AttributeError: 'float' object has no attribute 'price'
Entiendo que no puedo configurar los campos en una pareja nombrada. ¿Cómo hago para actualizar el price
?
Intenté convertirlo en una función:
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))
pero me sale un error con reemplazar diciendo:
rest.price = rest._replace(price = rest.price + newprice) AttributeError: can't set attribute
¿Alguien puede hacerme saber por qué sucede esto?
Las tuplas nombradas son inmutables , por lo que no puedes manipularlas.
Si quieres algo mutable , puedes usar 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('JK Rowling', "Harry Potter and the Sorcerer's Stone", 'Fantasy', 1997, 4.78, 12)] for book in books: book.price *= 1.1 print(book.price)
PD: Es posible que deba pip install recordtype
si no lo tiene instalado.
También puede seguir usando namedtuple
utilizando el método _replace()
.
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('JK 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)
Esto parece una tarea para la biblioteca de análisis de datos de Python, pandas . Es realmente muy fácil hacer este tipo de cosas:
In [6]: import pandas as pd In [7]: df = pd.DataFrame(BSI, columns=Book._fields) In [8]: df Out[8]: author title genre year \ 0 Suzane Collins The Hunger Games Fiction 2008 1 JK Rowling Harry Potter and the Sorcerers Stone Fantasy 1997 price instock 0 6.96 20 1 4.78 12 In [9]: df['price'] *= 100 In [10]: df Out[10]: author title genre year \ 0 Suzane Collins The Hunger Games Fiction 2008 1 JK Rowling Harry Potter and the Sorcerer's Stone Fantasy 1997 price instock 0 696 20 1 478 12
¿No es eso mucho, mucho mejor que trabajar con namedtuple
s?
En Python> = 3.7 puede usar el decorador de clase de datos con la nueva característica de anotaciones variables para producir tipos de registros mutables:
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( "JK 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}")
Salida:
New price for 'The Hunger Games' book is 7.66 New price for 'Harry Potter and the Sorcerer's Stone' book is 5.26