Python Nested Lists 嵌套知识概述

Python Nested Lists 嵌套

1.基础内容

1) 嵌套列表是可以包含其他列表的列表,可以用来表示二维或多维的数据结构
嵌套循环(nested loops)是一种常用的遍历嵌套列表中所有元素的方法,需要在外层循环控制行索引,在内层循环控制列索引。

2)嵌套列表可以用下标(index)来访问和修改其中的元素,需要两层或多层的索引

3)嵌套列表可以用len()函数来获取其长度,即其中包含的子列表的个数

4)转置(transpose)是一种将嵌套列表中的行和列互换位置的操作,可以用append()方法来实现

2.重点回顾
  • 长度:利用len()函数来获取列表或者嵌套列表中元素的个数
my_list = [1, 2, 3]
print(len(my_list)) # 3

nested_list = [[1, 2], [3, 4], [5, 6]]
print(len(nested_list)) # 3
print(len(nested_list[0])) # 2

在这个例子中,我们首先使用 len(my_list) 来获取列表 my_list 中元素的个数,结果为 3。然后,我们使用 len(nested_list) 来获取嵌套列表 nested_list 中元素的个数,结果也为 3。最后,我们使用 len(nested_list[0]) 来获取嵌套列表中第一个子列表 [1, 2] 中元素的个数,结果为 2。

需要注意的是,当我们使用 len() 函数来获取嵌套列表中元素的个数时,它只会返回最外层列表中元素的个数。如果想要获取嵌套列表中所有元素(包括子列表中的元素)的总个数,则需要使用循环或递归函数来实现。

  • 索引:用来定位和访问嵌套列表中某个元素或子列表,例如x[0]表示x列表中第一个元素,x2表示x列表中第三个子列表中第二个元素
nested_list = [[1, 2], [3, 4], [5, 6]]
print(nested_list[0]) # [1, 2]
print(nested_list[0][1]) # 2

在这个例子中,我们使用 nested_list[0] 来访问嵌套列表中的第一个子列表 [1, 2]。然后,我们使用 nested_list[0][1] 来访问该子列表中的第二个元素 2。

我们也可以使用负数索引来从后往前访问嵌套列表中的元素。例如:

nested_list = [[1, 2], [3, 4], [5, 6]]
print(nested_list[-1]) # [5, 6]
print(nested_list[-1][-2]) # 5

在这个例子中,我们使用 nested_list[-1] 来访问嵌套列表中的最后一个子列表 [5, 6]。然后,我们使用 nested_list[-1][-2] 来访问该子列表中倒数第二个元素 5。

  • 切片:用来获取嵌套列表中一部分元素或子列表,例如x[1:3]表示x列表中第二个到第三个(不包括)元素组成的新列表,x:表示x所有子列表中第三个元素组成的新列
nested_list = [[1, 2], [3, 4], [5, 6]]
print(nested_list[0:2]) # [[1, 2], [3, 4]]
print(nested_list[0][0:1]) # [1]

在这个例子中,我们首先使用 nested_list[0:2] 来获取嵌套列表中前两个子列表。然后,我们使用 nested_list[0][0:1] 来获取第一个子列表中的第一个元素。

当然也可以使用负数索引和步长来更灵活地控制切片操作。例如:

nested_list = [[1, 2], [3, 4], [5, 6]]
print(nested_list[-2:]) # [[3, 4], [5, 6]]
print(nested_list[::2]) # [[1, 2], [5, 6]]

在这个例子中,我们首先使用 nested_list[-2:] 来获取嵌套列表中最后两个子列表。然后,我们使用 nested_list[::2] 来获取嵌套列表中每隔一个元素的子列表。

  • 转置:用来将嵌套或二维列表中行列互换位置,例如[[1,2],[3,4]]转置后变为[[1,3],[2,4]]

1)我们可以使用 append() 方法和循环来将嵌套或二维列表中的行和列互换位置。这个过程通常被称为转置矩阵:

matrix = [[1, 2], [3, 4], [5, 6]]
transposed_matrix = []
# 先看多少列,获取多少列循环
for i in range(len(matrix[0])):
    # 定义转置的空行
    transposed_row = []
    # 循环列表,将每一行某列都添加到空行中
    for row in matrix:
        transposed_row.append(row[i])
    # 将空行从上到下(从左到右)加到矩阵中
    transposed_matrix.append(transposed_row)
print(transposed_matrix) # [[1, 3, 5], [2, 4, 6]]

在这个例子中,我们首先定义了一个二维列表 matrix 和一个空列表 transposed_matrix。然后,我们使用两层循环来遍历矩阵中的每一列,并将每一列中的元素添加到一个新的列表 transposed_row 中。最后,我们将 transposed_row 添加到 transposed_matrix 中,并打印出转置后的矩阵。

2)使用列表推导式也能实现嵌套或二维列表中的行和列互换位置:

matrix = [[1, 2], [3, 4], [5, 6]]
# 本质和第一种一样,就是缩写为一行,而且用了迭代器生成
transposed_matrix = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(transposed_matrix) # [[1, 3, 5], [2, 4, 6]]
'''
其中:
> for i in range(len(matrix[0])):这个外层循环用来遍历原矩阵中的每一列。
> len(matrix[0]) 表示原矩阵中每一行的元素个数,也就是列数。
> for row in matrix:这个内层循环用来遍历原矩阵中的每一行。
> row[i]:这个表达式用来获取当前行中第 i 列的元素。
> [row[i] for row in matrix]:这个内层列表推导式用来创建一个新列表,其中包含原矩阵中第 i 列的所有元素。
> [[row[i] for row in matrix] for i in range(len(matrix[0]))]:最后,外层列表推导式将内层列表推导式生成的所有列表组合成一个新的二维列表,并赋值给变量 transposed_matrix。
'''

