我试图将类的实例保存到Python3.7中的字符串中。
我正在尝试这一点,因为我已经开始制作一个基于文本的游戏,它有一个世界协调和类实例字典(我遵循了本教程:https://letstalkdata.com/2014/08/how-to-write-a-text-adventure-in-python/),并且我想添加一个保存选项。如果你只是酸洗世界的字典,它说在内存中的房间在哪里,这不是很有帮助。但是,我在某个地方读到了关于repr()和exec()的文章,现在我正在尝试使用它来保存和加载测试类的实例。但是,当我试图打印新创建的类实例时,它会给我一个RecursionError: maximum recursion depth exceeded。
import traceback
def change_char(s, p, r):
l = list(s)
l[p] = r
return "".join(l)
class Class:
def __init__(self, i1, i2, *i3):
(filename,line_number,function_name,text)=traceback.extract_stack()[-2]
self.name = text[:text.find('=')].strip()
self.i1 = i1
self.i2 = i2
self.i3 = []
for iv in i3:
self.i3.append(iv)
def l(self, l):
s = ''
i = 1
for e in l:
if i < len(l):
s = s + repr(e) + ", "
else:
s = s + repr(e)
i += 1
return s
@property
def print_vals(self):
print('i1 : {1}\ni2 : {2}\ni3 : {3}'.format(self.i1, self.i2, self.l(self.i3)))
def __repr__(self):
return '{0} = Class({1}, {2}, {3})'.format(self.name, repr(self.i1), repr(self.i2), self.l(self.i3))
@property
def save(self):
return repr(self)
def Classload(st):
name = st[:st.find('=')].strip()
exec('global '+name+'\n'+st)
exec('global '+name+'\n'+name+'.name = '+name)
c = Class(1, "str", "Hello", 'world!')
print(repr(c))
i = c.save
i = change_char(i, 0, 'i')
print(i)
Classload(i)
print(c)
print(i)
print(repr(c))
print(repr(i))我预计产出如下:
c = Class(1, 'str', 'Hello', 'world!')
i = Class(1, 'str', 'Hello', 'world!')
c = Class(1, 'str', 'Hello', 'world!')
i = Class(1, 'str', 'Hello', 'world!')
c = Class(1, 'str', 'Hello', 'world!')
i = Class(1, 'str', 'Hello', 'world!')但我明白:
c = Class(1, 'str', 'Hello', 'world!')
i = Class(1, 'str', 'Hello', 'world!')
c = Class(1, 'str', 'Hello', 'world!')
Traceback (most recent call last):
File "C:\Users\HP\Desktop\test.py", line 107, in <module>
print(i)
File "C:\Users\HP\Desktop\test.py", line 63, in __repr__
return '{0} = Class({1}, {2}, {3})'.format(self.name, repr(self.i1), repr(self.i2), self.l(self.i3))
File "C:\Users\HP\Desktop\test.py", line 63, in __repr__
return '{0} = Class({1}, {2}, {3})'.format(self.name, repr(self.i1), repr(self.i2), self.l(self.i3))
File "C:\Users\HP\Desktop\test.py", line 63, in __repr__
return '{0} = Class({1}, {2}, {3})'.format(self.name, repr(self.i1), repr(self.i2), self.l(self.i3))
[Previous line repeated 245 more times]
RecursionError: maximum recursion depth exceeded我该怎么解决这个问题?
发布于 2019-04-27 09:44:49
对象的名称是对象本身。如果打印执行的内容,则如下所示:
global i
i = Class(1, 'str', 'Hello', 'world!')
global i
i.name = i当您在I上调用repr时,它将尝试将i.name表示为一个字符串,但要将i.name (即i)转换为它在其上调用repr的字符串。然后repr将尝试将i.name.name (即i.name,即i)表示为字符串,.直到你超过了递归深度。
在您的类负载中,您更希望类似于
i.name = 'i'更笼统地说,使用repr和exec作为保存系统并不是一个好主意。这是非常挑剔的,基本上可以归结为重新设计,而不是被设计为机器可读的(而是人类可读的)和执行几乎从来不是正确的选择,任何事情。相反,您可以使用反/序列化器(即将python对象转换为字节和字节到python对象的代码),比如泡菜、json、protobuf或xml。我真的不明白你反对泡菜,因为它基本上是为你设计的。
发布于 2019-04-27 10:59:46
关于您在文档(https://docs.python.org/3.7/library/pickle.html#comparison-with-marshal)中对泡菜的评论,它说:
泡菜模块跟踪它已经序列化的对象,这样以后对同一个对象的引用就不会再被序列化了。
大概是为什么会有内存引用。只需做以下操作看起来非常容易:
if __name__ == '__main__':
import pickle
initial = Class(1, 'hello', 'world', '!')
dumped = pickle.dumps(initial)
returned = pickle.loads(dumped)
print(f'initial: {initial}')
print(f'returned: {returned}')
print(f'i1: {returned.i1}, i2: {returned.i2}, i3: {returned.i3}')
# initial: Class(1, 'hello', 'world', '!')
# returned: Class(1, 'hello', 'world', '!')
# i1: 1, i2: hello, i3: ['world', '!']注意,我还删除了类名的代码中的位元,这就是为什么printout有点不同的原因。
https://stackoverflow.com/questions/55878850
复制相似问题