python - 在python中动态将dict转换为类

标签 python json mongodb dictionary casting

我知道以前已经回答过类似的问题,但在花了几个小时浏览网页后,我仍然无法找到解决我的问题的正确解决方案(或“python-way”解决方案)

我正在使用以下“数据库”模块将任何对象插入 MongoDB:

from pymongo import MongoClient
import json

def insert(obj, collection_name):
    with MongoClient(27017, 'localhost') as client:
        if hasattr(obj, '__dict__'):
            doc = obj.__dict__
        else:
            doc = json.dumps(obj)
        return client['test'][collection_name].insert_one(doc).inserted_id

def get_one(collection_name, query):
    with MongoClient(27017, 'localhost') as client:
        return client['test'][collection_name].find_one(query)

这部分工作得很好,因为我可以处理任何模块中的任何类并以通用方式存储对象。

我面临的问题是从 MongoDB 重新加载对象并将其转换回正确的类。

我有一个通用类“操作”(表示可以对银行/货币帐户执行的操作:

import database 

class Operation(object):
    def __init__(self):
        self._id = 'OPE-{}'.format(str(uuid.uuid1()))

    @property
    def id(self):
        return self._id

    def save(self):
        database.update(self, 'operations')

def create_from_dict(d):
    operation = Operation()
    for key, value in d.items():
        operation.__dict__[key] = value
    return operation

def get(operation_id):
    return create_from_dict(database.get_one('operations', {'_id': operation_id}))

直到此时一切正常,我可以实例化任何操作对象,将其插入 MongoDB 并使用它的 id 将其加载回来。

现在我有两个从“Operation”派生的新类“Fee”和“Credit”

import uuid
from operation import Operation

class Credit(Operation):
    def __init__(self):
        Operation.__init__(self)
        self._id = 'CRE-{}'.format(uuid.uuid1())

    @property
    def id(self):
        return self._id

还有

import uuid
from operation import Operation

class Fee(Operation):
    def __init__(self):
        Operation.__init__(self)
        self._id = 'FEE-{}'.format(uuid.uuid1())

    @property
    def id(self):
        return self._id

这个想法是保留在“Operation”类中保存/加载对象的代码,并在需要时创建简单的派生类。 因此,“Operation”类应该能够将加载的对象从“Operation”动态转换为“Credit/Fee/Transfer”...

我尝试做的是在所有类上添加以下行以存储对象类型:

self.type = self.__class__

或者(因为类不能直接序列化为json)

self.type = self.__name__

但我不知道如何实现:

def create_from_dict(d):
    operation = Operation()
    for key, value in d.items():
        operation.__dict__[key] = value
    operation.__class__ = get_type_from_name(operation.type) #This is the function I'm trying to implement
    return operation

在编码对象以从另一个模块将其转换回来时,我是否应该存储模块和类名?

很抱歉问了一个很长的问题,但我想完整地描述我的代码背后的逻辑 我绝对愿意接受任何建议!

编辑: locals() 或 globals() 可以作为选择吗?您将类名传递给 get_type_from_name() 方法,它会返回相应的类? 对于高级 Python 专家来说,还有一个问题:这是正确的方法吗?

最佳答案

使用您建议的 self.type = self.__name__ 想法,您可以尝试对 get_type_from_name 函数进行此实现:

def get_type_from_name(name):
    name_to_type = {'Credit': Credit, 'Fee':Fee}
    return name_to_type[name]

不过,我不太确定我是否完全理解您的问题,所以如果这不是您想要的,请告诉我。

关于python - 在python中动态将dict转换为类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40494438/

相关文章:

python - 相关模型字段未显示

javascript - 超链接在新文档窗口中返回 JSON。我希望它返回到像 "response"这样的变量

python - 在Python中从文件中读取数字,忽略b'

python - 如何使用带有日期的plotly graph_objects scatter

python - Nginx 的工作进程挂起并占用完整的 CPU

php - 在 Composer 为存储库设置名称

json - Aeson 和 Lens 与 DeriveGeneric 和 makeLenses - 名称不对齐

node.js - 使用 MongoDB 更新插入

mongodb - 如何更改 MongoDB 用户的密码?

mongodb - 在使用MongoDB-mgo插入许多文档的同时,如何忽略重复的键错误并继续插入?