Python 按对象排序';s型

Python 按对象排序';s型,python,sorting,Python,Sorting,我的代码在模块加载时静态地注册(类型,处理程序\函数)对,从而产生如下dict: HANDLERS = { str: HandleStr, int: HandleInt, ParentClass: HandleCustomParent, ChildClass: HandleCustomChild } def HandleObject(obj): for data_type in sorted(HANDLERS.keys(), ???): if isinstanc

我的代码在模块加载时静态地注册
(类型,处理程序\函数)
对,从而产生如下dict:

HANDLERS = {
  str: HandleStr,
  int: HandleInt,
  ParentClass: HandleCustomParent,
  ChildClass: HandleCustomChild
  }

def HandleObject(obj):
  for data_type in sorted(HANDLERS.keys(), ???):
    if isinstance(obj, data_type):
      HANDLERS[data_type](obj)
其中
ChildClass
继承自
ParentClass
。问题是,因为它是一个dict,所以顺序没有定义——但是我如何内省类型对象来找出排序键呢


生成的顺序应该是子类,然后是超类(首先是大多数特定类型)。例如,
str
位于
basestring
之前,
ChildClass
位于
ParentClass
之前。如果类型是不相关的,那么它们之间的相对位置就无关紧要了。

对每个类的
\uuuuuuuuuuuu>成员进行分析。

对每个类的
\uuuuuuuuuuu>成员进行分析。

如果您知道自己总是在处理新样式的类:

def numberofancestors(klass):
    return len(klass.mro())
或者,如果您担心组合中可能会有老式的类:

import inspect

def numberofancestors(klass):
    return len(inspect.getmro(klass))
然后,不管是哪种情况

sorted(HANDLERS, key=numberofancestors, reversed=True)
将提供您所需的(您不需要
.keys()
部件)

@Ignacio关于拓扑排序的建议在理论上是正确的,但是由于给定了一个类,你可以通过这些
numberOfFounders
函数轻松快速地得到它的前体(也称为“祖先”…在一个奇怪的词意义中,你是你的祖先之一;-)的数量,我的方法更加实用:它依赖于一个明显的事实,即任何派生类都至少比它的任何基类多一个“祖先”,因此,使用这个
键=
,它总是在它的任何基类之前排序

不相关的类可能以任意顺序结束(就像它们在拓扑排序中一样),但您已经明确表示您不关心这个问题

编辑:OP在下面的评论线程中思考了对多重继承案例的最佳支持,提出了一个与问题中嵌入的最初“预排序”截然不同的想法,但他关于如何实现这个想法的建议并不是最优的:

[h for h in [HANDLERS.get(c) for c in type(obj).mro()] if h is not None][0]
这个想法很好(如果对多重继承支持感兴趣),但最好的实现可能是(Python 2.6或更高版本):

通常,
adict.get(k)和check not None
如果adict:adict[k]
中的k快,但这不是一个特别正常的情况,因为使用
get
需要构建一个“假”单项目列表并在其上“循环”以模拟分配

更一般地说,通过理解构建一个完整的列表只是为了获取它的
[0]
第项是多余的工作——在genexp上调用的
下一个
内置函数更像是
第一个
,如“给我genexp的第一项”,除此之外没有额外的工作。如果listcomp/genexp为空,则会引发StopIteration而不是Indexer,但这通常不是问题;您还可以在
next
中使用第二个参数,如果genexp为空,则将其用作“默认值”

在2.5及更早版本中,您必须使用
(thegenexp).next()
(并且没有办法给它一个默认参数),但尽管在语法上有点不那么闪亮,但在语义和速度上,它或多或少相当于2.6及更好的构造


我很高兴在评论中继续讨论,因为我认为这个结论是有价值的,并且可能有用的(尽管在OP的应用程序的确切环境中可能不太有用,在这种环境中,多重继承实际上可能不是一个问题)。

如果您知道您一直在处理新样式的类:

def numberofancestors(klass):
    return len(klass.mro())
或者,如果您担心组合中可能会有老式的类:

import inspect

def numberofancestors(klass):
    return len(inspect.getmro(klass))
然后,不管是哪种情况

sorted(HANDLERS, key=numberofancestors, reversed=True)
将提供您所需的(您不需要
.keys()
部件)

@Ignacio关于拓扑排序的建议在理论上是正确的,但是由于给定了一个类,你可以通过这些
numberOfFounders
函数轻松快速地得到它的前体(也称为“祖先”…在一个奇怪的词意义中,你是你的祖先之一;-)的数量,我的方法更加实用:它依赖于一个明显的事实,即任何派生类都至少比它的任何基类多一个“祖先”,因此,使用这个
键=
,它总是在它的任何基类之前排序

不相关的类可能以任意顺序结束(就像它们在拓扑排序中一样),但您已经明确表示您不关心这个问题

编辑:OP在下面的评论线程中思考了对多重继承案例的最佳支持,提出了一个与问题中嵌入的最初“预排序”截然不同的想法,但他关于如何实现这个想法的建议并不是最优的:

[h for h in [HANDLERS.get(c) for c in type(obj).mro()] if h is not None][0]
这个想法很好(如果对多重继承支持感兴趣),但最好的实现可能是(Python 2.6或更高版本):

通常,
adict.get(k)和check not None
如果adict:adict[k]
中的k快,但这不是一个特别正常的情况,因为使用
get
需要构建一个“假”单项目列表并在其上“循环”以模拟分配

更一般地说,通过理解构建一个完整的列表只是为了获取它的
[0]
第项是多余的工作——在genexp上调用的
下一个
内置函数更像是
第一个
,如“给我genexp的第一项”,除此之外没有额外的工作。如果listcomp/genexp为空,则会引发StopIteration而不是Indexer,但这通常不是问题;您还可以在
next
中使用第二个参数,如果genexp为空,则将其用作“默认值”

在2.5及更早版本中,您必须使用
(thegenexp).next()
(并且没有办法给它一个默认参数),但是从语法上来说,它有点不那么光鲜,但更像是