Python - 无法更改类中项的值

时间:2013-10-15 22:46:05

标签: python json

我是Python新手,不明白为什么我不能这样做。 当我尝试从父对象更改Packet.ItemData中的值时,它不起作用。请参阅代码中的“不起作用”注释。

import json
from copy import deepcopy


class Event():
    __slots__= 'itemName'

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


    def encode(self):
        obj = {}
        obj['itemName'] = str(self.itemName)               
        return json.dumps(obj)

    def decode(self, json_Str):
        obj = json.loads(json_Str)
        self.itemName = obj['itemName']        



class Packet():
    __slots__= 'pID', 'itemData' 

    def __init__(self, pID, itemData):
        self.pID = pID
        self.itemData = itemData

    def encode(self):
        obj = {}
        obj['pID'] = int(self.pID)
        obj['itemData'] = str(self.itemData.encode())

        return json.dumps(obj)

    def decode(self, json_Str):
        obj = json.loads(json_Str)
        self.pID = obj['pID']
        self.itemData = Event(0,'')


defaultEvent = Event('Dflt')
defaultPacket = Packet(1, defaultEvent)



event2 = Event('NoName')
print 'event : ', event2.encode()
packet3 = deepcopy(defaultPacket)
packet3.ItemData = event2; #direct assign doesn't work
packet3.ItemData = deepcopy(event2); #deep copy doesn't work
packet3.ItemData.itemName = 'Hello' #event this doesn't work
print 'packet : ', packet3.encode()

我想整理数据,以便在JSON编码和解码时得到我期望的结果。

2 个答案:

答案 0 :(得分:4)

FJ指出的确实是正确的......属性的名称是itemData而不是ItemData

对Python不熟悉你可能已经预料到错误会抛出错误......类似'数据包没有属性ItemData',但这不会发生。默认情况下,Python类将属性存储在字典中,因此分配给以前不存在的属性就像将新映射添加到字典中一样。

奇怪的是,你的代码以迂回的方式突出了一个例外......这与描述符__slots__有关。 __slots__将类更改为不再在动态字典中存储属性,而是在静态结构中。有关详细信息,请参阅Usage of __slots__?

通常,在定义__slots__时,您无法分配__slots__中未指定的属性。所以你可能会问....因为你为你的课程定义了__slots__为什么你没有得到AttributeError?答案是__slots__仅适用于'新式课程'参见What is the difference between old style and new style classes in Python?以了解旧式和新式课程之间的区别。

您是否已将Packet定义为从基类object继承,而不仅仅是class Packet(object):,而不仅仅是class Packet()它会使它成为一个新风格的类,你会有当您尝试分配到AttributeError

时,确实获得了ItemData

答案 1 :(得分:2)

属性名称为itemData,而非ItemData。如果您将所有packet3.ItemData引用更改为packet3.itemData,这应该可以正常工作。