【问题标题】:Combining multiple conditional expressions in a list comprehension在列表推导中组合多个条件表达式
【发布时间】:2016-02-20 21:53:07
【问题描述】:

在将 \u2013 等字符插入 SQLite 之前,我对它们进行 utf-8 编码。

当我用 SELECT 将它们拉出时,它们又回到了未编码的形式,所以如果我想对它们做任何事情,我需要重新编码它们。在这种情况下,我想将行写入 CSV。在将行写入 CSV 之前,我想首先将超链接添加到值以“http”开头的任何行。一些值将是整数、日期等,所以我执行以下 条件表达式 - 列表理解 组合:

row = ['=HYPERLINK("%s")' % cell if 'http' in str(cell) else cell for cell in row].

str() 操作会产生众所周知的:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2013' in 位置 15:序数不在范围内 (128) 错误。

然后我需要再次执行.encode('utf-8') 编码,但仅限于列表中以字符串开头的那些元素。以下将不起作用(因为并非所有元素都是字符串):

['=HYPERLINK("%s")' % cell if 'http' in str(cell).encode('utf8') else cell.encode('utf8') for cell in row]

TLDR:如何扩展/修改列表推导以仅对字符串中的元素进行编码?

【问题讨论】:

  • "在将字符插入 SQLite 之前,我对 \u2013 之类的字符进行了 utf-8 编码。"不;这是一件愚蠢的事情,因为 SQLite 很乐意存储 Unicode。如果您必须进行转换,请尽可能靠近输出。

标签: python list unicode conditional list-comprehension


【解决方案1】:

一般来说,尽可能长时间地使用 unicode,并将 unicode 编码为 仅在必要时使用字节(即strs),例如将输出写入网络 套接字或文件。

不要将strs 与unicode 混用——尽管这在 Python2 中是允许的, 它会导致 Python2 使用 ascii 编解码器将 str 隐式转换为 unicode 或反之亦然。如果隐式编码或解码失败,那么您将分别收到 UnicodeEncodingError 或 UnicodedDecodingError,例如您所看到的。

由于cell 是unicode,请使用u'=HYPERLINK("{}")'.format(cell)u'=HYPERLINK("%s")' % cell 而不是'=HYPERLINK("%s")' % cell。 (请注意,如果 cell 包含双引号,您可能需要对 cell 进行 url 编码)。

row = [u'=HYPERLINK("{}")'.format(cell) 
       if isinstance(cell, unicode) and cell.startswith(u'http') else cell 
       for cell in row]

稍后,当/如果您需要将row 转换为strs,您可以使用

row = [cell.encode('utf-8') if isinstance(cell, unicode) else str(cell) 
       for cell in row]

或者,首先将row 中的所有内容转换为strs:

row = [cell.encode('utf-8') if isinstance(cell, unicode) else str(cell) 
       for cell in row]

然后你可以使用

row = ['=HYPERLINK("{}")'.format(cell) if cell.startswith('http') else cell 
       for cell in row]

同样,由于 row 包含 cells 是 unicode,所以执行测试

if u'http' in cell

使用unicode u'http' 而不是str 'http',或者更好,

if isinstance(cell, unicode) and cell.startswith(u'http')

虽然在此处保留'http' 不会出现错误(因为ascii 编解码器可以解码0-127 范围内的字节),但无论如何使用u'http' 是一个好习惯,因为符合规则从不混合strunicode,支持头脑清晰。

【讨论】:

  • 谢谢。但是当if cell.startswith(u'http') 到达一个int 的单元格时,它不会跌倒吗(带有语法错误,因为startswith 不是int 的方法)?
  • 不确定您希望代码如何工作,因为如果 cell 是一个 int...,'http' in cell 会引发 TypeError....
  • 我在str(cell)(不是cell)中检查'http',并且由于str() 操作接受int,这工作正常....直到我遇到有问题的非 ASCII 字符。
  • 我已经完成了以下工作:[u'=HYPERLINK("{}")'.format(cell) if (isinstance(cell, basestring) and 'http' in cell.encode('utf8')) else cell for cell in row]。你的判决?
  • 看起来不错,但经过​​进一步考虑,我认为将所有内容都转换为str first 可能会使代码看起来更漂亮一些。然后你可以放弃isinstance(cell, unicode) 检查。
猜你喜欢
  • 2011-09-17
  • 1970-01-01
  • 2021-03-15
  • 2013-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 2023-04-08
相关资源
最近更新 更多