【问题标题】:Import modules in each other class in python using metaclass使用元类在python中的每个其他类中导入模块
【发布时间】:2014-10-29 12:13:04
【问题描述】:

我需要创建一个业务查询模型,我需要在其中创建一个循环依赖,我正在使用一个看起来像 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)

当我执行上述程序时,它会抛出一个错误,名称'B'在执行a.py时没有定义,反之亦然。

之后,我对此进行了一些研究,以找出 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)

【问题讨论】:

  • 附注:在 Python 2 中总是从“object”继承——你的类继承了“nothng”的形式(如class A:)——在 Python 2 中,这会产生不实现的旧式类一些现代的属性获取机制,以及其他可能会让您大吃一惊的不兼容性。

标签: python django metaclass


【解决方案1】:

有一些方法可以做到这一点。其中之一是将您的外键作为实际类的代理类,在实例化时,只需注释类模型,然后下一个后续属性访问实例化代理类,并保留其引用,后续属性只会被重定向到底层类。

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

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

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)您的模型必须像我在问题中评论的那样从“对象”继承,以及(b) - 如果您实现“dunder”方法(python 双下划线方法)以覆盖任何行为模型 - 在这种情况下,您还必须设置适当的 te dunder 方法来执行代理。

【讨论】:

    猜你喜欢
    • 2016-02-17
    • 1970-01-01
    • 2011-10-15
    • 2019-02-04
    • 1970-01-01
    • 2021-06-09
    • 2019-07-18
    • 2017-08-10
    • 2020-07-23
    相关资源
    最近更新 更多