【问题标题】:Python: EAFP in checking for an empty collection/iterablePython:EAFP 在检查空集合/可迭代
【发布时间】:2020-08-09 14:29:27
【问题描述】:

我有一些其他语言的编程经验,但我一直在学习 Pluralsight 的 Core Python 课程来对比语言特性。在课程的可迭代部分中,讲师创建了这个函数,该函数使用 EAFP 原理在可迭代参数为空时引发异常:

def first(iterable):
    iterator = iter(iterable)
    try:
        return next(iterator)
    except StopIteration:
        raise ValueError("iterable is empty")

我看到这个并想,“我不能在 else 子句中引发那个异常吗?所以我写了这个函数:

def first(iterable):
    if(len(iterable) == 0):
        raise ValueError("iterable is empty")
    else:
        return iterable[0]

在写这篇文章时,我发现这个Stack Overflow question 是关于一个空列表的implicit boolness,并认为我可以重构我的代码以使其更加pythonic:

def first(iterable):
    if not iterable:
        raise ValueError("iterable is empty")
    else:
        return iterable[0]

它们的工作方式似乎相同,而我的仍然使用 EAFP 原理,对吧?第一个更快吗?还是只是对 iter() 和 next() 函数的演示?

【问题讨论】:

  • tryexcept 是昂贵的操作,因此在这种情况下,您的代码会更快。但是您的代码有一个问题,因为它无法区分实际的可迭代对象和不可迭代对象,例如 first(22322) 对于 int 输入,您的代码正在考虑将其视为可迭代,而实际上却不是。跨度>
  • @sahasrara62 我不确定这个;我记得几年前的一位核心开发人员(Marc Andre Lemburg)曾在一次演讲中说try 本身很便宜,但输入except 子句很昂贵。
  • 您可以在任何 ide 中测试速度和示例(我在 pcharm 中测试过)是的,尝试基本上是 o(1) 成本操作,但除了成本高昂

标签: python iteration iterable


【解决方案1】:
def first(iterable):
    if(len(iterable) == 0):
        raise ValueError("iterable is empty")
    else:
        return iterable[0]

这个函数假定迭代有一个有意义的长度(也就是说,它有一个__len__ 方法)。例如,这不适用于生成器表达式

>>> len(x for x in  range(4))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()

同样的功能

def first(iterable):
    if not iterable:
        raise ValueError("iterable is empty")
    else:
        return iterable[0]

假设bool(iterable) 为空时将评估为False。同样,这可能不是真的:

>>> bool(x for x in  [])
True

有用的阅读:

【讨论】:

    猜你喜欢
    • 2012-12-29
    • 1970-01-01
    • 2012-07-07
    • 2012-04-02
    • 2017-05-02
    • 2014-12-10
    • 1970-01-01
    • 2022-07-05
    • 2019-02-14
    相关资源
    最近更新 更多