【问题标题】:Using if else for and del in the same line in python?在python的同一行中使用if else for和del?
【发布时间】:2020-03-12 10:33:15
【问题描述】:

我有一个列表,其中的项目是可变长度的列表。

如果这些可变长度的列表项超过此长度,则需要将其截断为特定长度 (x)。

我已经做了这个小功能。

def truncateList(batch_, trim_len):

truncated_list = []
for eachAbstract in train_abstracts_encoded:
    if len(eachAbstract) > trim_len:
        del eachAbstract[trim_len:]
        truncated_list.append(eachAbstract)
    else:
        truncated_list.append(eachAbstract)
return truncated_list

但是,我可以在一行中以更 Python 的方式完成吗?

像这样:

prefData = [ del eachEncodedAbstract[MAX_LEN:] if len(eachEncodedAbstract) > 510 else eachEncodedAbstract for eachEncodedAbstract in test_abstracts_encoded]

但这不起作用,我收到错误。

    prefData = [ del eachEncodedAbstract[MAX_LEN:] if len(eachEncodedAbstract) > 510 else eachEncodedAbstract for eachEncodedAbstract in test_abstracts_encoded]
               ^
    SyntaxError: invalid syntax

我们将不胜感激。

【问题讨论】:

  • 这已经是最 Pythonic 的方式了。仅仅因为它们适合单行而编写复杂(神秘)的理解并不是最佳实践。不过有一个提示:由于 runcated_list.append(eachAbstract) 是两个 if/else 分支共有的,因此您可以将其移出,从而完全摆脱 else 分支。
  • del 是一个语句,而不是一个表达式。您不能在理解中使用语句 - 只能使用表达式
  • 你为什么del eachAbstract[trim_len:]?你为什么不直接.append(eachAbstract[:trim_len])?你真的需要修剪对原始数据可见吗?
  • "但是,我可以在一行中以更 Pythonic 的方式完成吗?"单行!= pythonic。列表推导和相关表达式(dict /set推导和生成器表达式)旨在简洁地创建映射/过滤操作。它们不是意味着“单行循环”。习惯上,它们应该是函数式转换,即没有副作用,因为这些是函数式编程结构。 del 是非常必要的事情。

标签: python python-3.x list truncate


【解决方案1】:

你可能需要eachEncodedAbstract[:MAX_LEN]

例如:

prefData = [eachEncodedAbstract[:MAX_LEN] if len(eachEncodedAbstract) > 510 else eachEncodedAbstract for eachEncodedAbstract in test_abstracts_encoded]

【讨论】:

    【解决方案2】:

    如果您不想修改 eachAbstract 对象而只是获得一个修剪后的版本,那么您可以使用以下内容:

    truncated_list = [abstract[:trim_len] for abstract in train_abstracts_encoded]
    

    请注意,这与您使用 del 的版本不同,因为它不会修改对象。

    您仍然可以通过将公共部分移出 if/else 分支来简化您的版本:

    truncated_list = []
    for eachAbstract in train_abstracts_encoded:
        if len(eachAbstract) > trim_len:
            del eachAbstract[trim_len:]
        truncated_list.append(eachAbstract)
    

    但是由于无论如何您都在就地修改对象,您可以只创建原始列表的副本然后循环遍历它(这会稍微快一些,因为 copy() 避免重复调用 append 并因此避免内部调整大小):

    truncated_list = train_abstracts_encoded.copy()
    for eachAbstract in truncated_list:
        if len(eachAbstract) > trim_len:
            del eachAbstract[trim_len:]
    

    这里train_abstracts_encodedtruncated_list 共享相同的对象。

    【讨论】:

      猜你喜欢
      • 2018-09-09
      • 2016-05-15
      • 2012-03-11
      • 1970-01-01
      • 2017-11-27
      • 2013-11-18
      • 2022-01-10
      • 2020-04-17
      • 2012-10-19
      相关资源
      最近更新 更多