class MyList:
def __getitem__(self, index):
return self.data[index] # 自定义下标读取逻辑
def __setitem__(self, index, value):
self.data[index] = value # 自定义下标写入逻辑
obj = MyList()
obj[0] = 10 # 调用 __setitem__
print(obj[0]) # 调用 __getitem__
问题1: 我试了下,报Mylist没有attribute data
和
问题2:
class MyList:
def __init__(self):
self.data = []
def __getitem__(self, index):
return self.data[index] # 自定义下标读取逻辑
def __setitem__(self, index, value):
self.data[index] = value # 自定义下标写入逻辑
obj = MyList()
obj[0] = 10 # 调用 __setitem__
print(obj[0]) # 调用 __getitem__
我试了下,报Mylist报list超过索引范围
第一处:任何变量使用前先定义
声明(declaration) 不存在。Python 没有“先声明再使用”的语法。 ❌
定义(definition) 第一次把名字绑定到对象(即首次出现 = 或参数)。 ✅
初始化(initialization) 把变量第一次设成有意义的值(常与定义同时完成)。 通常伴随定义
赋值(assignment) 把新的对象再绑定到已存在的名字。 任意次数
在 Python 里,“定义”和“初始化”几乎总是同时发生。
如果你硬要找一个只定义而不初始化的场景,可以举:
函数形参
def f(x): # x 被定义,但值由调用者决定
pass
global / nonlocal 语句
x = None
def f():
global x # 告诉解释器“下面出现的 x 用外层的”,但此刻 x 的值尚未写入
这两种情况下名字已定义(解释器知道它存在),但尚未赋予具体值,需要后续代码或外部调用才真正“初始化”。除此之外,普通变量只要出现 = 就同时完成定义+初始化
------------------------------------------------------------------------------------------------------------------------------------------------------------------
第二处:
因为你给下标 0 赋值时,self.data 还是空列表 [],索引越界。
在真正写入前,先把列表扩展到足够长度即可。
改一行:
class MyList:
def init(self):
self.data = []
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
# 长度不够就补 None
if index >= len(self.data):
self.data.extend([None] * (index - len(self.data) + 1))
self.data[index] = value
obj = MyList()
obj[0] = 10
print(obj[0]) # 输出 10
现在 obj[0] = 10 会自动把列表扩展到长度 1,再写入值,不再越界
Python 列表不允许直接给不存在的索引赋值,必须先扩展列表长度,Shell(如 Bash):数组会自动扩展
Shell(如 Bash):数组会自动扩展
bash
lst=()
lst[0]=1 # 合法
Java:数组初始化必须指定长度
java
int[] arr = new int[10]; // 必须先分配空间
arr[0] = 1; // 合法
