这是我到目前为止所拥有的:
def is_ordered(collection):
if isinstance(collection, set):
return False
if isinstance(collection, list):
return True
if isinstance(collection, dict):
return False
raise Exception("unknown collection")
有更好的方法吗?
NB:我的意思是命令并且不排序。
动机:
我想迭代一个有序的集合。 e.g。
def most_important(priorities):
for p in priorities:
print p
在这种情况下,优先级有序的事实很重要。什么样的收藏不是。我想在这里打鸭子。我经常被Pythonistas的类型检查所劝阻。
答案 0 :(得分:4)
如果集合真的是任意的(意味着它可以是任何类),那么答案必须是否。
基本上,有两种可能的方法:
后者显然是不可行的。前者与您已有的一致,除了您必须了解每个派生的类,例如collections.OrderedDict
;检查dict
是不够的。
坦率地说,我认为整个is_ordered
检查是一堆蠕虫。你为什么要这样做呢?
答案 1 :(得分:1)
更新:从本质上讲,您正在尝试对传递给您的参数进行单元测试。停止这样做,并对您自己的代码进行单元测试。测试您的消费者(确保它适用于有序集合),并对调用它的代码进行单元测试,以确保它获得正确的结果。
在静态类型语言中,您只需将自己局限于特定类型。如果你真的想要复制它,只需指定你接受的唯一类型,并测试它们。如果传递任何其他内容,则引发异常。它不是pythonic,但它可靠地实现了你想做的事情
嗯,你有两种可能的方法:
append
方法的东西几乎都是有序的;和add
方法,你可以尝试添加一个nonce-value,然后遍历该集合以查看nonce是否出现在结尾(或者,可能在一端);你可以尝试添加第二个nonce,再做一次就可以更自信了。当然,这不适用于该集合为空,或者存在一个不会在末尾添加的排序函数。
可能更好的解决方案就是指定您的代码需要有序集合,并且只传递有序集合。
答案 2 :(得分:0)
我认为列举90%的情况与你将得到的一样好(如果使用Python 3,则用str替换basestring)。可能还想考虑如何处理生成器表达式和类似的同类(再次,如果使用Py3,跳过xrangor):
generator = type((i for i in xrange(0)))
enumerator = type(enumerate(range(0)))
xrangor = type(xrange(0))
is_ordered = lambda seq : isinstance(seq,(tuple, list, collections.OrderedDict,
basestring, generator, enumerator, xrangor))
如果您的调用者开始使用itertools,那么您还需要添加islice,imap,groupby返回的itertools类型。但是这些特殊情况的绝对数量确实开始指向code smell。
答案 3 :(得分:-1)
如果没有订购列表怎么办,例如[1,3,2]?