1

这是我到目前为止所拥有的:

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")

有没有更好的方法来做到这一点?

注意:我的意思是有序而不是排序。

动机:

我想遍历一个有序的集合。例如

def most_important(priorities):
    for p in priorities:
        print p

在这种情况下,优先级排序这一事实很重要。不是什么收藏品。我想在这里过着打鸭子的生活。我经常被 Pythonistas 的类型检查所劝阻。

4

4 回答 4

4

如果集合确实是任意的(意味着它可以是任何类别),那么答案必须是no

基本上,有两种可能的方法:

  1. 了解可以呈现给您的方法的每个可能的类,以及它是否是有序的;
  2. 通过将所有可能的键组合插入其中来自己测试集合,并查看是否保留了顺序。

后者显然是不可行的。前者与您已经拥有的基本相同,只是您必须了解每个派生类,例如collections.OrderedDict; 检查dict是不够的。

坦率地说,我认为整个is_ordered支票都是一罐蠕虫。你为什么要这样做呢?

于 2012-05-02T10:39:04.470 回答
1

更新:本质上,您正在尝试对传递给您的参数进行单元测试。停止这样做,然后对您自己的代码进行单元测试。测试你的消费者(确保它适用于有序集合),并对调用它的代码进行单元测试,以确保它得到正确的结果。

在静态类型语言中,您只需将自己限制为特定类型。如果您真的想复制它,只需指定您接受的唯一类型,然后测试它们。如果传递了其他任何内容,则引发异常。它不是pythonic,但它可靠地实现了您想要做的事情


好吧,您有两种可能的方法:

  1. append几乎可以肯定,任何带有方法的东西都是有序的;和
  2. 如果它只有一个add方法,您可以尝试添加一个 nonce 值,然后遍历集合以查看 nonce 是否出现在末尾(或者,可能在一端);您可以尝试添加第二个随机数并再次执行以更加自信。

当然,这在集合为空的情况下是行不通的,或者有一个排序函数不会在末尾产生加法。

可能更好的解决方案是简单地指定您的代码需要有序集合,并且只传递有序集合。

于 2012-05-02T10:50:14.920 回答
0

我认为枚举 90% 的情况与您将获得的一样好(如果使用 Python 3,请将 basestring 替换为 str)。可能还想考虑如何处理生成器表达式和类似的东西(同样,如果使用 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 类型。但这些特殊情况的绝对数量确实开始指向代码异味

于 2012-05-02T13:26:53.480 回答
-1

如果列表没有排序,例如 [1,3,2] 怎么办?

于 2012-05-02T10:39:47.053 回答