添加用于继承的动态类和类名的映射

add dynamic class for inheritance and mapping for class name

提问人:Zeus 提问时间:10/22/2023 更新时间:10/22/2023 访问量:51

问:

我正在做一个 Python 项目,其中我有两个不同的对象文档映射器 (ODM),Beanie 和 Bunnet,用于管理数据库中的数据。每个 ODM 都需要不同的类结构来定义数据模型。

我有两个单独的 User 模型类,User_B1 用于 Bunnet 和 User_B2 用于 Beanie,它们都继承自各自 ODM 的基本文档类。

现在,我正在构建一个 Database 类,该类根据用户在运行时选择的 ODM 动态选择适当的 User 类。我目前正在使用字典(映射)将类名映射到其对应的类,并使用调用方法根据其名称返回所需的类实例。

class User_B1(UserModel, BunnetDocument):
    class Settings:
        name = "user"

class User_B2(UserModel, BeanieDocument):
    class Settings:
        name = "user"

class Database:
    def __init__(self, odm_name: str):
        if odm_name == "bunnet":
            self.User = User_B1
        elif odm_name == "beanie":
            self.User = User_B2
        else:
            raise ValueError("Invalid ODM name")

    def __call__(self, class_name: str) -> Any:
        mapping = {"User": self.User}
        return mapping[class_name]

if __name__ == "__main__":
    db = Database("bunnet")
    user = db.User
    user = db("User") 
    obj_1 = user(
        username="ali2",
        password="Addsasad12365",
        name="ali",
        family="ali",
        email="[email protected]",
    )
    obj_1.insert()

但是,我正在寻找一种更简洁、更动态的方式来实现 Database 类,而无需使用静态映射字典。有没有办法根据提供的类名动态返回适当的类,也许是通过检查数据库实例中的可用类或使用其他一些 Python 方法?

此外,我想知道是否有更好的方法来管理用户类选择,这样我就不需要单独的User_B1类和User_B2类,而是可以根据用户的 ODM 选择动态切换用户的父类。这是否可行,或者我是否需要为每个 ODM 维护单独的类?

python 继承 abstract-class abstract

评论


答:

0赞 Tusher 10/22/2023 #1

根据提供的类名动态返回相应的类,您可以使用内置的 getattr() 函数从模块命名空间中获取类对象。

class Database:
    def __init__(self, odm_name: str):
        if odm_name == "bunnet":
            self.module = "bunnet_module"
        elif odm_name == "beanie":
            self.module = "beanie_module"
        else:
            raise ValueError("Invalid ODM name")

    def __call__(self, class_name: str) -> Any:
        module = importlib.import_module(self.module)
        return getattr(module, class_name)

用户类选择的管理允许根据用户的 ODM 选择动态切换用户的父类。一种方法是建立包含通用属性和函数的基本 User 类,然后定义从基 User 类和相应的 ODM 的基文档类继承的单个 ODM 子类。下面介绍如何更改 User 类以利用基 User 类:

class User(UserModel):
    class Settings:
        name = "user"

    def common_method(self):
        pass

class User_B1(User, BunnetDocument):
    pass

class User_B2(User, BeanieDocument):
    pass