2012-09-20 18 views
1

我對Python有點新(1天),所以也許我的問題很愚蠢。我已經看過here但我找不到我的答案。將數組/列表的子集引用作爲參數傳遞給Python

我需要以隨機大小隨機偏移修改數組的內容。 我有一個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個字節數組,我想讀從32rd字節開始的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並在?之後重新組合?

回答

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)

+0

謝謝你的回答。正如我對@sapht所說的,我無法修改API函數。我想過切片和重組後,但我不確定內存效率。例如:a = [0,1,2,3,4] –

+0

@MichelL哎呀!我明白...戴着帽子。它是否返回數組? –

+0

是的,原型是 **(int return,u08 [] data_in,u16 num_read)= read_device(Device handle,u08 [] data_in)** –

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])
+1

'__getslice__'被(http://docs.python.org/reference/datamodel.html?highlight=__getslice__#object.__getslice__)有利於__getitem__'的'[自2.0棄用]與'切片()'的論點。 – glglgl

+0

不知道,謝謝。答案已更新。 – sapht

+0

@sapht:我**不能**修改read_device,這是一個API函數。感謝您提供'__getitem__'和'__setitem__'解釋! –

1

看你如何不能更新和/或更改API代碼。最好的方法是將函數傳遞給一個小的臨時數組,然後在函數調用之後將該數組分配給現有的64字節數組。

因此,這將是類似於以下內容,不知道您的API調用的確切細節。

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

這就是我所做的。 –

相關問題