Python-通过引用复制
是否有可能通过引用复制变量,无论它是int还是class实例 我的目标是有两个相同对象的列表,当其中一个对象发生变化时,第二个对象的变化是可见的 换句话说,我需要指针:/Python-通过引用复制,python,reference,Python,Reference,是否有可能通过引用复制变量,无论它是int还是class实例 我的目标是有两个相同对象的列表,当其中一个对象发生变化时,第二个对象的变化是可见的 换句话说,我需要指针:/ 我只需要int、float和其他标准类型,它们通常是通过值复制的,强制通过引用复制。这将使我的代码更加一致 如果没有这种可能性,类包装器是最好的解决方案。您可以在类中包装不可变的对象: class MutableWrapper(object): def __init__(self, value):
我只需要int、float和其他标准类型,它们通常是通过值复制的,强制通过引用复制。这将使我的代码更加一致
如果没有这种可能性,类包装器是最好的解决方案。您可以在类中包装不可变的对象:
class MutableWrapper(object):
def __init__(self, value):
self.value = value
a = MutableWrapper(10)
b = a
a.value = 20
assert b.value == 20
我不知道你必须提供什么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
提供的排序列表类型比使用内置list
类型的bisect
模块提供的排序列表类型更有效。使用数据库(如内置的sqlite3
模块访问的数据库)也可以更好地处理此类的操作。可能有一种比使用指针更优雅的python方法来处理这个问题。你能不能提供一点你想做的事情的背景
根据您到目前为止给出的内容,我将对内置列表类型进行子类化,并让它存储自身的替代版本。重写列表方法以对其自身进行操作,并在有意义的地方重写其自身的替代版本。在没有意义的地方,比如在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):
...
...
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']]
这个额外间接层的概念是否能帮助您真正尝试做什么,只有您能知道,因为我们并不真正知道您正在尝试做什么;-)。(编辑以显示对同一内存位置的取消引用示例)
在处理混合类型的列表时,卢珀·鲁奇的方法非常恰当。只需用容器包装不可变的类型
如果您确实坚持使用C样式的数组,其中元素被限制为单一类型(int数组、char数组等),则可以使用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
为什么不在两个位置共享同一个列表?我希望它们以不同的方式排序,并且当一个被修改时,另一个被修复,而不是从一开始构建。@qba:当对象被更改时,唯一的对象将被更改,无论该对象出现在多少个列表中。对象在引用它的所有列表、字典和集合中都会更改。你想解决的问题是什么?对每个对象的更改在使用该对象的任何地方都可见。你有什么问题?请提供代码来说明您的问题。
int
和float
,以及任何其他内容都不会被Python隐式复制。它们以与其他任何东西相同的语义传递。它们是不可变的,这使得它们有点像某些语言中的值类型,但值类型/引用类型范式不适用于Python;它们和所有其他类型的实例的赋值语义工作相同。