2

我对 Python 有点陌生(1 天),所以我的问题可能很愚蠢。我已经看过这里,但我找不到我的答案。

我需要以随机大小的随机偏移量修改数组的内容。我有一个 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并重新组合它吗?

4

3 回答 3

1

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

所以这将类似于以下内容,不知道您的 API 调用的确切细节。

the_64_array[31:31+16] = read_device(16)
于 2012-09-20T10:06:14.800 回答
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])

所以我建议以下任何一种:

  • 将 list ( my_64_array) 和一个slice对象传递给 read_device 而不是传递 的结果__getitem__,之后您可以读取必要的数据并设置相应的偏移量。没有子类化。就可读性和易于开发而言,这可能是最好的解决方案。
  • 子类化列表,覆盖__getitem____setitem__返回具有父引用的该子类的实例,然后将列表的所有修改或读取方法更改为引用父列表。如果您是 python 新手,这可能有点棘手,但基本上,您会利用 python 列表属性在很大程度上由list实例内的方法定义。这在性能方面可能更好,因为您可以创建引用。
  • 如果read_device返回结果列表,并且该列表大小相同,则可以执行以下操作:a[x:y] = read_device(a[x:y])
于 2012-09-20T09:27:20.957 回答
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)

于 2012-09-20T09:28:36.323 回答