【问题标题】:In Python, how do I determine if an iterable has stable iteration order?在 Python 中,如何确定可迭代对象是否具有稳定的迭代顺序?
【发布时间】:2012-09-17 09:58:47
【问题描述】:

在 Python 中,如何确定一个可迭代对象是否具有稳定的迭代顺序?

collections.Iterable 抽象基类,但没有稳定的对应物。

我问的原因是能够阻止用户或在他们通过(错误地)以不稳定的迭代顺序(dictset 等)迭代到迭代稳定性的函数时警告他们很重要。

【问题讨论】:

标签: python collections iterator abstract-class


【解决方案1】:

您可能正在寻找的东西是collections.Sequence。这比你想要的更具体一点,因为根据the docs 一个序列“支持使用整数索引进行有效的元素访问”;它也不够具体,因为没有明确保证两次获得相同的索引必须两次返回相同的值。但这足以区分列表和元组与字典和集合。

但是,一般来说是没有办法的。一般来说,没有办法,因为你可以编写任何你喜欢的迭代,并且不需要你指定它是否稳定。例如,你可以这样做:

>>> def f():
...     if random.random() < 0.5:
...         for a in xrange(10):
...             yield a
...     else:
...         stuff = range(10)
...         random.shuffle(stuff)
...         for a in stuff:
...             yield a
>>> list(f())
0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(f())
1: [7, 0, 2, 8, 5, 1, 4, 3, 6, 9]

可以编写迭代器而无需声明它们是否稳定,以及无法通过迭代某事物来判断它是否会在以后以相同方式迭代的事实,意味着存在无法判断给定的迭代器是否稳定。

我建议您简单地记录您的函数需要迭代顺序的稳定性。您还可以显式检查您知道可能不稳定的内置类型,并在这些类型上引发错误。但是没有办法检查任意用户定义的迭代器的稳定性。

【讨论】:

  • +1。您真正可以做的唯一另一件事是尝试检测不稳定性(例如,您以前见过这个 id 并且索引以不同的顺序出现)并断言,这似乎不值得做。
  • collections.Sequence 在这里没有用,因为除了可迭代性之外,它还要求使用整数索引访问元素。我正在寻找通用解决方案,因为我想避免显式类型检查。但我同意,如果没有一种语言提供一种预先声明迭代稳定性的方法,这可能是不可能的。
  • @PiotrDobrogost:您可以定义自己的抽象基类以实现稳定的迭代顺序。类似于this 中所做的事情回答另一个问题。
  • @martineau:这对于简化已知稳定可迭代类型(或已知不稳定可迭代类型)的识别是一个好主意,但它仍然无法帮助您确定任意可迭代对象是否稳定。
  • 正如链接答案中提到的,代码的外部用户可以自己注册类,以便正确处理它们。我认为对于任意未知类没有实用的方法。猜猜最好的办法是假设它不是,并向用户发出警告,建议他们注册正在传递的实例的类。
猜你喜欢
  • 2010-12-29
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 2013-08-03
相关资源
最近更新 更多