The problem of Python's List variable object

The problem of Python's List variable object

hint

Reference books: "Python Crazy Lectures", "Python Basic Programming Actual Combat" by Band of Brothers

1 Getting to know the List object first

  • The list (list) in Python is implemented based on PyListObject, and the list supports element insertion, deletion, and update operations, so PyListObject is a variable-length object, ie; at the same time, it is also a 列表的长度随着元素的增加(或删除)而变长(或变短)variable object, ie 列表中的元素根据列表的操作而发生变化,内存大小动态的变化.
  • A list (list) can actually be similar to an array in C++ and Java.
  • A list is an object in Python. A list is an object used to store objects. An object is an area in memory dedicated to storing data;
  • Multiple ordered data can be saved in a list, but like a value, it can only save a single data;
  • Lists can be indexed (index) to get the elements in the list:
    • The index is the position of the element in the list, and each element in the list has an index
    • The index is an integer starting from 0, the first position index of the list is 0, the second position index is 1, the third position index is 2, and so on
    • Index syntax: my_list[index], such as my_list[0]
    • Note the out-of-bounds exception for list index subscripts:IndexError: list index out of range
  • Creation of python lists:
# 1、创建列表,通过[]来创建(空)列表
my_list = []

# 2、打印该列表,type()为获得my_list的类型
print(my_list , type(my_list))   # 运行结果:[] <class 'list'>

# 列表存储的数据,我们称为元素。一个列表中可以存储多个元素,也可以在创建列表时,来指定列表中的元素。
# 3、创建一个只包含一个元素的列表
my_list = [10] 

# 当向列表中添加多个元素时,多个元素之间使用,隔开
# 4、创建了一个包含有5个元素的列表
my_list = [10,20,30,40,50] 

# 5、列表中可以保存任意的对象,这里可能有点套娃
my_list = [10,'hello',True,None,[1,2,3],['python','java']]

# 6、通过索引获取列表中的元素 
print(my_list[4])  # 运行结果:[1,2,3]

# 7、如果使用的索引超过了最大的范围,会抛出异常
print(my_list[6])  # 运行结果:IndexError: list index out of range

# 8、len()函数,通过该函数可以获取列表的长度,即列表中元素的个数。
# 获取到的长度的值,是列表的最大索引 + 1
print(len(my_list))   # 运行结果:6

2 Changes after the List reference is passed

# list(列表)
a = [1,2,3]
b = a
b[0] = 2     # 由于list是可变对象,改变b的时候会导致a的改变,列表a和b都是[2,2,3]
print(a)
print(b)

'''
运行结果:
[2,2,3]
[2,2,3]
'''

# str(字符串)
s = 'abc'
s2 = s
s2 += 'd'   # 由于str是不可变对象,s2是新建的对象,s2的修改不会影响s。s为'abc',s2为'abcd'。
print(s)
print(s2)
'''
运行结果:
'abc'
'abcd'
'''

3 List's Pit

建议不要花里胡哨

a = [1,2,3]
b = a
a is b      # 运行结果:True
# 因为按引用传递,a和b存的地址(引用)是一样的,改变b相当于改变a。

b = a[:]
a is b       # 运行结果:False
# 想使用list的值却不想修改原list时可以使用切片[:]拷贝一份到新空间。

a = [1,2,3]
id(a)    # 运行结果:140376329323528
a = [1,2,3]
id(a)    # 运行结果:140376359286920
# 两次定义相同的list,但是其地址并不相同,会创造新对象

a = [1,2,3]
id(a)    # 运行结果:140376329323528
a[:] = [1,2,3]
id(a)    # 运行结果:140376329323528
# 因为a[:]切片创建的是新空间,对新空间赋值不影响旧空间a,所以a的地址跟原来一致。

a =[ [0]*2 ]* 2   # 用这种方式创建一个二维list,此时a为[[0,0],[0,0]]。(容易出现坑)
a[0] is a[1]      # True,这种创建方法的机制是复制list,所以2个list其实是同一个list。
a[0][0] = 1       # 改变第一个list时,第二个list也改变,此时a为[[1,0],[1,0]]。
a[0] += [1]       # 改变第一个list时,第二个list也改变,此时a为[[1,0,1],[1,0,1]]。+=相当于extend,对list进行原地修改。

a[0] = a[0] + [1] # 改变第一个list时,第二个list不改变,此时a为[[1,0,1,1],[1,0,1]]。因为不是原地改变,而是创建了新list,然后给原来的引用赋了新值。
a[0] = [1,2]      # a[0]指向创建的新list[1,2]。此时a[1]不变,a为[[1,2],[1,0,1]]。同样是给a[0]赋值了新的list[1,2],不会影响到a[1]。

a = [[0]*2 for _ in range(2)] # 相对正确的创建方式,这样创建的二维list,改变a[0]并不会影响a[1]
a[0] is a[1]                 # 运行结果:False
a = [ []*1000 ]          # 同理,运行结果:[]。并不能得到含有1000个空list的list。(容易出现坑)
a = [ [] for _ in range(1000) ]  # 正确的定义方式

x = float('han')
x == x, [x] == [x] # 运行结果:False, True 
# 因为list之间比较的时候先比较元素的地址,如果相等则认为相等,当id不相等

Guess you like

Origin blog.csdn.net/xu_yushu/article/details/124579673