对象列表的Python迭代“不可iterable”

2024-09-24 02:22:09 发布

您现在位置:Python中文网/ 问答频道 /正文

刚接触Python,但我已经研究了几个小时了。如果我漏掉了一些显而易见的东西,请原谅。

我有一个名为LineItem的类,它有一个属性lineItems,一个属于给定LineItem的lineItems列表。基本上是一个子列表。

我想打印出一个LineItem及其所有子项(子项拥有子项),但是迭代有问题。

from decimal import * 
class LineItem(object):
    """
    Instance attributes:
      amount: Decimal
      _lineItems: list of child internal lineitems (possibly an empty list)
      isInternal: bool
    """

    def __init__(self, **kw):
        self.amount = Decimal(0)
        self._lineItems = []
        self.isInternal = False
        for k, v in kw.items():
            setattr(self, k, v)

下面定义了一个给我带来麻烦的示例行项目ext2,它有三个孩子。

# External line item with one level of children
int1 = LineItem(amount=Decimal('1886.75'), description='State Dues',
         isInternal=True)
int2 = LineItem(amount=Decimal('232.50'), description='National Dues',
         isInternal=True)
int3 = LineItem(amount=Decimal('50'), description='Processing Fee',
         isInternal=True)
ext2 = LineItem(amount=Decimal('2169.25'), description='Dues',
         _lineItems=[int1, int2, int3])

我有这个递归函数来迭代所有的子项(并将它们编号,比如1、2、2.1作为第二个项的第一个子项,等等)

def print_line_item(LineItems):
    count = 1
    for a in LineItems:
        print count, ' ', a.description, ' (', a.amount, ')'
        if a._lineItems != []:
            for b in a._lineItems:
                print count, '.', print_line_item(b),
        count+=1

但是当我试着用它的时候

def main():
    print_line_item([ext1, ext2, ext3]) #ext1 has no children, prints fine
if __name__=="__main__":
    main()

我明白了

line 56, in print_line_item
    print count, '.', print_line_item(b),
line 51, in print_line_item
    for a in LineItems:
TypeError: 'LineItem' object is not iterable

好吧,不知怎么的,我把名单搞砸了。

如果我添加几个打印语句:

def print_line_item(LineItems):
    count = 1
    for a in LineItems:
        print count, ' ', a.description, ' (', a.amount, ')'
        if a._lineItems != []:
            print a._lineItems
            for b in a._lineItems:
                print b
                print count, '.', print_line_item(b),
        count+=1

我得到的证据表明a.\u lineItems确实是一个列表,打印如下:

[<__main__.LineItem object at 0x0227C430>, <__main__.LineItem object at 0x0227C5F0>, <__main__.LineItem object at 0x0227C670>]

我试图传递给递归调用的b是单个行项目的内存地址

<__main__.LineItem object at 0x0227C430>

所以我该怎么做我想做的?我试过用.iter或___iter___做一些事情,但没有成功。

还有,if a.u系列产品!=[]似乎也不起作用(也没有变化)。我收到“无”的打印行


Tags: inforobjectmaincountlinedescriptionitem
3条回答
def print_line_item(LineItems):
    count = 1
    for a in LineItems:
        print count, ' ', a.description, ' (', a.amount, ')'
        if a._lineItems != []:
            for b in a._lineItems:
                print count, '.', print_line_item(b),
        count+=1

它可能是正确的版本,未经测试。

def print_line_item(LineItems, precedingNumber='1'):
    count = 1
    for a in LineItems:
        print precedingNumber, '.', count, ' ', a.description, ' (', a.amount, ')'
        print_line_item(a._lineItems, precedingNumber + '.' + count),
        count+=1

这是有意义的,你得到了一个不可写的消息——你基本上是递归到列表中每个项的print_line_item中——迟早,你会在列表中找到一些本身不可写的东西——然后你继续调用print_line_item(),它会尝试遍历它。

如果你想问“这个项目是列表吗?”你可以用isinstance(some-object, list)。或者,如果您希望允许其他iterable,但不允许列出内容,则可以使用if isinstance(some-object, collections.Iterable)(必须导入集合)。

你得到一个不可写的消息是有意义的——你本质上是递归到列表中每个项的print_line_item中——迟早,你会在列表中找到一个本身不可写的东西——然后你继续调用print_line_item(),它会尝试迭代它。

如果你想问“这个项目是列表吗?”你可以用isinstance(some-object, list)。或者,如果您希望允许其他iterable但不列出内容,则可以使用if isinstance(some-object, collections.Iterable)(必须导入集合)。

相关问题 更多 >