2011-08-16 47 views
1

我正在Python中使用一个Email()类,我想扩展到一个SerializeEmail()类,该类简单地添加了两个其他方法,.write_email()和.read_email()。我想这样的行为:使用Python“json”模块创建一个可串行化的类

# define email 
my_email = SerializeEmail() 
my_email.recipients = '[email protected]' 
my_email.subject = 'RE: Master sword' 
my_email.body = "Master using it and you can have this." 
# write email to file system for hand inspection 
my_email.write_email('my_email.txt') 
... 
# Another script reads in email 
my_verified_email = SerializeEmail() 
my_verified_email.read_email('my_email.txt') 
my_verified_email.send() 

我已经驾驶的JSON编码/解码的过程,我可以成功地写我SerializeEmail()对象,并在阅读它,但是,我无法找到一个满意的通过SerializeEmail.read_email()调用重新创建对象的方法。

class SerializeEmail(Email): 

    def write_email(self,file_name): 

     with open(file_name,"w") as f: 
      json.dump(self,f,cls=SerializeEmailJSONEncoder,sort_keys=True,indent=4) 

    def read_email(self,file_name): 

     with open(file_name,"r") as f: 
      json.load(f,cls=SerializeEmailJSONDecoder) 

这里的问题是,在我的read_email的json.load()调用()方法返回我SerializeEmail对象的实例,但不分配一个对象,我使用当前实例叫它。所以现在我不得不做这样的事情,

another_email = my_verified_email.read_email('my_email.txt') 

当我想要的是调用my_veridied_email.read_email()上的文件中的数据来填充my_verified_email的当前实例。我试过

self = json.load(f,cls=SerializeEmailJSONDecoder) 

但这并不起作用。我可以将我的返回对象的每个单独元素分配给我的“自我”对象,但这似乎是特设和不雅,我正在寻找“正确的方法”来做到这一点,如果它存在。有什么建议么?如果您认为我的整个方法有缺陷并推荐完成此任务的其他方式,请为我绘制出来。

回答

2

尽管您可以跳过一些环节以将序列化内容加载到现有实例中,但我不建议这样做。这是一个不必要的复杂功能,它确实让你一无所获;这意味着每次要从JSON加载电子邮件时都需要创建虚拟实例的额外步骤。我建议使用工厂类或工厂方法,从序列化的JSON中加载电子邮件并将其作为新实例返回。我个人的喜好而定了工厂方法,这你完成如下:

class SerializeEmail(Email): 

    def write_email(self,file_name): 

     with open(file_name,"w") as f: 
      json.dump(self,f,cls=SerializeEmailJSONEncoder,sort_keys=True,indent=4) 

    @staticmethod 
    def read_email(file_name): 

     with open(file_name,"r") as f: 
      return json.load(f,cls=SerializeEmailJSONDecoder) 

# You can now create a new instance by simply doing the following: 
new_email = SerializeEmail.read_email('my_email.txt') 

注意@staticmethod装饰,它允许你呼吁类中的方法,没有任何隐含的第一个参数的传递通常工厂方法将是@classmethod s,但是由于您从JSON加载对象,隐式类参数是不必要的。

请注意,通过此修改,您无需实例化SerializeEmail对象,然后您可以从JSON加载另一个对象。您只需在课堂上直接调用方法并获得所需的行为。