Python中的引用

8 投票
2 回答
5094 浏览
提问于 2025-04-16 18:42

我有一个多播网络,需要不断地向所有其他用户发送数据。这些数据会不断变化,所以我不想让程序员去处理发送数据包给用户的事情。因此,我想知道如何在Python中引用任何对象或变量(我对Python还不太熟悉),这样用户就可以修改它,并且这些修改会影响到发送的多播数据包。

下面是我想要的一个例子:

>>> test = "test"
>>> mdc = MulticastDataClient()
>>> mdc.add(test) # added into an internal list that is sent to all users

# here we can see that we are successfully receiving the data
>>> print mdc.receive() 
{'192.168.1.10_0': 'test'}

# now we try to change the value of test
>>> test = "this should change"
>>> print mdc.receive()
{'192.168.1.10_0': 'test'}   # want 'test' to change to -> 'this should change'

如果有人能帮我解决这个问题,我会非常感激。

更新:

我也试过这样做:

>>> test = [1, "test"]
>>> mdc = MulticastDataClient()
>>> mdc.add(test)
>>> mdc.receive()
{'192.168.1.10_1': 'test'}
>>> test[1] = "change!"
>>> mdc.receive()
{'192.168.1.10_1': 'change!'}

这样是有效的。 但是,

>>> val = "ftw!"
>>> nextTest = [4, val]
>>> mdc.add(nextTest)
>>> mdc.receive()
{'192.168.1.10_1': 'change!', '192.168.1.10_4': 'ftw!'}
>>> val = "different."
>>> mdc.receive()
{'192.168.1.10_1': 'change!', '192.168.1.10_4': 'ftw!'}

这个就不行了。在这种情况下,我需要把'ftw!'变成'different.'。我在测试中使用字符串,并且习惯于其他语言中的字符串是对象。我只会编辑对象内部的内容,这样做会有效吗?

2 个回答

4

你不能做到,至少不容易。在Python中,一个名字(变量)其实只是一个指针的位置。如果你覆盖了它,实际上只是把指针换成了另一个指针,也就是说,改变只对使用同一个变量的人可见。对象的成员基本上也是这样,但因为每个指向它们的指针都能看到它们的状态,所以你可以像这样传播变化。你只需要每次都使用 obj.var。当然,字符串(还有整数、元组、一些其他内置类型和几种其他类型)是不可变的,也就是说,你不能改变它们让别人看到,因为你根本无法改变它们。

不过,对象的可变性又打开了另一种可能性:如果你愿意去实现的话,你可以写一个包装类,里面包含一个任意对象,通过 set() 方法来允许改变那个对象,并把所有重要的事情委托给那个对象。不过,你可能会早晚遇到一些麻烦。例如,我无法想象这会和遍历所有成员的元编程很好地配合,或者任何认为需要去干预的东西。这种方法也非常不可靠(也就是不稳定)。可能有更简单的解决方案。

(顺便提一下,PyPy在它的一个非默认对象空间中有一个 become 函数,真的可以把一个对象替换成另一个对象,所有有这个对象引用的人都能看到。不过,这在其他实现中是行不通的,我觉得它的巨大潜力和误用的混淆,加上我们大多数人几乎从未需要过这个,使得它在实际代码中几乎不可接受。)

5

在Python中,一切都是引用,但字符串是不可变的。这意味着test实际上是指向“test”这个字符串的一个引用。如果你把“this should change”赋值给test,你只是把它指向了另一个字符串,而原来的“test”字符串的引用依然存在于其他地方。所以简单来说,在Python中事情不是这样运作的!;-)

一个解决办法是把数据放到一个对象里:

data = {'someKey':"test"}
mdc.add(data)

现在你的其他代码持有的是这个字典的引用。如果你像这样更新字典,你的其他代码就能看到这些变化:

data['someKey'] = "this should change"

撰写回答