为什么Python中没有第一个(可迭代的)内置函数?

我想知道是否有一个原因,在Python内置函数中没有first(iterable) ,有点类似于any(iterable)all(iterable) (它可能被塞进stdlib模块的某个地方,没有在itertools看到它)。 first会执行短路发生器评估,以避免不必要的(和可能的无限数量的)操作; 即

 def identity(item): return item def first(iterable, predicate=identity): for item in iterable: if predicate(item): return item raise ValueError('No satisfactory value found') 

这样你可以expression如下的东西:

 denominators = (2, 3, 4, 5) lcd = first(i for i in itertools.count(1) if all(i % denominators == 0 for denominator in denominators)) 

显然你不能做list(generator)[0]在这种情况下,因为发电机没有终止。

或者,如果你有一堆正则expression式匹配(当他们都有相同的groupdict接口时有用):

 match = first(regex.match(big_text) for regex in regexes) 

通过避免list(generator)[0]和正匹配短路,可以节省大量不必要的处理。

如果你有一个迭代器,你可以调用它的next方法。 就像是:

 In [3]: (5*x for x in xrange(2,4)).next() Out[3]: 10 

有一个名为“第一”的Pypi包是这样做的:

 >>> from first import first >>> first([0, None, False, [], (), 42]) 42 

以下是如何返回第一个奇数的方法,例如:

 >> first([2, 14, 7, 41, 53], key=lambda x: x % 2 == 1) 7 

如果你只是想从迭代器中返回第一个元素,不pipe是否为真,执行下面的操作:

 >>> first([0, None, False, [], (), 42], key=lambda x: True) 0 

它是一个非常小的包:它只包含这个函数,它没有依赖关系,它可以在Python 2和Python 3上运行。它是一个单独的文件,所以你甚至不需要安装它来使用它。

实际上,这几乎是整个源代码(从MIT 2.0.1版本开始,由Hynek Schlawack发布,在MIT许可下发布):

 def first(iterable, default=None, key=None): if key is None: for el in iterable: if el: return el else: for el in iterable: if key(el): return el return default 

我最近也问了一个类似的问题 (到现在为止,这个问题已经被重复了)。 我的担心也是,我喜欢用内置插件来解决find发电机的第一个真实值的问题。 我自己的解决scheme是这样的:

 x = next((v for v in (f(x) for x in a) if v), False) 

find第一个正则expression式匹配的例子(不是第一个匹配模式!),看起来像这样:

 patterns = [ r'\d+', r'\s+', r'\w+', r'.*' ] text = 'abc' firstMatch = next( (match for match in (re.match(pattern, text) for pattern in patterns) if match), False) 

它不会对谓词进行两次评估(如果只返回该模式,您将不得不这样做),并且不会像理解中的本地人那样使用hack。

但是它有两个发生器嵌套的地方逻辑将决定使用一个。 所以更好的解决scheme会很好。

你的问题有些含糊不清 第一个和正则expression式的定义意味着有一个布尔testing。 但分母的例子明确地有一个if子句; 所以每个整数恰好是真的只是一个巧合。

它看起来像next和itertools.ifilter的组合会给你你想要的。

 match = next(itertools.ifilter(None, (regex.match(big_text) for regex in regexes))) 

Haskell利用你刚才所描述的functiontake作为功​​能(或者在技术上作为部分functiontake 1 )。 Python Cookbook编写了生成器包装器,它执行与taketakeWhile和Haskell相同的function。

但至于为什么这不是内置的,你的猜测和我的一样好。

itertools中有一个“切片”迭代器。 它模拟我们在Python中熟悉的切片操作。 你在找什么类似的东西:

 myList = [0,1,2,3,4,5] firstValue = myList[:1] 

迭代器使用itertools的等价物:

 from itertools import islice def MyGenFunc(): for i in range(5): yield i mygen = MyGenFunc() firstValue = islice(mygen, 0, 1) print firstValue 

您可以使用Python 3.x中支持的明星解包。 你应该阅读这个PEP: https : //www.python.org/dev/peps/pep-3132/

 x = [0, 1, 2, 3] first, *rest = x print(first) print(rest) 

Python遍历列表并将每个元素分配给左侧的variables。 前面带星号的variables,剩下的作为一个新的列表。