【问题标题】:Python generating list with unique lexical elementsPython 生成具有唯一词法元素的列表
【发布时间】:2013-08-24 12:08:34
【问题描述】:

假设我想像这样创建一个空的 3x4 二维数组。

x = [[0.0]*3]*4

但是,使用上面的代码,

print x[0] is x[1]     # Output = True

意义,

x[1][1] = 5.0
print x      # Output = [[0.0, 5.0, 0.0], 
             #           [0.0, 5.0, 0.0], 
             #           [0.0, 5.0, 0.0], 
             #           [0.0, 5.0, 0.0]]

为了绕过使用 4 个对同一列表的相同引用来创建此列表,我一直在做类似的事情:

y = [[0.0]*3, [0.0]*3, [0.0]*3, [0.0]*3]

在哪里

print y[0] is y[1]     # Output = False
y[1][1] = 5.0
print y      # Output = [[0.0, 0.0, 0.0], 
             #           [0.0, 5.0, 0.0], 
             #           [0.0, 0.0, 0.0], 
             #           [0.0, 0.0, 0.0]]

另一种方法是使用列表推导

z = [[0.0]*3 for x in range(4)]

但是,这看起来还是有点难看。

有没有办法让数组“y”或“z”,其中所有引用在优雅的格式中都是唯一的,例如在“x”中使用列表上的乘法?

【问题讨论】:

    标签: python arrays list list-comprehension


    【解决方案1】:

    列表推导是通常的答案。不像序列乘法那样干净,但最好的:

    [[0.0]*3 for _ in xrange(4)]
    

    请注意,对于许多需要值网格的应用程序,您正在做的事情 numpy ndarrays 可以做得更快、更清晰。

    【讨论】:

      【解决方案2】:

      这是在官方 Python 编程常见问题解答中,How do I create a multidimensional list?

      FAQ 提出了三种可能性:

      1. 创建所需长度的列表,然后循环替换每个元素。
      2. 使用列表理解。
      3. 首先使用 numpy.array 之类的东西,而不是多维列表。

      我认为大多数 Python 开发人员会以与常见问题解答中列出的完全相反的顺序提出这些建议……但没有人会抱怨其中的任何一个。所以:

      a = np.zeros((3, 4))
      
      a = [[0.0]*3 for _ in range(4)]
      
      a = [None] * 4
      for i, _ in enumerate(a):
          a[i] = [0.0]*3
      

      如果你发现自己经常这样做(而不是使用 numpy),你总是可以将它包装在一个函数中。事实上,这通常是处理 anything 的最佳方式,即使您尽可能以 Python 方式进行操作也是如此。所以:

      def make_matrix(r, c):
          return [[0.0]*c for _ in range(r)]
      

      然后它就尽可能清晰了:

      a = make_matrix(3, 4)
      

      itertools 有一个名为repeat 的函数,相当于* 的迭代器版本。文档显示了一些等效的纯 Python 代码,因此很容易将其调整为(浅或深)复制每个代表的对象:

      def repeat(obj, times):
          for _ in range(times):
              yield copy.copy(obj)
      
      list(repeat([0.0]*3, 4))
      

      我不认为这更具可读性——尤其是如果您想在多个级别上使用它:

      list(repeat(list(repeat(0.0, 3)), 4))
      

      …即使您将其包装在为您列出的函数中:

      def srepeat(object, times):
          return list(repeat(object, times))
      srepeat(srepeat(0.0, 3), 4)
      

      …如果你将它包装在一个处理多个维度的函数中,你只是重新创建了make_matrix

      【讨论】:

      • itertools.repeat 不能这样工作。除了使用迭代器而不是外部列表之外,它将执行与序列乘法代码相同的操作。
      • @user2357112:你是对的;您实际上需要一个重复副本的功能……让我编辑答案。谢谢。
      猜你喜欢
      • 1970-01-01
      • 2015-07-12
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多