python - pypubsub 消息数据是通过引用还是值发送的,为什么我不应该修改消息数据
问题描述
我正在使用 python 3。并且想知道附加到 pypubsub Sendmessage 命令的消息数据是通过引用还是通过值发送?它似乎是通过引用发送的,但我想知道是否有人可以验证这一点。
文档还说“消息不变性:侦听器必须保持消息内容不变,但 PyPubSub 不验证这一点”
下面的代码示例表明正在发送对消息数据参数的引用,并且修改这些数据会修改原始数据(而不是传递的数据副本)。为什么在侦听器例程中修改消息数据是个坏主意?
from pubsub import pub
class widget():
def __init__(self):
self.thingy = [{'biz':0},{'baz':1},{'buz':2}]
pub.subscribe(self.listen_for, 'wodget')
def listen_for(self, arg1):
print('wodget heard')
print(self.thingy)
print(arg1)
def send_thingy(self):
arg1 = self.thingy
pub.sendMessage('widget',arg1=arg1)
class wodget():
def __init__(self):
self.thongy = None
pub.subscribe(self.listen_for, 'widget')
# listen calendar
def listen_for(self, arg1):
print('widget heard')
print(arg1)
self.thongy = arg1
self.thongy[1]['baz']=99
print(arg1)
print(self.thongy)
arg1 = self.thongy
pub.sendMessage('wodget',arg1=arg1)
if __name__ == "__main__":
aWidget = widget()
aWidget.send_thingy()
aWodget = wodget()
aWidget.send_thingy()
解决方案
一个简单的脚本似乎表明使用 pypubsub 回调修改对象的行为与正常的 python 行为一致,这对我来说很有意义,因为 pypubsub 只是函数回调。见下文。
另请参阅:如何通过引用传递变量?讨论不变性。
from pubsub import pub
class TestClass():
def __init__(self):
self.item_1 = 10.0
self.item_2 = [1,2,3]
self.item_3 = {1:[3,4,5], 2:[6,7,8]}
def change_values(self):
self.item_1 += 1
self.item_2 = [v + 1 for v in self.item_2]
self.item_3 = {k:[v + 1 for v in self.item_3[k]] for k in self.item_3}
def print_values(self):
print(self.item_1)
print(self.item_2)
print(self.item_3)
# print('\n')
def receive_class(an_object):
print('INSIDE - BEFORE')
an_object.print_values()
an_object.change_values()
print('INSIDE - AFTER')
an_object.print_values()
def receive_variable(a_variable):
print('INSIDE - BEFORE')
print(a_variable)
a_variable += 1.0
print('INSIDE - AFTER')
print(a_variable)
def receive_list(a_list):
print('INSIDE - BEFORE')
print(a_list)
a_list[0] += 1
a_list[1] += 1
a_list[2] += 1
print('INSIDE - AFTER')
print(a_list)
if __name__ == "__main__":
pub.subscribe(receive_class, "test_topic_class")
pub.subscribe(receive_variable, "test_topic_variable")
pub.subscribe(receive_list, "test_topic_list")
### TEST 1
print('-----CLASS TEST')
myclass = TestClass()
print('OUTSIDE - BEFORE')
myclass.print_values()
pub.sendMessage("test_topic_class", an_object=myclass)
print('OUTSIDE - AFTER')
myclass.print_values()
### TEST 2
print('-----VARIABLE TEST')
avar = 100.0
print('OUTSIDE - BEFORE')
print(avar)
pub.sendMessage("test_topic_variable", a_variable=avar)
print('OUTSIDE - AFTER')
print(avar)
### TEST 3
print('------LIST TEST')
alist = [1.0, 2.0, 3.0]
print('OUTSIDE - BEFORE')
print(alist)
pub.sendMessage("test_topic_list", a_list=alist)
print('OUTSIDE - AFTER')
print(alist)
输出:
-----CLASS TEST
OUTSIDE - BEFORE
10.0
[1, 2, 3]
{1: [3, 4, 5], 2: [6, 7, 8]}
INSIDE - BEFORE
10.0
[1, 2, 3]
{1: [3, 4, 5], 2: [6, 7, 8]}
INSIDE - AFTER
11.0
[2, 3, 4]
{1: [4, 5, 6], 2: [7, 8, 9]}
OUTSIDE - AFTER
11.0
[2, 3, 4]
{1: [4, 5, 6], 2: [7, 8, 9]}
-----VARIABLE TEST
OUTSIDE - BEFORE
100.0
INSIDE - BEFORE
100.0
INSIDE - AFTER
101.0
OUTSIDE - AFTER
100.0
------LIST TEST
OUTSIDE - BEFORE
[1.0, 2.0, 3.0]
INSIDE - BEFORE
[1.0, 2.0, 3.0]
INSIDE - AFTER
[2.0, 3.0, 4.0]
OUTSIDE - AFTER
[2.0, 3.0, 4.0]
推荐阅读
- c# - 如何在 C# 中将 json 数据转换为对象?
- c++ - 无法访问嵌入到 Objective-C 项目中的 C++ 代码中的文件
- c# - WPF 如何使用 GridViewColumns(ListView 绑定)添加绑定到数组元素的列
- vba - 如何在 VBA 中创建一个函数以返回与记录集中每条记录的特定条件匹配的列名?
- angular - SVG animateTransform 不更新 from 和 to 值变化
- sql - BigQuery:将 mm/yyyy 日期与特定日期和 CURRENT_DATE 进行比较
- php - 将文件从一个 laravel 应用上传/存储到另一个 laravel 应用
- sql - 如何完全按照给定的图像排序行?
- java - 由 JButton 组成的 ArrayList。但没有按预期工作
- excel - 当前工作表的行限制超过 1,048,576 时,继续在连续工作表中粘贴数据