为什么队列(Queues)没有实现 len() 方法?

19
内置函数len() (https://docs.python.org/3/library/functions.html#len) 返回“对象的长度(即项目数)”,但是对于queue.Queue (https://docs.python.org/3/library/queue.html),该函数未实现。 相反,queue.Queue具有qsize()方法,返回队列的近似大小,但其实它确实有长度;可以在构造函数中指定Queue的最大长度。类似的collections.deque使用len函数工作正常。
为什么不使用通用的len()来处理queue.Queue?或者说,如果将qsize命名为__len__以启用len()函数会出现什么问题?

3
也许是因为人们期待 len 返回一个准确的值,而不是一个近似值。并且这个操作应该快速完成。为了实现一个准确的 __len__,队列需要被暂时锁住以防止添加和删除操作,这将影响性能。 - PM 2Ring
1个回答

20

len() 方法没有在 queue.Queue 中实现,因为这会是一个"有吸引力的危险物":仅专家应该考虑使用它,但一个“友好的名称”将鼓励非专家使用。

与大多数序列类型(如 listdeque)不同,queue.Queue 是特别用于多线程上下文中使用的(类似于 multiprocessing 模块的队列类型)。虽然任何时候 Queue 中的项目数量都有一个确定的值,但用户代码无法找出那个值是多少:在调用 .qsize() 返回值并且你的代码可以查看返回值之间,任意数量的其他线程(或进程,在 multiprocessing 的情况下)可能已经对队列的内容进行了任意数量的更改。

因此,唯一可以真正说关于 .qsize() 返回值的事情是,Queue某个时间点曾经包含过那么多的项目。当你可以使用返回值时,它可能在其中任意添加了更多(或更少)的值。

当然,如果您只运行一个线程,则不存在为 Queue 支付实现复杂性的必要(使用 listdeque 代替即可)。


1
那么为什么队列要实现 empty()full() 方法呢? - Charles Pehlivanian
5
如果我写了 empty()full(),它们不会被实现。在早期,各种可选的 timeout= 参数并不存在,因此 full()empty() 被用于循环中作为概率玩意儿,以便猜测 .put().get() 是否“可能”成功。使用这些函数的代码(例如使用 qsize() 的代码)常常容易出现时间错误。 - Tim Peters
3
对我来说,一个简单且不会让人感到意外的 len() 比过于复杂的 qsize() 更合适,因为我不是专家。len() 的具体细节和可能的不准确性可以在帮助信息中解释,这对程序员来说应该足够了。 - Nik O'Lai
我不明白。len函数是可重载的:“*如果存在__len__方法,则len()函数将使用该方法来查询对象的长度。*”为什么不将__len__别名为qsize?这样你就可以得到完全相同的属性。这并不意味着if o.qsize() > 0: o.get()if len(o) > 0: o.get()更可靠或不可靠。 - Luc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接