首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在调用对象时修复'RecursionError:最大递归深度超过‘?

如何在调用对象时修复'RecursionError:最大递归深度超过‘?
EN

Stack Overflow用户
提问于 2019-04-27 08:54:49
回答 2查看 3.2K关注 0票数 0

我试图将类的实例保存到Python3.7中的字符串中。

我正在尝试这一点,因为我已经开始制作一个基于文本的游戏,它有一个世界协调和类实例字典(我遵循了本教程:https://letstalkdata.com/2014/08/how-to-write-a-text-adventure-in-python/),并且我想添加一个保存选项。如果你只是酸洗世界的字典,它说在内存中的房间在哪里,这不是很有帮助。但是,我在某个地方读到了关于repr()exec()的文章,现在我正在尝试使用它来保存和加载测试类的实例。但是,当我试图打印新创建的类实例时,它会给我一个RecursionError: maximum recursion depth exceeded

代码语言:javascript
复制
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))

我预计产出如下:

代码语言:javascript
复制
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!')

但我明白:

代码语言:javascript
复制
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

我该怎么解决这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-27 09:44:49

对象的名称是对象本身。如果打印执行的内容,则如下所示:

代码语言:javascript
复制
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)表示为字符串,.直到你超过了递归深度。

在您的类负载中,您更希望类似于

代码语言:javascript
复制
i.name = 'i'

更笼统地说,使用repr和exec作为保存系统并不是一个好主意。这是非常挑剔的,基本上可以归结为重新设计,而不是被设计为机器可读的(而是人类可读的)和执行几乎从来不是正确的选择,任何事情。相反,您可以使用反/序列化器(即将python对象转换为字节和字节到python对象的代码),比如泡菜、json、protobuf或xml。我真的不明白你反对泡菜,因为它基本上是为你设计的。

票数 2
EN

Stack Overflow用户

发布于 2019-04-27 10:59:46

关于您在文档(https://docs.python.org/3.7/library/pickle.html#comparison-with-marshal)中对泡菜的评论,它说:

泡菜模块跟踪它已经序列化的对象,这样以后对同一个对象的引用就不会再被序列化了。

大概是为什么会有内存引用。只需做以下操作看起来非常容易:

代码语言:javascript
复制
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有点不同的原因。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55878850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档