Python: __subclasses__ 订单
Python: __subclasses__ order
我有一些代码可以通过在基础 class.
上调用 __subclasses__()
函数来创建子 classes(的实例)列表
subclasses = [subclass() for subsclass in BaseClass.__subclasses__()]
在Python 2.7 中,此列表中子class 的顺序始终等于我的代码中导入语句的顺序(每个子class 定义在它有自己的 Python 文件)。但在 Python 3.5 中,此列表中子 classes 的顺序似乎是随机的。我可以使用某种解决方法在 Python 3.5 中获得相同的行为吗?
在Python 3.5 中,没有任何微不足道的方法。 As of Python 3.4 the tp_subclasses
data structure tracks subclasses via a dictionary (mapping the id()
value of the subclass to a weak reference, see Python issue #17936 为什么)。字典是无序的。
在 Python 3.6 中,字典的内部实现发生了变化,它们现在跟踪插入顺序。当您升级到 Python 3.6 时,您将再次按插入顺序(Python 首次看到它们的顺序)获得子classes。
然而,subclasses 在字典中被跟踪的事实是一个实现细节,不应真正依赖。
您可以通过其他方式跟踪订单。你可以给你的基础 class 一个 metaclass 来记录 subclass 的顺序,例如:
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
我有一些代码可以通过在基础 class.
上调用__subclasses__()
函数来创建子 classes(的实例)列表
subclasses = [subclass() for subsclass in BaseClass.__subclasses__()]
在Python 2.7 中,此列表中子class 的顺序始终等于我的代码中导入语句的顺序(每个子class 定义在它有自己的 Python 文件)。但在 Python 3.5 中,此列表中子 classes 的顺序似乎是随机的。我可以使用某种解决方法在 Python 3.5 中获得相同的行为吗?
在Python 3.5 中,没有任何微不足道的方法。 As of Python 3.4 the tp_subclasses
data structure tracks subclasses via a dictionary (mapping the id()
value of the subclass to a weak reference, see Python issue #17936 为什么)。字典是无序的。
在 Python 3.6 中,字典的内部实现发生了变化,它们现在跟踪插入顺序。当您升级到 Python 3.6 时,您将再次按插入顺序(Python 首次看到它们的顺序)获得子classes。
然而,subclasses 在字典中被跟踪的事实是一个实现细节,不应真正依赖。
您可以通过其他方式跟踪订单。你可以给你的基础 class 一个 metaclass 来记录 subclass 的顺序,例如:
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