【问题标题】:How to pass slice into a function by reference如何通过引用将切片传递给函数
【发布时间】:2017-02-10 15:50:38
【问题描述】:

如果我有

a = [1, 2, 3]

def foo (arr):
    for i in len (arr): arr [i] += 1

def bar (arr):
    foo (arr[:2])

bar (a)
print (a)

我想输出为

>>> [2, 3, 3 ]

我该怎么做?

动机:我想要一个可以冻结最后一个N 元素的优先级队列,即仅将queue[:N] 传递给heapq.heappush()。但是,每次我将切片传递给它或任何一般函数时,它都会将切片的副本而不是实际列表发送给函数,因此我的列表最终保持不变。

【问题讨论】:

  • 你还有一个问题:for item in arr: item += 1 也不会更改列表。
  • 将数组切片生成另一个对象。
  • 当输出为[2, 3, 4 ]arr[:2]) 有什么意义(所有元素加1)

标签: python python-3.x pass-by-reference slice


【解决方案1】:

如果 a 是 numpy 数组,这将起作用。默认情况下,numpy 切片引用与原始数组相同的内存块。

import numpy as np
a = np.array([1, 2, 3])

def foo(arr):
    for i in range(len(arr)): arr[i] += 1
    # or just arr += 1

def bar(arr):
    foo(arr[:2])

bar(a)
print(a)
# [2, 3, 3 ]

【讨论】:

    【解决方案2】:

    使用列表推导并使用带有[:]的完整切片分配更新初始列表:

    def foo(arr):
       arr[:] = [x+1 for x in arr]
    

    试用:

    >>> a = [1, 2, 3]
    >>> def foo(arr):
    ...    arr[:] = [x+1 for x in arr]
    ...
    >>> foo(a)
    >>> a
    [2, 3, 4]
    

    【讨论】:

    • 不错,但我认为这不是“切片”问题。我承认:OP 问题尚不清楚,但请查看def bar (arr): foo (arr[:2])。我认为不能那样做。
    • 我认为其他功能不能反映 OP 的目标。我看到他们想要的输出已明确说明
    【解决方案3】:

    说实话,我不会去切片,而是传递索引;

    a = [1, 2, 3]
    def foo(array, start, stop, jmp= 1):
        for idx in range(start, stop + 1, jmp):
            array[idx] += 1
    
    def bar(array):
        foo(array, 1, 2)
    bar(a)
    print(a)
    [1, 3, 4]
    

    【讨论】:

      【解决方案4】:

      对列表进行切片将创建一个包含切片内容的新列表,因此arr[:2] 会丢失对原始a 的引用。

      除此之外,像您一样进行迭代根本不会更改列表,它只会更改 item 并忽略该值。

      如果您想更改列表的特定部分,您必须随身携带对原始列表的引用。例如,保留arr,使用enumerate(arr[:2]) 遍历其中的一部分,然后更改arr

      a = [1, 2, 3]
      
      def foo(arr):
          for i, item in enumerate(arr[:2]): 
              arr[i] = item + 1
      
      def bar(arr):
          foo(arr)
      
      bar(a)
      print(a)
      

      现在打印会产生[2, 3, 3],删除enumerate 中的切片会产生[2, 3, 4]。当然,bar 在这里没有任何作用,你可以放弃它,保留foo 并立即致电foo(a)

      【讨论】:

      • @Jean-FrançoisFabre 如果第二个问题是如何传递切片并保留原始引用,那么,不可能按照他想要的方式进行。您可以在迭代期间进行切片以获得类似的结果(如果这是他所追求的)。
      猜你喜欢
      • 2018-06-15
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 2023-03-08
      • 2021-10-26
      • 2017-09-18
      • 1970-01-01
      相关资源
      最近更新 更多