是否有可能通过引用复制变量,无论其int或类实例是什么?
我的目标是拥有两个相同对象的列表,当一个更改时,更改在第二个中可见。
换句话说,我需要指针:/
我只想要int,float和其他通常按值复制的标准类型,强制通过引用复制。这将使我的代码更加一致。
如果没有这种可能性,类包装器是最好的解决方案。
答案 0 :(得分:8)
您可以将不可变对象包装在类中:
class MutableWrapper(object):
def __init__(self, value):
self.value = value
a = MutableWrapper(10)
b = a
a.value = 20
assert b.value == 20
答案 1 :(得分:8)
Python总是通过引用工作,除非你明确要求一个副本(一个内置列表的片段被认为是“要求复制” - 但是一块numpy数组也可以通过引用工作)。但是,正因为如此,alist=anotherlist; alist.sort()
表示单个列表对象(具有两个等效名称alist
和anotherlist
)被排序 - 您无法同时维护两个不同的排序在同一个列表对象上。
所以,在这种情况下,你必须明确要求一个副本(例如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']]
这个额外间接层次的概念是否可以对你正在尝试做的事情有所帮助,只有你能说出来,因为我们并不真正知道你是什么< strong> 尝试做; - )。
答案 2 :(得分: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
模块访问的数据库)也可以更好地处理此类的操作。
答案 3 :(得分: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):
...
...
答案 4 :(得分:0)
(已编辑以显示取消引用相同内存位置的示例)
在处理混合类型列表时,Luper Rouch的方法很有用。只需用容器包装不可变类型。
如果你真的坚持C风格的数组,其元素被限制为单一类型(整数数组,字符数组等),你可以使用ctypes
模块。除了FFI之外,它还允许您访问c数据类型和指针以使用DLL。
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