【问题标题】:In Python, why zipped elements get separated, when added to a list?在 Python 中,为什么压缩的元素在添加到列表时会被分开?
【发布时间】:2018-01-28 14:18:34
【问题描述】:

我想创建像 A1、B2、C3 和 D4 这样的名称

batches = zip('ABCD', range(1, 5))

for i in batches:
  batch = i[0] + str(i[1])
  print(batch)

这会产生预期的输出:

A1
B2
C3
D4

但是,如果我将一个列表 batch_list 初始化为空并将每个批次添加到其中,如下所示:

batch_list = []

batches = zip('ABCD', range(1, 5))

for i in batches:
  batch_list += i[0] + str(i[1])

print(batch_list)

输出如下:

['A', '1', 'B', '2', 'C', '3', 'D', '4']

为什么不呢?

['A1', 'B2', 'C3', 'D4']

【问题讨论】:

  • 您的扩展列表没有附加到它。
  • 如果你使用batch_list = [ch + str(n) for ch, n in zip('ABCD', range(1, 5))],代码会变得更清晰,更少混乱

标签: python string algorithm list iterator


【解决方案1】:

因为它将您的字符串视为一个数组。

>>> arr = []
>>> arr += 'str'
>>> arr
['s', 't', 'r']

试试这个:

batch_list += [i[0] + str(i[1])]

或者这个:

batch_list.append(i[0] + str(i[1]))

【讨论】:

    【解决方案2】:

    问题是您扩展列表而不是附加到它。 Python 也考虑字符串序列:

    >>> l = []
    >>> l += 'ab'
    >>> l
    ['a', 'b']
    

    因此,+= 将通过将左侧可迭代项中的每个项目解包到右侧列表中来扩展列表。在幕后,+=list.__iadd__ 的语法糖:

    >>> l = []
    >>> l.__iadd__('abc')
    ['a', 'b', 'c']
    

    list.__iadd__ 在传递一个可迭代对象时,与list.extended 具有相同的行为:

    >>> l = []
    >>> l.extend('ab')
    >>> l
    ['a', 'b']
    

    要获得所需的行为,请改用list.append

    batch_list.append(i[0] + str(i[1]))
    

    【讨论】:

      【解决方案3】:

      通过使用+= 运算符,您可以将字符串中的每个项目附加到您的batch_list。因此,避免破坏字符串的一种方法是将其包装在一个列表中。

      batch_list = []
      for i in zip('ABCD', range(1,5)):
          batch_list += [i[0] + str(i[1])]
      print(batch_list)
      

      输出

      ['A1', 'B2', 'C3', 'D4'] 
      

      顺便说一句,使用list.appendlist.extend 方法通常比使用+= 更好。尽管使用+= 的代码更短,但使用这些方法使代码更具可读性,但还有其他好处,例如能够改变全局列表,尽管有些人可能会争辩说你不应该这样做。 ;)


      但是有更好的方法来写这个。

      您可以使用列表推导,并让.format 方法将字母与数字组合起来,这样就无需显式调用str 构造函数。

      batch_list = ['{}{}'.format(*u) for u in zip('ABCD', range(1, 5))]
      

      另一种选择是使用enumerate,而不是使用range 进行压缩。 enumerate 函数允许您提供起始编号,而不是使用默认的起始编号零。

      batch_list = ['{}{}'.format(v, i) for i, v in enumerate('ABCD', 1)]
      

      这可能是最有效的方式,除非你有 Python 3.6,在这种情况下你可以使用 f-string 来进行格式化:

      batch_list = [f'{v}{i}' for i, v in enumerate('ABCD', 1)]
      

      【讨论】:

      • 我从@Danil Speransky、Christian Dean 和 PM 2Ring 那里得到的每一个答案都物超所值。除了提供的简洁正确的代码之外,我将您的投票(PM 2Ring)作为提供的丰富信息的正确答案。我无法将多个回答标记为正确答案,这真是令人难过和可耻。
      • @SeshadriR 不过,您可以根据需要对任意数量的答案进行投票。
      • @mkrieger1 是的,我这样做是为了表达对他人的感激之情。
      【解决方案4】:
      >>> from itertools import count
      >>> batch_list = []
      >>> for i, v in zip('ABCD', count(1)): # count(1) -> start counter at 1
      ...     batch = '{}{}'.format(i, v)
      ...     batch_list.append(batch)
      ... 
      >>> batch_list
      ['A1', 'B2', 'C3', 'D4']
      

      【讨论】:

      • 虽然这产生了预期的结果,但它并没有回答为什么第二种方法没有按预期工作的问题。
      • @mkrieger1,很简单,因为答案已经给出。我建议基于范围参数的替代解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-28
      • 1970-01-01
      • 2019-06-23
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多