V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
PEax
V2EX  ›  Python

新手请教,关于操作列表的问题

  •  
  •   PEax · 2022-07-21 14:29:50 +08:00 · 2011 次点击
    这是一个创建于 856 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 ,循环不是很满足

    12 条回复    2022-07-22 22:33:38 +08:00
    lyang
        1
    lyang  
       2022-07-21 14:46:28 +08:00
    ```
    def opreate(item):

    dosomething...

    for item in task:
    opreate(item)
    ```
    PEax
        2
    PEax  
    OP
       2022-07-21 14:52:00 +08:00
    @lyang 用 for 有一个问题,就是如果要用多线程,没办法共享列表了
    lyang
        3
    lyang  
       2022-07-21 16:01:28 +08:00   ❤️ 1
    @PEax 多线程不怎么用,但应该可以的吧,加锁。
    reter
        4
    reter  
       2022-07-21 16:15:27 +08:00   ❤️ 1
    python 不是有一个 GIL 锁吗,理论上是可以多线程同时操作同一个列表对象的。当然最好的方法还是用自带的 Queue (有多线程和多进程的版本).
    wxf666
        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
    skies457
        6
    skies457  
       2022-07-21 16:30:30 +08:00   ❤️ 1
    fbichijing
        7
    fbichijing  
       2022-07-21 16:32:30 +08:00   ❤️ 1
    直接用 queue 不就完事了吗?
    ispinfx
        8
    ispinfx  
       2022-07-21 16:56:12 +08:00   ❤️ 1
    > 持续操作列表的,每次取出一个,直到列表清空

    同楼上
    sujin190
        9
    sujin190  
       2022-07-21 17:38:51 +08:00   ❤️ 1
    while task:
    item = task.pop(0)
    dosomething...

    while 循环处理就是了啊,干嘛要递归调用
    renmu123
        10
    renmu123  
       2022-07-21 17:48:44 +08:00 via Android   ❤️ 1
    你用多线程为什么还要等一个操作完再操作另一个,迷惑行为。
    这种需求直接单线程不就行了,只要你的操作不是异步的
    jmqrock2020
        11
    jmqrock2020  
       2022-07-22 10:23:49 +08:00
    多线程的 CPU 时间片的分配,应该是看调用操作是不是原子的,如果非原子的那么可能在没有完成时就会被切换至其他线程。GIL 只是锁住了并行度,并不能保证线程安全。我的理解可能说的不对,欢迎指正。
    @reter
    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

    总之,有多线程就要考虑并发读写变量的情况
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   911 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 21:51 · PVG 05:51 · LAX 13:51 · JFK 16:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.