重新链接python对象(即通过引用传递)

时间:2011-06-23 02:50:59

标签: python reference pass-by-reference

我有一个我想用来操作输入参数的函数,但是,在这个过程中我必须复制输入参数。我不想返回修改后的对象(因为可能涉及或可能不涉及多处理)。如何将输入参数重新分配给复制的值?这是函数的表示:

from copy import deepcopy, copy

def myFunc(myObj,i):
    myObj.x = 'start'
    # I can't avoid this step:
    modObj = deepcopy(myObj)
    modObj.x = 'modified'
    if i == 0:
        myObj.x = modObj.x
    elif i == 1:
        myObj = modObj
    elif i == 2:
        myObj = copy(modObj)
    elif i == 3:
        myObj.__dict__ = modObj.__dict__

class MyClass(object):
   def __init__(self):
       self.x = "construct"

for i in range(4):
   temp = MyClass()
   myFunc(temp,i)
   print i,temp.x

这是输出:

0 modified
1 start
2 start
3 modified

由于选项#3非常接近我想做的事情,是否有“官方”的方式来做到这一点? E.g。

myObj.shallowcopy(modObj)

此浅层复制的行为类似于复制中的浅层复制。一种替代方法是将MyClass作为其他类的成员嵌入,并将该类传递给函数...但是如果我能做到这一点,为什么python只能通过复制成员数据来保存这一步?我读过this,但他们似乎没有给我答案。

1 个答案:

答案 0 :(得分:1)

更新:好的,现在我了解了有关该问题的更多信息,我建议将选项1和4结合使用:创建公共update()dictify()方法。这些可以包围选项4或某些变体,如myObj.__dict__.update(modObj.__dict__) - 这两者都有点hackish。

或者,它们可以是优雅,可读,自我记录的方法,分别接受和返回self的适当字典表示,其可能与self.__dict__重合,也可能不重合。我认为Python之所以没有任何内置功能的原因是没有真正通用的方法来实现它,因为并非所有对象都有__dict__。这种行为具有以实现自定义。

如果操纵__dict__足以满足您的需求,那很好,但是如果您隐藏在后面可以更改的抽象背后的操作,如果您决定要实现__slots__,则可以省去一些麻烦或类似的东西。

(出于历史目的离开以下)


这让我感到困惑:“我不想返回修改后的对象(因为可能涉及或可能不涉及多处理)。”如果您指的是multiprocessing模块,那么即使选项0和3也会失败,因为进程不共享内存。

>>> for i in range(4):
...     temp = MyClass()
...     p = Process(target=myFunc, args=(temp, i))
...     p.start()
...     p.join()
...     print i,temp.x
... 
0 construct
1 construct
2 construct
3 construct

请参阅?如果要在进程之间传输数据,则必须使用multiprocessing的内置类型之一。

>>> from multiprocessing import Process, Queue
>>> 
>>> def myFuncQ(myObj, i, return_queue):
...     myObj.x = 'start'
...     modObj = deepcopy(myObj)
...     modObj.x = 'modified'
...     return_queue.put(modObj)
... 
>>> return_queue = Queue()
>>> for i in range(4):
...     temp = MyClass()
...     p = Process(target=myFuncQ, args=(temp, i, return_queue))
...     p.start()
...     p.join()
...     temp = return_queue.get()
...     print i,temp.x
... 
0 modified
1 modified
2 modified
3 modified

如果您没有使用multiprocessing,那么Queue将与任何其他可变容器一样用于此目的。这是最接近Python的“官方”方式通过引用传递。