pandas行级apply函数内修改同一对象是否安全?
问题解答
结论
你给出的代码片段在原生pandas的默认执行逻辑下,两个断言总能返回一致的结果。原生pandas的行级Series.apply默认不存在同时处理两行数据的情况,只有特殊场景下才会出现并行处理的异常。
具体说明
- 原生pandas的
Series.apply()是严格按行顺序单线程串行执行的,每处理完一行才会调用一次你传入的counter.add方法,不会出现两行同时调用该方法的情况,因此不存在实例状态的竞态冲突问题。 - 你的
add方法每次返回的是当前传入的行值,因此apply返回的序列必然和原列[1,2,3,4,5]完全一致,第一个断言始终成立。 - 因为调用顺序严格按行顺序执行,count累加的就是1+2+3+4+5的总和15,第二个断言也始终成立。
可能出现结果不一致的特殊场景
如果你手动引入了多进程/多线程逻辑,或者使用了swifter、pandarallel这类pandas并行扩展库来替代原生apply,就会出现同时处理多行的情况:
- 多进程场景下Counter实例在不同进程中会被独立复制,最终的count值不会是15
- 多线程场景下会出现读写竞态,count的结果会不确定,apply返回的序列也可能出现错乱
你用到的相关代码参考:
import time class Counter(): def __init__(self): self.count = 0 self.value = None def add(self, value): self.value = value time.sleep(2) # 对应实际场景中的复杂业务逻辑 self.count += self.value return self.value
import pandas as pd df = pd.DataFrame({'A': [1,2,3,4,5]}) counter = Counter() assert df['A'].apply(counter.add).tolist() == [1,2,3,4,5] assert counter.count == 15
内容的提问来源于stack exchange,提问作者Helia Jamshidi
相关产品推荐
相关产品推荐

