在python中使用元类导入其他类中的模块

2024-10-04 09:28:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要创建一个业务查询模型,在这个模型中我需要创建一个循环依赖,我正在使用一个类似django模型的设计来实现它

#Modeule a.py

import b
class A:
    b_obj = B()
    a_property_1 = ObjectAttribute(b_obj.b_property_1) # a_property_1 is dependent on b_property_1
    a_property_2 = ObjectAttribute(b_obj.b_property_2)


#Module b.py

import a
class B:
        a_obj = A()
        b_property_1 = ObjectAttribute(a_obj.a_property_1)
        b_property_2 = ObjectAttribute(a_obj.a_property_2)

当我执行上面的程序时,它会抛出一个错误,在执行a.py和viceversa时没有定义名称“B”。你知道吗

在那之后,我对此做了一些研究,发现django模型已经通过ForeignKey实现了类似的东西

https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey

所有我需要实现我的ForeignKey模块,有人能帮我理解逻辑和编写以下格式的代码。你知道吗

#Modeule a.py

import b
class A:
    b_obj = MyForeignKey('B')
    a_property_1 = ObjectAttribute(b_obj.b_property_1) # a_property_1 is dependent on b_property_1
    a_property_2 = ObjectAttribute(b_obj.b_property_2)


#Module b.py

import a
class B:
        a_obj = MyForeignKey('A')
        b_property_1 = ObjectAttribute(a_obj.a_property_1)
        b_property_2 = ObjectAttribute(a_obj.a_property_2)

Tags: djangopy模型importobjisonproperty
1条回答
网友
1楼 · 发布于 2024-10-04 09:28:42

有一些方法可以做到这一点。其中之一是将外键作为实际类的代理类,在实例化时,只需注释类模型,对于下一个后续属性访问,只需实例化代理到类并保留其引用,后续属性就可以重定向到基础类。你知道吗

允许在属性fect上执行此类钩子的一种机制是实现__getattribute__方法(请记住,在Pyhton中,类“method”只是一个可调用的属性,因此它也适用于方法)。你知道吗

假设您有一个“模型”模块(或其他类型的注册表),当您的所有模型都被引用时,在创建之后,您的代码可能或多或少像这样:

import models

class MyForeignKey(objec):
    def __init__(self, model_name, *args, **kw):
        self._model_name = model_name
        self._args = args
        self._kw = kw

    def _instantiate(self):
        self._object = getattr(models, self._model_name)(*self._args, **self._kw)

    def __getattribute__(self, attr):
        if attr in ("_model_name", "_args", "_kw", "_object", "_instantiate"):
            return object.__getattribute__(self, attr)
        if not hasattr(self, "_object"):
            self._instantiate()
        return getattr(self._object, attr)

    def __setattr__(self, attr, value):
        if attr in ("_model_name", "_args", "_kw", "_object"):
            return object.__setattr__(self, attr, value)
        if not hasattr(self, "_object"):
            self._instantiate()
        return setattr(self._object, attr, value)

请注意,(a)您的模型必须从“object”继承,就像我在问题中评论的那样,(b)如果您实现“dunder”方法(python双下划线方法)来覆盖任何模型上的行为,则这是不完整的-在这种情况下,您必须设置适当的te dunder方法来执行代理。你知道吗

相关问题 更多 >