You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python类实例化时列表共享问题排查及正确写法问询

问题与解答

问题描述

我有如下类定义:

class Land:
 id = None
 blocks = []

class Block:
 blockId = None
 blockName = None

我遍历一个JSON数据列表创建包含Block的Land实例,代码逻辑如下:

for value in jsonList:
  l = Land()
  l.id = value.id
  
  for block in value.blocks:
    b = Block()
    blockId = block.id
    blockName = block.name
    l.blocks.append(b)

但后续发现数组中的每个Land实例都包含了所有添加过的Block,看起来创建新Land对象时并没有生成新的blocks列表,而是引用了同一个列表。我习惯用C#的new关键字,显然在引用方面存在误解。

补充:
根据相关提示,我是不是应该修改为如下写法?

class Land:  
    def __init__(self):   
        self.id = None   
        self.Blocks = []   
  
class Block:  
    def __init__(self):   
        self.blockId = None  
        self.blockName = None

解答

你的问题核心是混淆了Python中的类变量和实例变量:

  • 原来的Land类里,blocks = []是定义在类层级的类变量,所有Land的实例会共享这个列表对象,所以每次执行l.blocks.append(b)时,都是往同一个全局列表里添加元素,最终导致所有实例的blocks都包含所有Block实例。
  • 而C#中在类内声明字段默认是实例专属的,这和Python的类变量行为完全不同,这是你产生误解的根源。

你补充的修改方向完全正确,必须把实例专属的属性放到__init__方法中,用self.xxx来定义,这样每个Land实例创建时都会初始化自己独立的列表(注意你写的是Blocks,和原代码的blocks大小写不一致,保持命名统一即可)。

另外还要修正你创建Block时的小疏漏:你只定义了blockId和blockName两个局部变量,但没有赋值给b的对应属性,应该改成:

b = Block()
b.blockId = block.id
b.blockName = block.name
l.blocks.append(b)

最终正确的代码结构如下:

class Land:  
    def __init__(self):   
        self.id = None   
        self.blocks = []   
  
class Block:  
    def __init__(self):   
        self.blockId = None  
        self.blockName = None

# 修正后的实例创建逻辑
for value in jsonList:
  l = Land()
  l.id = value.id
  
  for block in value.blocks:
    b = Block()
    b.blockId = block.id
    b.blockName = block.name
    l.blocks.append(b)

这样每个Land实例都会拥有自己独立的blocks列表,不会再出现共享同一列表的问题。

内容的提问来源于stack exchange,提问作者Jason Orman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:00:23