更改namedtuples列表的值

Leo*_*rao 28 python tuples list python-3.x

我有一个命名的命名元组列表,Books我试图将price字段增加20%,这确实改变了它的值Books.我试着这样做:

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)
Run Code Online (Sandbox Code Playgroud)

但我一直在:

 Traceback (most recent call last):
 print(item.price)
 AttributeError: 'float' object has no attribute 'price'
Run Code Online (Sandbox Code Playgroud)

我知道我不能在namedtuple中设置字段.我该如何进行更新price

我试着把它变成一个函数:

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))
Run Code Online (Sandbox Code Playgroud)

但我得到一个错误,替换说:

 rest.price = rest._replace(price = rest.price + newprice)
 AttributeError: can't set attribute
Run Code Online (Sandbox Code Playgroud)

有人能告诉我为什么会这样吗?

Sai*_*ait 41

命名元组是不可变的,因此您无法操纵它们.

正确的做法:

如果你想要一些可变的东西,你可以使用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)
Run Code Online (Sandbox Code Playgroud)

PS:pip install recordtype如果你没有安装它,你可能需要.

糟糕的做法:

您也可以继续namedtuple使用该_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('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)
Run Code Online (Sandbox Code Playgroud)

  • @ progo,`_replace`实际上不是"私人"或内部.基于[this](https://docs.python.org/3/library/collections.html#collections.namedtuple)doc:_为了防止与字段名冲突,方法和属性名称以下划线开头._ (6认同)
  • 我不了解python社区...那个`namedtuple._replace()`在功能语言中很惯用,为什么这里的“私有”!这样做确实应该不是坏方法,它肯定比转变为易变的疯狂更好 (3认同)
  • @LeonSurrao我根据你的意愿用`_replace()`方法更新了帖子. (2认同)
  • 而不是'rest.price = rest._replace(price = rest.price + newprice)`,做`rest = rest._replace(price = rest.price + newprice)`.注意`_replace()`返回一个`namedtuple`的新实例. (2认同)
  • @Sait“假设您的元组中有数百万个项目。” 这不太可能发生,是吗? (2认同)

Vla*_*den 8

在Python> = 3.7中,可以将数据类修饰器与新的变量注释功能一起使用,以生成可变的记录类型:

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}")
Run Code Online (Sandbox Code Playgroud)

输出:

New price for 'The Hunger Games' book is 7.66
New price for 'Harry Potter and the Sorcerer's Stone' book is 5.26
Run Code Online (Sandbox Code Playgroud)

  • 我希望我能给予更多的支持——这保持了“namedtuple”的简单性,增加了类的可变性,并且不需要任何其他包,无论轻量级还是重度。 (4认同)