FastAPI中函数内初始化对象仍出现竞态条件问题咨询
FastAPI中CustomQuery对象field_2属性异常累加的原因分析
问题核心:可变对象的共享引用陷阱
你的代码里,START_QUERY_DICT中的field_2默认值是可变的列表对象['human', 'homo sapien']。在CustomQuery的__init__方法中,执行setattr(self, k, v[0])时,并没有创建这个列表的新副本,而是直接把全局列表的引用赋值给了实例的field_2属性。
当后续代码执行self.field_2.extend(['human', 'homo sapien'])时,实际上修改的是START_QUERY_DICT里的原始列表。因为所有CustomQuery实例在初始化时,只要没有传入field_2参数,都会共享这个全局列表的引用,导致每次请求都会让这个全局列表不断被扩展,最终出现你看到的累加现象。
为什么传入field_2参数后问题消失?
当请求负载中包含"field_2": ["human"]时,代码会执行setattr(self, request_key, request_value),这里的request_value是从JSON解析出来的新列表对象,它替换了实例对全局列表的引用。后续的extend操作只会修改这个新创建的列表,不会影响START_QUERY_DICT里的原始列表,因此不会出现累加问题。
解决方案:初始化时创建可变对象的副本
修改CustomQuery的初始化逻辑,对可变类型的默认值创建副本,避免共享全局对象的引用:
class CustomQuery: def __init__(self, json_data) -> None: for k, v in START_QUERY_DICT.items(): default_val = v[0] # 针对可变类型(列表、字典)创建独立副本 if isinstance(default_val, (list, dict)): setattr(self, k, default_val.copy()) else: setattr(self, k, default_val) # 后续原有逻辑保持不变 for request_key, request_value in json_data.items(): if not request_key in START_QUERY_DICT: raise AttributeError('Unknown attribute {} from query'.format(request_key)) if not isinstance(request_value, START_QUERY_DICT[request_key][1]): raise TypeError('invalid data type [%s] for field [%s]'% \ (type(request_value).__name__, request_key)) setattr(self, request_key, request_value) if 'human' in self.field_2 or 'homo sapien' in self.field_2: self.field_2.extend(['human', 'homo sapien']) print(self.field_2) self.field_2 = list(set(self.field_2))
这样每个CustomQuery实例的field_2都会是独立的列表副本,不会再出现跨请求的累加问题。
内容的提问来源于stack exchange,提问作者Xuekai Du
相关产品推荐
相关产品推荐

