task = []
def opreate(task):
item = task.pop(0)
dosomething...
if(len(task) == 0):
return
opreate(task)
opreate(task)
这样会造成栈无线堆积 RecursionError: maximum recursion depth exceeded while calling a Python object
大佬们,请问有什么方法可以持续操作列表的,每次取出一个,直到列表清空,我需要等每一个 item 里面操作完再进行下一个 item ,循环不是很满足
1
lyang 2022-07-21 14:46:28 +08:00
```
def opreate(item): dosomething... for item in task: opreate(item) ``` |
4
reter 2022-07-21 16:15:27 +08:00 1
python 不是有一个 GIL 锁吗,理论上是可以多线程同时操作同一个列表对象的。当然最好的方法还是用自带的 Queue (有多线程和多进程的版本).
|
5
wxf666 2022-07-21 16:24:20 +08:00 1
@PEax 这样?
def sum_of_squares(items): def square(n: int): time.sleep(1) return n ** 2 with ThreadPoolExecutor(max_workers=4) as executor: return sum(executor.map(square, items)) if __name__ == '__main__': print(sum_of_squares(range(1, 10 + 1))) # 1^2 + 2^2 + ... + 10^2 |
6
skies457 2022-07-21 16:30:30 +08:00 1
这个东西叫 tail recursion
https://stackoverflow.com/questions/13591970/does-python-optimize-tail-recursion |
7
fbichijing 2022-07-21 16:32:30 +08:00 1
直接用 queue 不就完事了吗?
|
8
ispinfx 2022-07-21 16:56:12 +08:00 1
> 持续操作列表的,每次取出一个,直到列表清空
同楼上 |
9
sujin190 2022-07-21 17:38:51 +08:00 1
while task:
item = task.pop(0) dosomething... while 循环处理就是了啊,干嘛要递归调用 |
10
renmu123 2022-07-21 17:48:44 +08:00 via Android 1
你用多线程为什么还要等一个操作完再操作另一个,迷惑行为。
这种需求直接单线程不就行了,只要你的操作不是异步的 |
11
jmqrock2020 2022-07-22 10:23:49 +08:00
多线程的 CPU 时间片的分配,应该是看调用操作是不是原子的,如果非原子的那么可能在没有完成时就会被切换至其他线程。GIL 只是锁住了并行度,并不能保证线程安全。我的理解可能说的不对,欢迎指正。
@reter |
12
reter 2022-07-22 22:33:38 +08:00
我认为是对的。但是 python 是解释型语言,应该先从解释器角度去理解。
比如 https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe 描述到,python 解释器的执行单元是字节码指令。字节码指令背后的所有 C 语言代码执行也是“原子操作”。当一个字节码成功执行后,其他线程才有机会拿到 GIL 。 CPU 还有各种缓存和指令执行顺序问题,那就更加复杂了。 @jmqrock2020 总之,有多线程就要考虑并发读写变量的情况 |