2013-10-15 4 views
1

Я новичок в Python и не понимаю, почему я не могу этого сделать. Когда я пытаюсь изменить значения в Packet.ItemData из родительского объекта, это не сработает. См. Комментарии «Не работает» в коде.Python - Невозможно изменить значение элемента внутри класса

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.

ответ

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

+0

Спасибо , Я ненавижу погоню чувствительной, поэтому использую паскаль. Я пытался использовать слоты, чтобы предотвратить добавление дополнительных данных. – runfastman

2

Наименование атрибута itemData, а не ItemData. Если вы измените все ссылки packet3.ItemData на packet3.itemData, это должно работать нормально.

Смежные вопросы