【问题标题】:How to build a generic function to print out a list of attribute for a previous list in Python 3.3?如何构建一个通用函数来打印 Python 3.3 中先前列表的属性列表?
【发布时间】:2013-10-17 17:55:00
【问题描述】:
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'

【问题讨论】:

  • 如果您尝试动态使用属性名称,为什么要使用namedtuple 而不仅仅是使用dict(或继承自dict 或使用dict 的类)? namedtuple 的全部意义在于为您提供 static 属性,您可以通过在源代码中找到它们的名称来查找这些属性。
  • 另外,如果您确实需要解构 namedtuple 出于某种原因,您始终可以将其属性名称的有序列表访问为 i_fields,或将其转换为 OrderedDict i._asdict().

标签: python python-3.x generic-list generic-programming generic-collections


【解决方案1】:

改变

print(i.attribute)

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

由于attribute是一个参数,你需要使用getattr来提取对象的属性,而不是仅仅使用i.attribute

【讨论】:

    【解决方案2】:

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

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

    但是,所有这些都引发了一个问题,即您为什么首先使用namedtuple。一般来说,属性访问的全部要点,尤其是namedtuple,是它非常适合静态 访问其属性:其中属性名称是源代码的一部分。以这种方式使用它类似于动态创建一堆变量,这是一个坏主意,正如 herehere 所解释的那样。

    如果您只使用 dict(或继承自或拥有它的类),这将是微不足道的,因为通过名称动态查找事物就是 dict 的全部意义所在: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 正是适合这项工作的工具。

    【讨论】:

    • 感谢您提供的所有答案和非常有用的参考资料。 :D 我必须使用“namedtuple”,因为这是我课堂作业的一部分。我们还没有学过字典。无论如何,再次感谢您的答案。
    • @TrungNguyen:你的老师在dict之前教过你namedtuple?严重地?你可能需要一位新老师……
    • @TrungNguyen 你确定你没有错过dict 的课程吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 2010-12-21
    相关资源
    最近更新 更多