Python - 通过引用复制

qba*_*qba 5 python reference

无论是int还是类实例,都有可能通过引用复制变量吗?

我的目标是拥有两个相同对象的列表,当一个更改时,更改在第二个中可见.

换句话说,我需要指针:/


我只想要int,float和其他通常由value复制的标准类型,强制通过引用复制.这将使我的代码更加一致.

如果没有这种可能性,类包装器是最好的解决方案.

Lup*_*uch 8

您可以在类中包装不可变对象:

class MutableWrapper(object):

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

a = MutableWrapper(10)
b = a
a.value = 20
assert b.value == 20
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 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']]
Run Code Online (Sandbox Code Playgroud)

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


Jer*_*own 1

(编辑以显示取消引用同一内存位置的示例)

Luper Rouch 的方法在处理混合类型列表时非常准确。只需用容器包装不可变类型即可。

如果您确实坚持使用 C 样式数组,其中元素被限制为单一类型(整数数组、字符数组等),则可以使用该ctypes模块。除了使用 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
Run Code Online (Sandbox Code Playgroud)

结果:

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
Run Code Online (Sandbox Code Playgroud)