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)'] 「クラス」はタスクの名前です。

問題は 'Task("class",20)' を囲む一重引用符に関係していることは理解していますが、それらを取り除く方法はわかりません。私が得るエラーメッセージは、「strオブジェクトには属性 'name'がありません」という行に沿って何かを言います

次回ファイルを読み取るときにクラスを再構築できるように、これらの引用符を削除するにはどうすればよいですか?

4

1 に答える 1

5

あなたは本当に、本当に、シリアライゼーション形式としてreprandを使用したくありません。eval

たとえば、を使用した場合、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)、一重引用符が取り除かれ、その特定の例が機能するようになります。eval2回呼び出すことで、読み取り側でそれを回避することもできます。または、この特定の例では、eval(s[1:-1])orを呼び出すことによってもeval(s.strip("'")). しかし、そのような「修正」は、たとえば、単一のすべて ASCII 文字の単語ほど単純ではない名前を使用した場合に遭遇する一般的な問題のデバッグを難しくするだけです。

于 2013-11-07T00:11:19.143 に答える