2010-05-06 86 views
4

有沒有可能通過引用複製變量,無論它的int或類實例是什麼?Python - 通過引用複製

我的目標是擁有兩個相同對象的列表,當其中一個發生變化時,第二個可以看到變化。

換句話說我需要指針:/


我只是想整數,浮點和其他標準類型的通常由值複製,力通過參考複製。這將使我的代碼更加一致。

如果沒有這種可能性,類包裝是最好的解決方案。

+1

爲什麼不分享在這兩個地方同一個列表? – 2010-05-06 18:35:41

+0

我希望它們以不同的方式排序,並且當其中一個被修改時,其他的被修復,而不是從開始構建。 – qba 2010-05-06 18:42:21

+0

@qba:當對象被改變時,無論對象出現在多少個列表中,唯一的對象都會改變。對象在所有列表,字典和引用它的集合中改變。你想解決什麼問題?對每個對象的更改都是可見的**無處不在**使用該對象。你有什麼麻煩?請提供代碼以顯示您的問題。 – 2010-05-06 20:29:37

回答

0

(編輯,以顯示示例解引用到相同存儲器位置的)

Luper魯什的做法是斑點上具有混合類型的列表的時候。只需用容器包裝不可變類型即可。

如果你真的堅持C元素數組被限制爲單一類型(整數,字符數組等等),你可以使用​​模塊。除了使用DLL的FFI以外,它還可以訪問c數據類型和指針。

from ctypes import * 
containerTYPE = POINTER(c_uint) * 10 #Array of pointers to UINTs of size 10 
containerA = containerTYPE() 
containerB = containerTYPE() 

for i in range(10): 
    val = c_uint(i) 
    containerA[ i ] = pointer(val) 
    containerB[ -1 - i ] = pointer(val) 

print "A\tB" 
for i in range(10): 
    print containerA[ i ].contents.value, "\t", containerB[ i ].contents.value 

for i in range(10): #affects both arrays 
    derefed = containerA[ i ].contents 
    derefed.value = i * 2 

print 
print "A\tB" 
for i in range(10): 
    print containerA[ i ].contents.value, "\t", containerB[ i ].contents.value 

結果:

A  B 
0  9 
1  8 
2  7 
3  6 
4  5 
5  4 
6  3 
7  2 
8  1 
9  0 

A  B 
0  18 
2  16 
4  14 
6  12 
8  10 
10  8 
12  6 
14  4 
16  2 
18  0 
8

你可以用你不可變對象的一類:

class MutableWrapper(object): 

    def __init__(self, value): 
     self.value = value 

a = MutableWrapper(10) 
b = a 
a.value = 20 
assert b.value == 20 
0

我不知道你必須提供什麼樣的API。這是可能的,你要像

import bisect 

class DualLists(object): 
    def __init__(self, iterable=[]): 
     self.insertion_order = list(iterable) 
     self.sorted = sorted(self.insertion_order) 

    def append(self, item): 
     self.insertion_order.append(item) 
     bisect.insort(self.sorted, item) 

>>> d = DualLists() 
>>> d.append(4) 
>>> d.append(6) 
>>> d.append(1) 
>>> d.insertion_order 
[4, 6, 1] 
>>> d.sorted 
[1, 4, 6] 

注意,第三方包blist提供了更有效的排序列表類型比使用bisect模塊與內置list類型可以提供。通過使用數據庫(如內置sqlite3模塊訪問的數據庫),也可以更好地爲此類操作提供服務。

0

有可能比使用指針更優雅,pythonic方式來處理這個。你能否提供一些你想要做的事情。

根據你到目前爲止給出的內容,我將子類化內置列表類型並讓它存儲自己的替代版本。重寫列表方法以在其自身上進行操作,以及在其有意義的情況下替代自身的版本。在沒有意義的情況下,如在sort()函數中,爲備用列表定義第二個函數。

這隻有真正有意義,如果排序是不合理的昂貴;否則,我只會維護一個列表並根據需要進行排序。

class MyList(list): 

    def __init__(self, li): 
     super(MyList, self).__init__(li) 
     self.altlist = list(li) 

    def append(self, x): 
     super(MyList, self).append(x) 
     self.altlist.append(x) 

    def sortalt(self): 
     ... 

    ... 
8

的Python總是通過引用作品的,除非你明確要求拷貝(內置列表的片段被視爲「索要副本」 - 但numpy的陣列的片還通過工作參考)。但是,正因爲如此,alist=anotherlist; alist.sort()意味着單個列表對象(具有兩個等效名稱alistanotherlist)被排序 - 您無法在同一列表對象上同時維護兩個不同的排序。

所以,在這種情況下,你必須明確要求副本(例如alist=list(anotherlist)) - 並且一旦你這樣做,有兩個不同的列表中的對象之間沒有更多的連接。你不可能有兩種方法:要麼通過引用來工作(並且只有一個列表對象,因此只有一個順序!),或者製作一個副本(在這種情況下,最終會有兩個單獨的列表對象)。

你可以採取的事實副本,以便討論優勢至今都 - 對象(項目),這兩個名單是指同...直到除非您執行清除,添加或重新分配任一清單上的項目(突變另一方面不會改變此連接:它是與上述任何項目完全分開和完全不同的情況,因爲清除,添加和重新分配是列表上的操作,同時調用項目上的變異方法是項目上的操作- 項目忘記了涉及它們的一個或多個列表上的任何操作,列表對於任何對其參考的一個或多個項目進行操作)。

除了在其他答案中建議的兩個列表包裝和同步到單個對象中,您可以做的除了刪除和添加之外沒有太多可做的事情;但是對於項目的重新分配,如果這就是你所需要的,那麼你可以通過添加一個間接級別而不是直接引用項目的列表來將它們轉變成突變項目。到一個項目的子列表。例如:

>>> alist = list([x] for x in 'ciao') 
>>> blist = list(alist) 
>>> blist.sort() 
>>> alist 
[['c'], ['i'], ['a'], ['o']] 
>>> blist 
[['a'], ['c'], ['i'], ['o']] 
>>> blist[-1][0] = 'z' 
>>> blist 
[['a'], ['c'], ['i'], ['z']] 
>>> alist 
[['c'], ['i'], ['a'], ['z']] 

是否額外的間接級別的概念可以幫助你究竟正在試圖做可言,只有你可以告訴,因爲我們真的不知道它是什麼,你試圖做;-)。