__dict__ 不允许在 Python 中调用方法

Posted

技术标签:

【中文标题】__dict__ 不允许在 Python 中调用方法【英文标题】:__dict__ Doesn't Allow Call to Method in Python 【发布时间】:2016-07-12 20:52:54 【问题描述】:

我正在创建一个对象字典,我想保存并在不同时间重新加载(我想使用“json”模块,而不是“pickle”)。

我创建了一个类(我们称它为“Ball”),而字典只包含该类的许多不同实例。它的样子是:

my_dict = 
            "ball1": "size": "big", "baseball": False, etc...,
            "ball2": "size": "small", "baseball": True, etc...,
             etc...
          

当我创建“Ball”类的新实例时,我只是将它们附加到“my_dict”。

我的“Ball”类具有允许我更改某些字段值的方法...即:

changeSize(self, size)

问题:

为了让我的保存功能能够正常使用 json 模块,我必须对“Ball”类的每个新实例执行以下操作:

newBall = Ball(name)
my_dict[name] = newBall.__dict__

添加

.__dict__

然后将其附加到字典使其 JSON 可序列化,但它使当我进入“编辑模式”时我无法调用该方法(即 changeSize(name) ),因为它只是一个字典不再是“球”对象。

如何制作以便我可以保存(使用 json 模块)并使用我现有的方法进行编辑?

另外,我保存/加载的方式如下:

out_file = open("testSave.json"), "w")
json.dump(my_dict, out_file, indent=4)
out_file.close()

in_file = open("testSave.json", "r")
my_dict = json.load(in_file)
in_file.close()

谢谢!

【问题讨论】:

【参考方案1】:

最终,json 不支持序列化任意 python 对象。如果你想这样做,你可以看看pickle

或者,您可以在 Ball 上创建一个备用构造函数,该构造函数将使用来自 dict 的值对其进行初始化:

class Ball(object):

    @classmethod
    def from_json(self, dictionary):
        b = cls()
        b.__dict__.update(dictionary)
        return b

    ...

我写这个假设Ball构造函数可以用0参数调用——如果不是这样,或者__init__做了任何“花哨”的事情,你可能需要修改代码(除了设置json 可序列化属性)。解决__init__ 参数要求的一种方法是使用__new__ 创建实例,然后通过更新类字典来填充成员:

class Ball(object):
    def __init__(self, name, foo, bar):
        self.name = name
        self.foo = foo
        self.bar = bar

    def to_dict(self):
        return self.__dict__

    @classmethod
    def from_dict(cls, dictionary):
        self = cls.__new__(cls)
        self.__dict__.update(dictionary)
        return self

    def __str__(self):
        return 'Ball(%r, %r, %r)' % (self.name, self.foo, self.bar)


b = Ball('HockyPuck', 'flat', 'NotABall')
d = b.to_dict()
bb = Ball.from_dict(d)

print(bb)

这适用于 python2.x 和 3.x。

【讨论】:

Ball 构造函数至少需要一个名称(但它会在程序中提示,因此保证会发生)。你是说如果我基本上做了与pickle 相同的事情,它会起作用吗?我知道它不太安全,这就是我尝试学习 json 方式的原因。另外,如果我继续使用json,您能否快速解释一下您为什么使用decorator?我对他们不是很了解。非常感谢! @AmericanMade -- 你也可以使用b = cls(dictionary.get('name')) 或类似的方法。回复:pickle——那里肯定存在安全问题。如果你不完全信任它,就永远不要解开它。至于@classmethod,这只是使得from_jsoncls中的@是而不是类的实例。

以上是关于__dict__ 不允许在 Python 中调用方法的主要内容,如果未能解决你的问题,请参考以下文章

Python - 追加到嵌套在 dict 子类中的列表

Python魔术方法

Python 的 enum 模块源码分析

错误“NoneType”对象没有属性“__dict__”

Python学习————反射

python遍历并获取对象属性--dir(),__dict__,getattr,setattr