【问题标题】:Creating a list in Python with multiple copies of a given object in a single line在 Python 中创建一个列表,在一行中包含给定对象的多个副本
【发布时间】:2023-03-11 00:56:01
【问题描述】:

假设我有一个给定的对象(一个字符串“a”,一个数字 - 比如说 0,或者一个列表 ['x','y']

我想创建一个包含该对象的多个副本的列表,但不使用 for 循环:

L = ["a", "a", ... , "a", "a"]

L = [0, 0, ... , 0, 0]

L = [['x','y'],['x','y'], ... ,['x','y'],['x','y']]

我对第三种情况特别感兴趣。 谢谢!

【问题讨论】:

    标签: python list


    【解决方案1】:

    您可以使用* 运算符:

    L = ["a"] * 10
    L = [0] * 10
    L = [["x", "y"]] * 10
    

    小心这会创建相同项目的N 个副本,这意味着在第三种情况下,您创建一个包含N 个对["x", "y"] 列表的引用的列表;例如,更改 L[0][0] 也会修改所有其他副本:

    >>> L = [["x", "y"]] * 3
    >>> L
    [['x', 'y'], ['x', 'y'], ['x', 'y']]
    >>> L[0][0] = "z"
    [['z', 'y'], ['z', 'y'], ['z', 'y']]
    

    在这种情况下,您可能需要使用列表推导:

    L = [["x", "y"] for i in range(10)]
    

    【讨论】:

    • +1:作用于列表的 * 运算符只是为了做原始发布者想要的。 list(itertools.repeat()) 解决方案对于小钉子来说太大了。
    • 您现在会收到一个金袋子,因为我已经投票赞成它和接受的答案,因此与接受的答案相比,这个答案可能有 2x 票至少有 10 票。不管金徽章如何,这两个答案都很好,顺便说一句。 :-)
    • 在最后一种情况下,由于您没有使用变量i,我认为礼貌的做法是将其命名为_,即L = [['x', 'y'] for _ in range(10)]
    • 实际上,只有最后一行(使用理解)是正确答案,因为 OP 专门要求原始对象的副本(!)。有一个类似的问题 - stackoverflow.com/questions/3459098 - 询问重复项,对于这种情况,* 运算符是正确的解决方案。
    【解决方案2】:

    itertools.repeat() 是你的朋友。

    L = list(itertools.repeat("a", 20)) # 20 copies of "a"
    
    L = list(itertools.repeat(10, 20))  # 20 copies of 10
    
    L = list(itertools.repeat(['x','y'], 20)) # 20 copies of ['x','y']
    

    请注意,在第三种情况下,由于列表是通过引用引用的,因此更改列表中 ['x','y'] 的一个实例将更改所有这些实例,因为它们都引用同一个列表。

    为避免引用同一个项目,您可以使用推导来为每个列表元素创建新对象:

    L = [['x','y'] for i in range(20)]
    

    (对于 Python 2.x,使用 xrange() 而不是 range() 以获得性能。)

    【讨论】:

    • 使用下划线而不是 i 来表示它是一次性变量是 IMO 的好习惯:L = [['x','y'] for _ in range(20)]
    【解决方案3】:

    你可以这样做

    x = <your object>
    n = <times to be repeated>
    L = [x for i in xrange(n)]
    

    用 range(n) 替换 Python 3。

    【讨论】:

      【解决方案4】:

      如果你想要唯一的实例并喜欢golf,这会(稍微)短一些:

      L = [['x', 'y'] for _ in []*10]
      

      疯狂的是它也(明显)更快:

      >>> timeit("[['x', 'y'] for _ in [0]*1000]", number=100000)   
      8.252447253966238                                             
      >>> timeit("[['x', 'y'] for _ in range(1000)]", number=100000)
      9.461477918957826
      

      【讨论】:

        【解决方案5】:

        我希望这对某人有所帮助。我想将 dict 的多个副本添加到列表中并提出:

        >>> myDict = { "k1" : "v1" }
        >>> myNuList = [ myDict.copy() for i in range(6) ]
        >>> myNuList
        [{'k1': 'v3'}, {'k1': 'v3'}, {'k1': 'v3'}, {'k1': 'v3'}, {'k1': 'v3'}, {'k1': 'v3'}]
        >>> myNuList[1]['k1'] = 'v4'
        >>> myNuList
        [{'k1': 'v3'}, {'k1': 'v4'}, {'k1': 'v3'}, {'k1': 'v3'}, {'k1': 'v3'}, {'k1': 'v3'}]
        

        我发现:

        >>> myNuList = [ myDict for i in range(6) ]
        

        没有制作新的字典副本。

        【讨论】:

        • “没有制作新的字典副本” - 这是因为 myNuList = [myDict for i in range(6)] 只创建了 6 个对同一个 dict 的引用。
        【解决方案6】:

        如果您想创建一个插入重复元素的listtuple unpacking 会派上用场:

        l = ['a', *(5*['b']), 'c']
        l
        Out[100]: ['a', 'b', 'b', 'b', 'b', 'b', 'c']
        

        [the docs]

        【讨论】:

          猜你喜欢
          • 2015-03-28
          • 2016-07-15
          • 1970-01-01
          • 2011-05-01
          • 1970-01-01
          • 2020-08-23
          • 1970-01-01
          • 2020-02-16
          • 2019-03-17
          相关资源
          最近更新 更多