【问题标题】:Python handling NoneType when parsing tables解析表时 Python 处理 NoneType
【发布时间】:2016-09-30 01:19:44
【问题描述】:

我正在尝试比较两个表(table_atable_b)并从table_b 的最后一列中减去table_a 的最后一列。但是, table_a 包含一个额外的行,导致我收到 NoneType 错误。有没有我仍然可以包含来自table_a 的“李子”行并为增量单元输出NULL?下面是我的可测试代码。

当前代码:

from datetime import datetime
import itertools

table_a = (
      (datetime(2016, 9, 28, 0, 0), 'Apples', 650, 700, 850),
      (datetime(2016, 9, 28, 0, 0), 'Oranges', 900, 950, 1000),
      (datetime(2016, 9, 28, 0, 0), 'Grapes', 1050, 1100, 1150),
      (datetime(2016, 9, 28, 0, 0), 'Plums', 2000, 3000, 4000)
      )

table_b = (
      (datetime(2016, 9, 27, 0, 0), 'Apples', 50, 150, 200),
      (datetime(2016, 9, 27, 0, 0), 'Oranges', 250, 350, 400),
      (datetime(2016, 9, 27, 0, 0), 'Grapes', 450, 550, 600),
      )

table_format = '{:<10}|{:<8}|{:<8}|{:<8}|{:<8}|{:<12}'
line_sep = ('-' * 60)

print(line_sep)
print(table_format.format('Date', 'Count_1', 'Count_2', 'Count_3' , 'Count_4', 'Count_4_Delta'))


for a, b in itertools.zip_longest(table_a, table_b):
      l = str(a[0])[0:10]
      m = a[1]
      n = a[2]
      o = a[3]
      p = a[4]
      q = b[4]
      print(line_sep)
      print(table_format.format(l, m, n, o, p, (p-q)))

输出错误:

------------------------------------------------------------
Date      |Count_1 |Count_2 |Count_3 |Count_4 |Count_4_Delta
------------------------------------------------------------
2016-09-28|Apples  |650     |700     |850     |650         
------------------------------------------------------------
2016-09-28|Oranges |900     |950     |1000    |600         
------------------------------------------------------------
2016-09-28|Grapes  |1050    |1100    |1150    |550         
Traceback (most recent call last):
  File "/media/test.py", line 30, in <module>
    q = b[4]
TypeError: 'NoneType' object is not subscriptable

如果我添加一个 if 语句来删除 NoneType,它会打印表格而不会出现错误,但会排除“Plums”行。

for a, b in itertools.zip_longest(table_a, table_b):
      if a and b is not None:
            l = str(a[0])[0:10]
            m = a[1]
            n = a[2]
            o = a[3]
            p = a[4]
            q = b[4]
            print(line_sep)
            print(table_format.format(l, m, n, o, p, (p-q)))

使用 If 语句输出:

------------------------------------------------------------
Date      |Count_1 |Count_2 |Count_3 |Count_4 |Count_4_Delta
------------------------------------------------------------
2016-09-28|Apples  |650     |700     |850     |650         
------------------------------------------------------------
2016-09-28|Oranges |900     |950     |1000    |600         
------------------------------------------------------------
2016-09-28|Grapes  |1050    |1100    |1150    |550              

我想要以下输出。 “李子”行仍在打印,但增量单元格的字符串为“NULL”。

期望的输出:

------------------------------------------------------------
Date      |Count_1 |Count_2 |Count_3 |Count_4 |Count_4_Delta
------------------------------------------------------------
2016-09-28|Apples  |650     |700     |850     |650         
------------------------------------------------------------
2016-09-28|Oranges |900     |950     |1000    |600         
------------------------------------------------------------
2016-09-28|Grapes  |1050    |1100    |1150    |550          
------------------------------------------------------------
2016-09-27|Plums   |2000    |3000    |4000    |NULL        

【问题讨论】:

  • 这是pandas 包的完美应用。看看吧。

标签: python python-3.x parsing itertools nonetype


【解决方案1】:

itertools.zip_longest 接受可选的fillvalue 参数。如果提供,则使用它来代替None

>>> list(itertools.zip_longest([1, 2, 3], [4, 5]))
[(1, 4), (2, 5), (3, None)]
>>> list(itertools.zip_longest([1, 2, 3], [4, 5], fillvalue='NULL'))
[(1, 4), (2, 5), (3, 'NULL')]

您可以提供空行(NULL 值列表)作为fillvalue

class EmptyValue:
    def __sub__(self, other):
        return 'NULL'
    def __rsub__(self, other):
        return 'NULL'

empty_row = [None, 'NULL', EmptyValue(), EmptyValue(), EmptyValue()]
for a, b in itertools.zip_longest(table_a, table_b, fillvalue=empty_row):
    ...

【讨论】:

  • 首先感谢您的收看。该 sn-p 确实解决了 NoneType 错误,但该表仍未打印。现在我收到错误'TypeError: unsupported operand type(s) for -:'int' and 'str''。
  • @MBasith,您可能需要使用另一个值而不是 'NULL',它可以在 - 操作中使用。我会更新答案。
  • 好的,我明白了。不能用字符串减去和整数。
  • 这很好用。我对课程还不是很熟悉,但看起来它们很有价值。如果你有时间,你能告诉我这堂课在做什么吗?非常感谢你的帮助。非常感谢。
  • @MBasith,当您从EmptyValue 实例中减去值时,使用特殊方法__sub____rsub__ 用于从其他值中减去 EmptyValue 实例。换句话说,EmptyValue() - 1 调用EmptyValue().__sub__(1)1 - EmptyValue() 调用 EmptyValue().__rsub__(1)(操作员重载)。我希望我的解释是有道理的。
【解决方案2】:

zip_longest 在值用完时返回单个 None 类型。你想要一个Nones 的列表,或者当你尝试使用下标[] 运算符时你会得到一个TypeError

使用可选的填充值来获取Nones 的列表,然后在格式化输出时测试None,这样当您尝试在q 时执行p-q 时就不会得到另一个TypeErrorNone:

for a, b in itertools.zip_longest(table_a, table_b,fillvalue=[None]*5):
    l = str(a[0])[0:10]
    m = a[1]
    n = a[2]
    o = a[3]
    p = a[4]
    q = b[4]
    print(line_sep)
    print(table_format.format(l, m, n, o, p, (p-q) if q is not None else 'NULL'))

【讨论】:

  • @dawg 这个解决方案很简短。工作得很好。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 2022-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多