首页 > 解决方案 > 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()

标签: pythonpypubsub

解决方案


一个简单的脚本似乎表明使用 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]

推荐阅读