谁能解释为什么将生成器作为函数的唯一位置参数传递似乎有特殊规则?
如果我们有:
>>> def f(*args):
>>> print "Success!"
>>> print args
Run Code Online (Sandbox Code Playgroud)
这正如预期的那样有效.
>>> f(1, *[2])
Success!
(1, 2)
Run Code Online (Sandbox Code Playgroud)按预期,这不起作用.
>>> f(*[2], 1)
File "<stdin>", line 1
SyntaxError: only named arguments may follow *expression
Run Code Online (Sandbox Code Playgroud)这正如预期的那样有效
>>> f(1 for x in [1], *[2])
Success!
(generator object <genexpr> at 0x7effe06bdcd0>, 2)
Run Code Online (Sandbox Code Playgroud)这有效,但我不明白为什么.不应该以与2)相同的方式失败
>>> f(*[2], 1 for x in [1])
Success!
(generator object <genexpr> at 0x7effe06bdcd0>, 2)
Run Code Online (Sandbox Code Playgroud)以下行为对我来说似乎有点违反直觉(Python 3.4):
>>> [(yield i) for i in range(3)]
<generator object <listcomp> at 0x0245C148>
>>> list([(yield i) for i in range(3)])
[0, 1, 2]
>>> list((yield i) for i in range(3))
[0, None, 1, None, 2, None]
Run Code Online (Sandbox Code Playgroud)
最后一行的中间值实际上并不总是None
,它们是我们send
进入生成器的任何东西,等价(我猜)到下面的生成器:
def f():
for i in range(3):
yield (yield i)
Run Code Online (Sandbox Code Playgroud)
令我感到有趣的是,这三条线路都很有用.该参考指出,yield
仅在一个函数定义允许的(虽然我可能读错和/或它可能只是已经从旧版本复制).前两行在SyntaxError
Python 2.7中生成,但第三行不生成.
而且,这似乎很奇怪
有人可以提供更多信息吗?
python yield list-comprehension generator generator-expression
我正在运行一段代码,意外地在程序的某个部分出现了逻辑错误.在调查该部分时,我创建了一个测试文件来测试正在运行的语句集,并发现一个看起来非常奇怪的异常错误.
我测试了这个简单的代码:
array = [1, 2, 2, 4, 5] # Original array
f = (x for x in array if array.count(x) == 2) # Filters original
array = [5, 6, 1, 2, 9] # Updates original to something else
print(list(f)) # Outputs filtered
Run Code Online (Sandbox Code Playgroud)
输出是:
>>> []
Run Code Online (Sandbox Code Playgroud)
是的,没什么.我期待过滤器理解能够在数组中获取数量为2的项并输出它,但我没有得到:
# Expected output
>>> [2, 2]
Run Code Online (Sandbox Code Playgroud)
当我评论第三行再次测试时:
array = [1, 2, 2, 4, 5] # Original array
f = (x for x in array if array.count(x) == 2) # Filters original
### array …
Run Code Online (Sandbox Code Playgroud) 我正在回答这个问题,我更喜欢这里的生成器表达并使用它,我认为它会更快,因为生成器不需要先创建整个列表:
>>> lis=[['a','b','c'],['d','e','f']]
>>> 'd' in (y for x in lis for y in x)
True
Run Code Online (Sandbox Code Playgroud)
Levon在他的解决方案中使用了列表理解,
>>> lis = [['a','b','c'],['d','e','f']]
>>> 'd' in [j for i in mylist for j in i]
True
Run Code Online (Sandbox Code Playgroud)
但是当我做这些LC的时间结果比生成器快时:
~$ python -m timeit -s "lis=[['a','b','c'],['d','e','f']]" "'d' in (y for x in lis for y in x)"
100000 loops, best of 3: 2.36 usec per loop
~$ python -m timeit -s "lis=[['a','b','c'],['d','e','f']]" "'d' in [y for x in lis for y …
Run Code Online (Sandbox Code Playgroud) 在Python 3中,列表理解只是语法糖,用于生成list
函数的生成器表达式?
例如是以下代码:
squares = [x**2 for x in range(1000)]
Run Code Online (Sandbox Code Playgroud)
实际上在后台转换成以下内容?
squares = list(x**2 for x in range(1000))
Run Code Online (Sandbox Code Playgroud)
我知道输出是相同的,并且Python 3修复了列表推导所具有的周围命名空间的令人惊讶的副作用,但就CPython解释器所做的事情而言,前者转换为后者,或者是否有任何区别在如何执行代码?
我发现,在评论部分等价的这一主张这个问题,和快速谷歌搜索显示了同样的要求正在作出这里.
在Python 3.0文档中的新内容中也提到了这一点,但措辞有些含糊:
还要注意,列表推导具有不同的语义:它们更接近于list()构造函数中的生成器表达式的语法糖,特别是循环控制变量不再泄漏到周围的范围中.
python list-comprehension generator-expression python-3.x python-internals
我今天跑了一个错误,因为我next()
用来提取一个值,而'找不到'会发出一个错误StopIteration
.
通常会停止程序,但函数使用next
是在all()
迭代中调用的,所以all
刚刚终止并返回True
.
这是预期的行为吗?是否有风格指南,以帮助避免这种事情?
简化示例:
def error(): return next(i for i in range(3) if i==10)
error() # fails with StopIteration
all(error() for i in range(2)) # returns True
Run Code Online (Sandbox Code Playgroud) 我有一个列表和一个lambda
定义为的函数
In [1]: i = lambda x: a[x]
In [2]: alist = [(1, 2), (3, 4)]
Run Code Online (Sandbox Code Playgroud)
然后我尝试两种不同的方法来计算一个简单的总和
第一种方法.
In [3]: [i(0) + i(1) for a in alist]
Out[3]: [3, 7]
Run Code Online (Sandbox Code Playgroud)
第二种方法.
In [4]: list(i(0) + i(1) for a in alist)
Out[4]: [7, 7]
Run Code Online (Sandbox Code Playgroud)
两种结果都出乎意料地不同.为什么会这样?
我可以在列表推导/生成器表达式中使用if
和for
list(i for i in range(100) if i*i < 30)
Run Code Online (Sandbox Code Playgroud)
我知道这不是最有效的,但对我而言,因为条件可能要复杂得多,这只是一个例子.但是,这仍然经历了一百次迭代,并且只在前6中产生一个值.有没有办法告诉生成器表达式在哪里停止这样的事情:
list(i for i in range(100) while i*i < 30)
Run Code Online (Sandbox Code Playgroud)
但是,while
在生成器表达式中不理解.所以,我的问题是,如何编写带有停止条件的生成器表达式,这样它就不会继续计算,即使它没有产生新的值.
我有一个字典列表,如下所示:
lst = [{'a': 5}, {'b': 6}, {'c': 7}, {'d': 8}]
Run Code Online (Sandbox Code Playgroud)
我写了一个生成器表达式,如:
next((itm for itm in lst if itm['a']==5))
Run Code Online (Sandbox Code Playgroud)
现在奇怪的是,虽然这适用于它的键值对,'a'
但下次会为所有其他表达式抛出错误.表达:
next((itm for itm in lst if itm['b']==6))
Run Code Online (Sandbox Code Playgroud)
错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
KeyError: 'b'
Run Code Online (Sandbox Code Playgroud) 据我所知,有三种通过理解创建生成器的方法1.
经典之一:
def f1():
g = (i for i in range(10))
Run Code Online (Sandbox Code Playgroud)
该yield
变种:
def f2():
g = [(yield i) for i in range(10)]
Run Code Online (Sandbox Code Playgroud)
的yield from
变体(即提出了SyntaxError
除了一个函数的内部):
def f3():
g = [(yield from range(10))]
Run Code Online (Sandbox Code Playgroud)
这三种变体导致不同的字节码,这并不奇怪.第一个是最好的,这似乎是合乎逻辑的,因为它是通过理解创建生成器的专用,直接的语法.但是,它不是产生最短字节码的那个.
在Python 3.6中反汇编
经典的发电机理解
>>> dis.dis(f1)
4 0 LOAD_CONST 1 (<code object <genexpr> at...>)
2 LOAD_CONST 2 ('f1.<locals>.<genexpr>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 STORE_FAST 0 (g) …
Run Code Online (Sandbox Code Playgroud) python ×10
generator ×5
python-2.7 ×2
python-3.x ×2
dictionary ×1
list ×1
recipe ×1
syntax ×1
timeit ×1
yield ×1