Python 更改命名元组列表的值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31252939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 09:42:02  来源:igfitidea点击:

Changing values of a list of namedtuples

pythonlistpython-3.xtuples

提问by Leon Surrao

I have a list of namedtuples named Booksand am trying to increase the pricefield by 20% which does change the value of Books. I tried to do:

我有一个命名的命名元组列表,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)

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?

我知道我无法在命名元组中设置字段。我该如何更新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?

有人可以让我知道为什么会这样吗?

采纳答案by Sait

Named tuples are immutable, so you cannot manipulate them.

命名元组是不可变的,所以你不能操纵它们。

Right way of doing it:

正确的做法:

If you want something mutable, you can use recordtype.

如果你想要一些可变的东西,你可以使用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 recordtypeif you don't have it installed.

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

Bad way of doing it:

糟糕的做法:

You may also keep using namedtuplewith using the _replace()method.

您也可以继续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)

回答by LondonRob

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

这看起来像是 Python 的数据分析库pandas的任务。做这样的事情真的非常容易:

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    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'] *= 100
In [10]: df
Out[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?

现在这不是比使用namedtuples好得多吗?

回答by Vlad Bezden

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

在 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}")

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