1
from collections import namedtuple
Book = namedtuple('Book', 'author title genre year price instock')

BSI = [
    Book("JK Rowling", "Harry Potter", "Fantasy", 1997, 10.00, 50),
    Book("Harper Lee", "To Kill a Mockingbird", "Fiction", 1960, 15.00, 100),
    Book("Dan Brown", "Da Vinci Code", "Thriller", 2003, 20.00, 500),
    Book("Mr. Python", "How to Python", "Technology", 2010, 40.00, 10),
    Book("Stephen King", "It", "Horror", 1986, 50.00, 10),
    Book("Some Guy", "Time Traveling", "Technology", 2020, 800.00, 256)
]

def Book_collection_attribute (BSI: list, attribute: str) -> list:
    '''Print out the list of the specific attribute of the list of Book collection'''
    for i in BSI:
        print(i.attribute)
    return BSI
    print(Book_collection_attribute(BSI,'title'))

我的目标是构建一个通用函数来打印前一个列表的属性列表(在此示例中是图书列表及其属性之一:标题或流派或价格)。我可以在 Python 3.3 中执行此操作吗?

不断报错:

Traceback (most recent call last):
  File "C:\Users\ntt2k\Desktop\ICS 31\lab3.py", line 133, in <module>
    print(Book_collection_attribute(BSI,'title'))
  File "C:\Users\ntt2k\Desktop\ICS 31\lab3.py", line 131, in Book_collection_attribute
    print(i.attribute)
AttributeError: 'Book' object has no attribute 'attribute'
4

2 回答 2

2

改变

print(i.attribute)

print(getattr(i, attribute)) 
#or if you want to specify a default, 
#print(getattr(i, attribute, ''))

由于attribute是一个参数,因此您需要提取对象的属性 usinggetattr而不是仅做i.attribute.

于 2013-10-17T17:56:43.993 回答
1

按名称查找属性的通用解决方案是,正如 karthikr 所解释的,getattr:getattr(i, 'foo')与 相同i.foo,并且getattr(i, attribute)允许您使用动态字符串就像使用文字一样简单'foo'

如果您专门处理namedtuples,您可以通过几种不同的方式访问它们的字段到索引的映射。例如,i._fields为您提供(有序的)字段列表,同时i._asdict()为您提供与 an 相同的值OrderedDict,因此您可以这样做d = i._asdict(),然后只需d[attribute].

然而,所有这些都引发了一个问题,即为什么你namedtuple首先使用 a 。通常,尤其是属性访问的全部意义namedtuple在于,它非常适合静态访问其属性:其中属性名称是源代码的一部分。以这种方式使用它类似于动态创建一堆变量,这是一个坏主意,如herehere所述。

如果你只是使用一个dict——或者一个继承自或拥有一个的类——这将是微不足道的,因为通过名称动态查找事物就是 adict的全部意义:i[attribute].

而且,即使没有类,您仍然可以编写一个book函数来dict为您构建,因此您的其余代码看起来一样好。例如:

def book(author, title, genre, year, price, instock):
    return {'author': author, 'title': title, 'genre': genre, 
            'year': year, 'price': price, 'instock': instock}

将其与您生成的代码namedtuple(您可以将其视为Book.source)进行比较,它要简单得多。如果你不喜欢这种重复,你总是可以这样做:

def book(*args):
    return dict(zip('author title genre year price instock'.split(), args))

当然,有时您会遇到一种情况,即您主要希望静态访问属性,但偶尔希望动态访问它们。在这种情况下,getattr它正是适合这项工作的工具。

于 2013-10-17T18:09:09.140 回答