python - Python:__subclasses__ 顺序
问题描述
我有一些代码通过调用__subclasses__()
基类上的函数来创建子类(实例)的列表。
subclasses = [subclass() for subsclass in BaseClass.__subclasses__()]
在 Python 2.7 中,此列表中子类的顺序始终等于我的代码中导入语句的顺序(每个子类都在其自己的 Python 文件中定义)。但在 Python 3.5 中,这个列表中子类的顺序似乎是随机的。我可以使用某种解决方法在 Python 3.5 中获得相同的行为吗?
解决方案
在 Python 3.5 中,没有,没有任何微不足道的方法。从 Python 3.4 开始,tp_subclasses
数据结构通过字典跟踪子类(将id()
子类的值映射到弱引用,请参阅Python 问题 #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
推荐阅读
- c++ - 如何在 C++ 中修复这个金字塔模式?
- java - 有很多 @Service 方法来检查一个 id 是否有一些结果
- php - 无法使用 SQL Server 在 Datatables 服务器端使用 order 和 limit
- photoshop - Extendscript 与 Photoshop:导入图像
- google-app-engine - GCS - 基于端口的拆分流量(GAE 和存储之间)
- hashtable - 不同图像的校验和相同
- python - Python Selenium Firefox 自定义配置文件保存
- reactjs - 如何在 React 应用程序中正确加载和使用 API?
- python - 在 Cartopy,Robinson 投影中绘制一条直线
- python - 在数据框中创建一个新列