在这个例子中,我们首先定义了一个二维列表 matrix。然后,我们使用嵌套的列表推导式来创建一个新的二维列表 transposed_matrix,其中每一行都是原矩阵中对应列的元素。最后,我们打印出转置后的矩阵。

3)我们也可以使用 zip() 函数来更简洁地实现相同的功能。例如:

matrix = [[1, 2], [3, 4], [5, 6]]
transposed_matrix = list(map(list, zip(*matrix)))
print(transposed_matrix) # [[1, 3, 5], [2, 4, 6]]
'''
其中:
> *matrix:星号操作符用来将二维列表 matrix 中的每一行拆分成单独的参数,并传递给 zip() 函数。
> zip(*matrix):zip() 函数接收多个可迭代对象作为参数,并将它们的对应元素打包成一个个元组。在这里,它将原矩阵中每一列的元素打包成一个元组。
> map(list, zip(*matrix)):map() 函数接收一个函数和一个可迭代对象作为参数,并返回一个新的可迭代对象,其中每个元素都是将原可迭代对象中的对应元素传递给函数后得到的结果。
  在这里,它将 zip(*matrix) 返回的每个元组传递给 list() 函数,将其转换为列表。
> list(map(list, zip(*matrix))):最后,我们使用 list(...) 将结果转换为一个新的二维列表,并赋值给变量 transposed_matrix
'''

在这个例子中,我们首先定义了一个二维列表 matrix。然后,我们使用 zip(*matrix) 来将矩阵中的每一列打包成一个元组,并使用 map(list,…) 将每个元组转换为列表。最后,我们使用 list(…) 将结果转换为一个新的二维列表,并打印出转置后的矩阵。

zip()打包函数参考https://www.runoob.com/python/python-func-zip.html
map()映射函数参考https://www.runoob.com/python/python-func-map.html

3.值得注意
  • 循环嵌套列表的所有行rows
nested_list = [[1, 2], [3, 4, 5], [6, 7]]
for row in nested_list:
        print(row)
  • 循环嵌套列表的所有元素Elements
nested_list = [[1, 2], [3, 4], [5, 6]]
for row in nested_list:
    for element in row:
        print(element)
  • 如何遍历不同嵌套类型的数组,如[[1, 2], [3, [4, 5]], [6]]?

如果想要遍历一个嵌套列表,其中包含更深层次的嵌套列表,那么需要使用递归函数来实现。

def print_nested_list(nested_list):
    for element in nested_list:
        # Python内置函数用来判断一个函数是否是一个已知的类型,类似 type()
        # isinstance(object, classinfo) object 实例对象;classinfo 可以是直接或间接类名、基本类型或者由它们组成的元组。
        # 参考:https://www.runoob.com/python/python-func-isinstance.html
        # 所以这里判断是否为列表类型,是的话就递归,直到探到底
        if isinstance(element, list):
            print_nested_list(element)
        else:
            print(element)

nested_list = [[1, 2], [3, [4, 5]], [6]]
print_nested_list(nested_list)

[扩展]:在Python中,isinstance() 和 type() 都可以用来检查一个对象的类型。但是,它们之间有一些重要的区别。

isinstance() 函数用来检查一个对象是否是一个类或者其子类的实例。例如:

x = 5
print(isinstance(x, int)) # True
print(isinstance(x, float)) # False

在这个例子中,我们使用 isinstance() 函数来检查变量 x 是否是 int 类型或者其子类的实例。结果显示,x 是一个 int 类型的实例。

而 type() 函数用来获取一个对象的确切类型。例如:

x = 5
print(type(x) == int) # True
print(type(x) == float) # False

在这个例子中,我们使用 type() 函数来获取变量 x 的确切类型,并将其与 int 和 float 类型进行比较。结果显示,x 的确切类型是 int。

以下是他们能够区别的使用方法:

class A:
    pass
 
class B(A):
    pass
 
isinstance(A(), A)    # returns True
type(A()) == A        # returns True
isinstance(B(), A)    # returns True
type(B()) == A        # returns False

A 和 B 都是类,其中 B 是 A 的子类。当使用 isinstance() 函数检查一个对象是否是一个类或者其子类的实例时,它会返回 True。因此,当我们使用 isinstance(B(), A) 时,它返回了 True,因为 B() 是一个 B 类型的实例,而 B 是 A 的子类。

而当使用 type() 函数获取一个对象的确切类型时,它只会返回该对象所属类型。因此,当我们使用 type(B()) == A 时,它返回了 False。这是因为虽然 B() 是一个属于类别为 B 的实例,并且 B 类继承自 A 类,但是 B() 实例本身并不属于 A 类型。

所以在这个例子中,由于 B 继承自 A ,所以 B 的实例也被认为是 A 的实例(即 isinstance(B(), A) 返回 True),但是 B() 实例本身并不属于 A 类型(即 type(B()) == A 返回 False)。

总之,当你想要检查一个对象是否属于某个类或者其子类时,应该使用 isinstance() 函数;而当你想要获取一个对象的确切类型时,则应该使用 type() 函数。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值