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()
(并且没有办法给它一个默认参数),但是从语法上来说,它有点不那么光鲜,但更像是