Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Python中没有第一个内置函数(iterable)?_Python_Iterator_Generator - Fatal编程技术网

为什么Python中没有第一个内置函数(iterable)?

为什么Python中没有第一个内置函数(iterable)?,python,iterator,generator,Python,Iterator,Generator,我想知道Python内置函数中没有first(iterable)的原因是什么,有点类似于any(iterable)和all(iterable)(它可能隐藏在stdlib模块的某个地方,但我在itertools中没有看到它)first将执行短路发生器评估,以避免不必要的(以及可能无限次的)操作;i、 e def identity(item): return item def first(iterable, predicate=identity): for item in iter

我想知道Python内置函数中没有
first(iterable)
的原因是什么,有点类似于
any(iterable)
all(iterable)
(它可能隐藏在stdlib模块的某个地方,但我在
itertools
中没有看到它)
first
将执行短路发生器评估,以避免不必要的(以及可能无限次的)操作;i、 e

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')
通过这种方式,您可以表达以下内容:

denominators = (2, 3, 4, 5)
lcd = first(i for i in itertools.count(1)
    if all(i % denominators == 0 for denominator in denominators))
显然,在这种情况下,您不能执行列表(生成器)[0],因为生成器不会终止

或者,如果您有一组要匹配的正则表达式(当它们都具有相同的
groupdict
接口时非常有用):


通过避免列表(生成器)[0]和对正匹配短路,可以节省大量不必要的处理。

如果有迭代器,可以调用它的
下一个
方法。比如:

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

Haskell使用了您刚才描述的函数
take
(或者从技术上说是部分函数
take 1
)。编写的生成器包装器执行与Haskell中的
take
takeWhile
drop
相同的功能


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

你的问题有些含糊不清。首先,您对的定义和regex示例意味着存在一个布尔测试。但是分母示例明确地有一个if子句;所以每个整数都是真的只是巧合

看起来next和itertools.ifilter的组合将为您提供所需的内容

match = next(itertools.ifilter(None, (regex.match(big_text) for regex in regexes)))
有一种方法可以做到这一点:

>>> from first import first
>>> first([0, None, False, [], (), 42])
42
下面是返回第一个奇数的方法,例如:

>> first([2, 14, 7, 41, 53], key=lambda x: x % 2 == 1)
7
如果只想从迭代器返回第一个元素,而不管是否为true,请执行以下操作:

>>> first([0, None, False, [], (), 42], key=lambda x: True)
0
它是一个非常小的包:它只包含这个函数,没有依赖项,并且可以在Python2和Python3上工作。它是一个单独的文件,所以您甚至不必安装它来使用它

事实上,这里几乎是全部源代码(来自Hynek Schlawack在MIT许可下发布的2.0.1版):

我最近问了一个问题(现在它被标记为这个问题的副本)。我还担心的是,我喜欢使用内置函数来解决查找生成器第一个真实值的问题。当时我自己的解决办法是:

x = next((v for v in (f(x) for x in a) if v), False)
对于查找第一个regexp匹配(而不是第一个匹配模式!)的示例,如下所示:

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

但是它有两个嵌套的生成器,逻辑要求只使用一个。因此,更好的解决方案会更好。

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 

请注意:我意识到谓词kwarg与生成器功能是冗余的。我只是想彻底定义“first”的真正含义。相关:此类函数(“类型和速度方面的内置函数”)在标准库的itertools模块中——就像(例如)正则表达式在re模块中,数学函数在数学模块中,等等。总是很难决定在主名称空间中最好显示什么——Perl有REs作为内置项,Fortran有SIN和COS&c,Haskell保留了一些名称,比如take。。。Python更喜欢将所有这些名称组都放在标准库模块中。Haskell的first等价物不是head吗?“take 1”返回一个列表,而不是一个元素。如果答案为零,则会出现问题。
next(迭代器)
是我没有找到的答案。上述方法在Python 3中不起作用,如果
x
是迭代器,则使用
next(iter(d))
if
d
是Python 2.6中所有iterables(例如,对于列表和生成器)的通用解决方案,而在Python 2.6及以上版本中使用
next(iter(xs))
。在Python2.5中,您可以执行
iter(xs).next()
。我不明白这个答案。问题中显示的“第一个”跳过了序列的初始元素“falsy”(由bool(谓词(项))定义)。我想这就是重点。”next()'不这样做。我很困惑。@JonathanHartley:关键是,拥有next()和一种构建过滤序列的通用方法(例如,使用
itertools.ifilter()
(…for…in…if condition)
),将它们结合起来并不足以证明拥有另一个内置工具是正确的。请注意,OP的正则表达式示例就是
next(regex for regex in regex if regex.match(big_text))
.OP的示例返回的内容不同于
next(regex for regex in regex if regex.match(big_text))
;它返回regex.match(big_text)的结果。如果没有first(),怎么做?
next(regex.match(big_text)for regex in regex if regex.match(big_text))
是多余的。
下一步(ifilter(imap(lambda x:x.match(big_text),regexes))
与first.Nice相比似乎过于复杂。但是自己实现它将需要大约三行代码。这很难证明安装完整包的开销是合理的(引入所有可移植性问题等)。问题仍然存在:为什么这不是Python内置的一部分?或者使用内置Python结构来表达这一点的最干净、最具Python风格的方式是什么?@Alfe:使用包是干净和Python风格的。至于为什么它不是内置的,这不是堆栈溢出的问题,因为任何不是cor的人都不可能回答这个问题好吧,那么让我这么说:你会怎么说
myList = [0,1,2,3,4,5]
firstValue = myList[:1]
from itertools import islice
def MyGenFunc():
    for i in range(5):
        yield i

mygen = MyGenFunc()
firstValue = islice(mygen, 0, 1)
print firstValue