0

我将对类 Task 的调用存储在 .dat 文件的数组中。我想阅读这个文件并重建类调用。

这是我现在正在使用的课程:

class Task:

    def __init__(self, name, timespent):
        self.name = name
        self.timespent = timespent

    def __repr__(self):
        return repr('Task("%s",%s)'%(self.name, self.timespent))

这是从文件中读取的内容:

task_list = []
with open("task_list2.dat", "r") as file:
    task_list = eval(file.readline())

这是对文件的写入:

with open("task_list2.dat", "w") as outFile:
    print(repr(task_list), file = outFile)

这是文件的内容: ['Task("class",20)'] 其中“class”是任务的名称。

我知道问题与 'Task("class",20)' 周围的单引号有关,但我不知道如何摆脱它们。我收到的错误消息大致如下:“str object has no attribute 'name'”

如何删除这些引号,以便下次阅读文件时可以重建类?

4

1 回答 1

5

你真的,真的,真的不想尝试使用reprandeval作为序列化格式。

如果你只是使用,说,pickle你根本不会有这个问题:

with open("task_list2.dat", "wb") as outFile:
    pickle.dump(task_list, outFile)

with open("task_list2.dat", "rb") as file:
    task_list = pickle.load(file)

简单得多,是吗?


但是,如果您想知道如何解决眼前的问题而不是让它变得无关紧要:您的__repr__方法中有多个问题,如果您希望它可以往返,所有这些问题都需要解决。

  • 你生成一个字符串表示……然后调用repr它。您想要返回字符串表示,而不是字符串表示字符串表示。只需省略repr.
  • 您应该始终委托给repr子对象,而不是str. 如果您使用%-formatting,这意味着使用%r而不是%s.
  • 不要尝试在事物周围添加引号。如果对象本身没有引号、反斜杠、不可见字符等,这可能会起作用,但为什么要依赖它呢?如果你认为你需要引号,这几乎总是表明你违反了以前的规则,你应该改正它。

以下是如何为此类编写可往返的 repr:

def __repr__(self):
    return 'Task(%r, %r)' % (self.name, self.timespent))

您可以验证它是否符合您的要求:

>>> t = Task('task name', 23.4)
>>> t
Task('task name', 23.4)
>>> eval(repr(t))
Task('task name', 23.4)

当然,在您的特定示例中,仅解决第一个问题(删除对 的虚假调用repr)就可以摆脱单引号并使该特定示例正常工作。eval您也可以通过调用两次来解决读取方面的问题。或者,对于这个特定的例子,甚至通过调用eval(s[1:-1])or eval(s.strip("'"))。但是,任何这样的“修复”只会使调试您遇到的一般问题变得更加困难,例如,一个不像单个全 ASCII 字母单词那么简单的名称。

于 2013-11-07T00:11:19.143 回答