在Python中将数组/列表的子集引用作为参数传递

时间:2012-09-20 09:15:24

标签: python arrays list reference arguments

我对Python有点新(1天),所以也许我的问题很愚蠢。我已经看了here,但我找不到答案。

我需要以随机大小随机偏移修改数组的内容。 我有一个Python API来连接USB设备的DDL,我无法修改。有一个函数就像这个:

def read_device(in_array):
    # The DLL accesses the USB device, reads it into in_array of type array('B')
    # in_array can be an int (the function will create an array with the int 
    # size and return it), or can be an array or, can be a tuple (array, int)

在我的代码中,我创建了一个数组,比方说,64字节,我想从32字节开始读取16个字节。在C中,我将&my_64_array[31]赋予read_device函数。 在python中,如果给出:

read_device(my_64_array[31:31+16])

似乎in_array是对给定子集的副本的引用,因此my_64_array不会被修改。

我该怎么办?我是否必须拆分my_64_array并在??之后重新组合

3 个答案:

答案 0 :(得分:1)

了解您无法更新和/或更改API代码的方式。最好的方法是将函数传递给一个小的临时数组,然后在函数调用之后将其分配给现有的64字节数组。

因此,如下所示,不知道API调用的具体细节。

the_64_array[31:31+16] = read_device(16)

答案 1 :(得分:0)

在阅读列表子集时,您使用该列表的__getitem__参数调用slice(x, y)。在您的情况下,这些陈述是相同的:

my_64_array[31:31+16]
my_64_array.__getitem__(slice(31, 31+16))

这意味着可以在子类中重写__getitem__函数以获得不同的行为。

您还可以使用a[1:3] = [1,2,3]设置相同的子集,在这种情况下,它会调用a.__setitem__(slice(1, 3), [1,2,3])

所以我建议其中任何一个:

  • 将列表(my_64_array)和slice对象传递给read_device,而不是传递__getitem__的结果,之后您可以读取必要的数据并设置相应的偏移量。没有子类化。就可读性和易开发性而言,这可能是最佳解决方案。
  • 子类化列表,重写__getitem____setitem__以使用父引用返回该子类的实例,然后更改列表的所有修改或读取方法以引用父列表。如果你是python的新手,这可能有点棘手,但基本上,你会利用python列表属性主要由list实例中的方法定义。这可能在性能方面更好,因为您可以创建引用。
  • 如果read_device返回结果列表,并且该列表大小相同,则可以执行以下操作:a[x:y] = read_device(a[x:y])

答案 2 :(得分:0)

正如您所说,如果您将切片输入到函数中,它会创建切片的参考副本。

稍后添加它的两种可能方法(假设read_device返回相关切片):

my_64_array = my_64_array[:32] + read_device(my_64_array[31:31+16]) + my_64_array[31+16:]
# equivalently, but around 33% faster for even small arrays (length 10), 3 times faster for (length 50)...
my_64_array[31:31+16] = read_device(my_64_array[31:31+16])

所以我认为你应该使用后者。

如果它是一个可修改的函数(但不是在这种情况下!)你可以改变你的函数参数(一个是整个数组):

def read_device(the_64_array, start=31, end=47):
   # some code
   the_64_array[start:end] = ... #modifies `in_array` in place

并致电read_device(my_64_array)read(my_64_array, 31, 31+16)