我可以使用 python 元类来跟踪单独文件中的子类吗?

Posted

技术标签:

【中文标题】我可以使用 python 元类来跟踪单独文件中的子类吗?【英文标题】:Can I use a python metaclass to keep track of subclasses in separate files? 【发布时间】:2015-01-06 03:35:24 【问题描述】:

我是社区的新手。在我的 Django 项目中,我有一个名为“social”的模块,其中有几个文件,如 facebook.py 和 twitter.py,每个文件的类都是“SocialProvider”的子类

例子

class Facebook(SocialProvider):

在我的社交模块中还有一个名为“helper.py”的文件,其中包含一个 SocialProviderHelper,我想跟踪所有 SocialProvider 子类,并为它们生成不同的列表和标识符。例如.. SocialProviderHelper 可以“找到” Facebook 和 Twitter,并将它们添加到各种列表中,例如 cool_providers = [] popular_providers = [] old_providers 等。目标是制作一个通用的 SocialProviderHelper,其他领域的代码可以导入和使用......例如......在一个视图中我可能想要获取所有“popular_providers”名称......所以我会导入 SocialProviderHelper.. 并执行类似

的操作
helper = SocialProviderHelper()
helper.getOldProviders()

在我的 SocialProviderHelper 中,我有:

class SocialProviderHelper(object):
    _providers = SocialProvider.__subclasses__()

但是 子类() 似乎返回一个空列表,因为“提供者”是在尚未导入的其他文件中定义的,并且 subclasses() 仅在它们“活动”时维护对该类的弱引用。

有没有办法解决这个问题?

**最终目标是能够在任何地方创建另一个 SocialProvider 子类,只需这样做......

import SocialProvider
    class NewSocialNetwork(SocialProvider)

...让 SocialProviderHelper 知道它的存在。**

我尝试使用保留子类注册表的元类来实现“subclasses(),但类似的问题仍然存在。

【问题讨论】:

【参考方案1】:

这可以通过装饰器来完成:

from SocialProvider import SocialProvider

@SocialProvider.Register
class NewSocialProvider( SocialProvider ):
    pass

我假设SocialProvider 是您编写的超类。如果是这样,在您的超类文件中,Register 帮助器可以定义为类方法:

class SocialProvider:

    subclasses = []
    @classmethod
    def Register( cls, subcl ):
        cls.subclasses.append( subcl )
        return subcl

如果不是,那么您仍然可以在某个地方定义一个函数,用作装饰器,但它和它附加到的列表必须在其他地方定义,与SocialProvider 类分开。您提到了尚未导入文件的问题。您无法检测尚未定义的类,因此您必须确保已导入具有子类定义的文件 (例如,通过 import facebook 等语句在模块的___init__.py 文件中)。

【讨论】:

我没有足够的声誉来支持您的答案,但非常感谢!我会试试这个! 很高兴听到它有用。如果事实证明可以解决您的问题,您可以通过单击至少与赞成票一样好的勾选标记来“接受”它。

以上是关于我可以使用 python 元类来跟踪单独文件中的子类吗?的主要内容,如果未能解决你的问题,请参考以下文章

Python 子类跟踪 - 元类与内置

Python利用元类来控制实例创建

Python 元类与类装饰器

使用 python 元类和继承的问题

使用元类动态设置属性

通过元类来控制类的产生