Python:__subclasses__ 顺序

标签 python subclass

我有一些代码通过在基类上调用 __subclasses__() 函数来创建子类(的实例)列表。

subclasses = [subclass() for subsclass in BaseClass.__subclasses__()]

在 Python 2.7 中,此列表中子类的顺序始终等于我代码中导入语句的顺序(每个子类都在其自己的 Python 文件中定义)。但在 Python 3.5 中,此列表中子类的顺序似乎是随机的。我可以使用某种变通方法在 Python 3.5 中获得相同的行为吗?

参见 class.__subclasses__ documentation .

最佳答案

在 Python 3.5 中,没有任何微不足道的方法。 As of Python 3.4 tp_subclasses 数据结构通过字典跟踪子类(将子类的 id() 值映射到弱引用,请参阅 Python issue #17936 了解原因)。字典是无序的。

在 Python 3.6 中,字典的内部实现发生了变化,它们现在跟踪插入顺序。当您升级到 Python 3.6 时,您将再次按插入顺序(Python 首次看到它们的顺序)获取子类。

但是,在字典中跟踪子类这一事实是一个实现细节,不应真正依赖。

您可以通过其他方式跟踪订单。你可以给你的基类一个按顺序记录子类的元类,例如:

from itertools import count
from weakref import WeakKeyDictionary

class SubclassesInOrderMeta(type):
    _subclass_order = WeakKeyDictionary()
    _counter = count()

    def __ordered_subclasses__(cls):
        # sort subclasses by their 'seen' order; the sort key
        # puts classes that are missing from the _subclass_order
        # mapping at the end, defensively.
        order_get = type(cls)._subclass_order.get
        sort_key = lambda c: order_get(c, float('inf'))
        return sorted(cls.__subclasses__(), key=sort_key)

    def __new__(mcls, *args, **kwargs):
        cls = super(SubclassesInOrderMeta, mcls).__new__(mcls, *args, **kwargs)
        mcls._subclass_order[cls] = next(mcls._counter)
        return cls

关于Python:__subclasses__ 顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51233073/

相关文章:

python - 如何从 __subclasses__ 中删除类?

python - 将一个字典的键替换为另一个字典的值以创建一个新字典

objective-c - 子类中的 NSNotificationCenter addObserver

objective-c - Obj-C 子类似乎无法识别继承的选择器

ios - 是否存在与 Swift 的 fatalError 等效的 Objective-C?

c# - 从控件子类化 ParentForm WndProc

python - matplotlib.pyplot.axvline 使用 axvline 函数时未出现标签

python - float 对象没有属性 __getitem__

Python:如何在 float 中打印 100.0 而不是 100

python - Django - Social Auth(请求 URL 显示 http 而不是 https)