2010-05-06 98 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']] 

是否额外的间接级别的概念可以帮助你究竟正在试图做可言,只有你可以告诉,因为我们真的不知道它是什么,你试图做;-)。