找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 490|回复: 0

[经验] “如何将renpy.revertable.RevertableDict转化为默认dict格式”的解决办法

[复制链接]
发表于 2025-3-13 20:41:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 烈林凤 于 2025-3-15 13:43 编辑

本篇教程中的转化方法首先是由@Koji233 (科基)提出的,我只是在此基础上做了延伸和解释,本篇教程也只是为了留档,防止以后还有和我一样的人不知道怎么办(但其实解法挺简单的)

(前面部分会说明原理,后面的部分会直接展示转化函数的写法,但还是建议先搞懂原理)
这篇教程问题的起因,是因为我在做类王权小游戏时,发现读取json获取到的dict无法通过type()在界面中正确判断其为dict格式,之后也在init python尝试过,发现一样无法正确判断
其格式如下,data便是通过with open后通过json.load()获取到的dict:
[RenPy] 纯文本查看 复制代码
            if type(data) == dict:
                print(type(data))

通过这种方法,并没有办法在控制台中看到print出的data的类型
然后我们直接打印一下type(data)
>>> <class 'dict'>
会发现其格式为dict
但是,不对啊?为什么明明通过type()判断其是否为dict格式,却没有通过判断呢?而它明明应该是dict格式才对
让我们打印一下type({'a':1})试试看
>>> <class 'renpy.revertable.RevertableDict'>
我们会发现,其格式并非我们所熟知的python中的dict格式
然后我们再尝试通过type方法判断其是否为dict格式:
[RenPy] 纯文本查看 复制代码
            if type({'a':1}) == dict:
                print(type({'a':1}))

可以发现,成功将其判断为了dict格式,并打印出了<class 'renpy.revertable.RevertableDict'>

这究竟是什么原理呢?这就得翻开我们的renpy文档了(这部分文档是@ZYKsslm 找到的)
存档、读档和回滚 — Ren'Py 中文文档
回滚操作的作用范围包括,初始化阶段之后还可以改变的变量,以及通过那些变量访问的可恢复的对象。 粗略来说,就是在Ren’Py脚本中定义并创建的类的实例,比如列表、字典和集合。 在Python和Ren’Py中内部创建的数据通常都是不可恢复的。

进一步来看,在Ren’Py脚本运行时,脚本内部的Python存储区中对象,包括列表、字典和集合类型都会替换为可恢复的类型。 从以上类派生的类型也是可恢复的。renpy.Displayable 派生的类也是可恢复的类。

为了使可恢复的对象使用起来更便利,Ren’Py会对脚本中找到的Python语句做如下修改:

原生的列表、字典和集合会自动转为可恢复的等效对象。

包含在其他语句中的列表、字典和集合也会自动转为可恢复的等效对象。

其他Python语法中,类似解包之类的操作,会创建列表、字典和集合的部分也会转为可恢复的等效对象。 但是,函数和方法中带两个星号的入参(即根据额外关键词入参创建字典)并不会转为可恢复的对象。

不显示从其他任意类型派生的类,会自动从可恢复对象的类型派生。

除此之外:

可恢复类型的方法和操作中产生的列表、字典和集合类型会修改可恢复对象。

内建函数如果返回列表、字典和集合的,都会返回可恢复的等效对象。

直接调用Python代码一般都不会生成可恢复对象。 某些情况下,获得的对象可能不会参与回滚:

调用内建类型的方法,比如 str.split 方法。

使用导入的Python模块创建的对象,返回给Ren’Py。 (例如,collections.defaultdict的实例不参与回滚。)

Ren’Py的API返回的对象,除非文档另有说明。

通过文档我们可以得知,renpy为了方便数据回滚和恢复,为部分格式创建了特殊的类,其中就比如dict和list,如果是在renpy内创建的,其格式便会分别为renpy.revertable.RevertableDict和renpy.revertable.RevertableList,而如果是通过python创建的,便会为原先的格式,分别为dict和list
相应的,renpy的部分函数也与原先不同,其中包括type()和isinstance(),两者原先所指代dict和list会被替换为renpy.revertable.RevertableDict和renpy.revertable.RevertableList,由python创建的dict和list是无法正确通过判断的

也就是意味着,我所使用json库通过python创建的data字典,renpy并没有将其和其内部转化为属于renpy的特殊格式,才导致了bug的出现

解决方法很简单,就是通过转化函数(递归)将其和其内容手动转化为renpy的特殊格式就好了
*以下内容仅为我在我自己的类中的函数所撰写的,请以实际需要自行修改
[RenPy] 纯文本查看 复制代码
    from builtins import dict as real_dict
    from builtins import list as real_list

        ## 读取json后,转化dict格式
        def trans_dict(self, old):
            new_dict = renpy.revertable.RevertableDict()
            for key, value in old.items():
                if type(value) == real_dict:
                    new_dict[key] = self.trans_dict(value)
                elif type(value) == real_list:
                    new_dict[key] = self.trans_list(value)
                else:
                    new_dict[key] = value
            return new_dict
        
        ## 读取json后,转化list格式
        def trans_list(self, old):
            new_list = renpy.revertable.RevertableList()
            for item in old:
                new_list.append(item)
            return new_list

使用import调用py的基础库dict和list,之后在函数内判断其是否为py基础库内的类型,如果是则用dict()或list()格式化为rp格式的dict和list,之后就是递归,不断地将字典内部的所有dict和list都格式化
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|RenPy中文空间 ( 苏ICP备17067825号|苏公网安备 32092302000068号 )

GMT+8, 2025-5-1 13:58 , Processed in 0.055403 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表