代码如下, 为什么 get_a
没有返回默认?
In [7]: a = [{'a':1},{'a':2}]
In [8]: a
Out[8]: [{'a': 1, 'b':'夏天'}, {'a': 2, 'b':'冬天'}]
In [9]: def filter_a(k,v):
...: return filter(lambda x: x[k] == v, a)
...:
In [10]: def get_a(k,v):
...: return next(filter_a(k,v), get_a('a',2)) # 我的想法是如果 iter 为空, 返回 这个默认
...:
In [11]: get_a('a',1)
报错如下
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
<ipython-input-11-428f62971dec> in <module>
----> 1 get_a('a',1)
<ipython-input-10-a36c60ef3685> in get_a(k, v)
1 def get_a(k,v):
----> 2 return next(filter_a(k,v), get_a('a',2))
3
... last 1 frames repeated, from the frame below ...
<ipython-input-10-a36c60ef3685> in get_a(k, v)
1 def get_a(k,v):
----> 2 return next(filter_a(k,v), get_a('a',2))
3
RecursionError: maximum recursion depth exceeded while calling a Python object
1
Divinook 2021-09-16 17:35:22 +08:00
因为你的递归没有终止条件,改成
return next(filter_a(k,v), {'a', 2}) |
3
hsfzxjy 2021-09-16 17:54:17 +08:00 via Android
参数会先于函数调用求值,所以不管 iter 是不是空 return next(filter_a(k,v), get_a('a',2)) 里的 get_a('a', 2) 都会执行
|
4
plko345 OP @Divinook 而且 filter 返回是非空的, next 应该直接返回该值才对, 但却不断的返回 default
|
5
plko345 OP @hsfzxjy 可是像这样却没有问题
```py In [13]: def get_b(x): ...: return x[0] ...: In [14]: next(filter(lambda x: x==0, [0,1,2]), get_b('abc')) Out[14]: 0 ``` |
6
plko345 OP |
7
princelai 2021-09-16 18:13:28 +08:00
def get_a(k,v):
return next(filter_a(k,v), next(filter_a('a',2))) 这样呢 |
8
2i2Re2PLMaDnghL 2021-09-16 19:47:11 +08:00 1
你在 get_a 里面还没进迭代器呢就先重复 get_a 了,罚您重看 SICP 1.1.5
next 的参数不会懒惰求值,咱把 get_a 写成 applicative order def get_a(k,v): t1 = filter_a(k,v) t2 = get_a('a',2) t3 = next(t1, t2) return t3 显然,计算 t2 的时候就已经无限递归了 你需要的大概是 try: return next(filter_a(k,v)) except StopIteration: return get('a',2) 或者 chain 一个生成器上去 next(itertools.chain(filter_a(k,v), (get_a('a',2) for _ in range(1)))) 但也有个问题,如果没有 x['a']==2 的记录,还是会无限递归。 |
9
2i2Re2PLMaDnghL 2021-09-16 19:51:10 +08:00
#4 不是返回 default,而是先求 default 再求 next
但因为求 default 导致了无限递归,你永远不会求 next 不妨试试这样写 original_next = next def next(*args): ... print("running next()") ... return original_next(*args) 你再试试,你会发现 "running next()" 一次也没被打印。 |
10
plko345 OP |
11
plko345 OP 我还是乖乖返回 None 再做次判断吧
|