【蟒蛇】5、数据容器之列表-学Python黑马程序员个人笔记

参考视频

黑马程序员python教程,8天python从入门到精通

数据容器入门

"""
Python中的数据容器:
一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素,
每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。

数据容器根据特点的不同,如:
·是否支持重复元素
·是否可以修改
·是否有序,等
分为5类,分别是:
列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)
"""

"""
以下来源菜鸟教程
"""
# 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
# 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

列表的定义

# 列表的定义
# 基本语法:
# 字面量
# [元素1,元素2,元素3,元素4,...]
#
# 定义变量
# 变量名称 =[元素1,元素2,元素3,元素4,...]
#
# 定义空列表
# 变量名称 = []
# 变量名称 = list()
#
# 列表内的每一个数据,称之为元素
#
# ·以[]作为标识
# ·列表内每一个元素之间用,逗号隔开

# 定义一个列表 list
my_list = ['heima', 'cast', 'python']
print(my_list)
print(type(my_list))

my_list = ['heima', 666, True]
print(my_list)
print(type(my_list))

# 定义一个嵌套的列表
my_list = [[1, 2, 3], [4, 5, 6]]
print(my_list)
print(type(my_list))

列表的下标索引

# 通过下标索引取出对应位置的数据
my_list = ['TOM', 'lily', 'rose']
# 列表[下表索引],从前向后从0开始,每次+1,从后向前从-1开始,每次-1
print(my_list[0])
print(my_list[1])
print(my_list[2])
"""
TOM
lily
rose
"""
# 通过下标索引取出数据(倒序取出)
print(my_list[-1])
print(my_list[-2])
print(my_list[-3])
"""
rose
lily
TOM
"""
# 取出嵌套列表的元素
my_list = [[1, 2, 3], [4, 5, 6]]
print(my_list[1][1])
"""
结果为5
"""

列表的常用操作

mylist = ['cast', 'heima', 'python']
# 1.1查找某元素在列表内的下标索引
index = mylist.index('heima')
print(f'heima在列表中的下标索引值是:{index}')
"""
heima在列表中的下标索引值是:1
"""
# 1.2如果查找某元素不存在,会报错
index = mylist.index('hello')
print(f'heima在列表中的下标索引值是:{index}')  # 报错error

# 2.修改特定下标索引的值
mylist[0] = '传智教育'
print(f'列表被修改元素值后,结果是:{mylist}')
"""
列表被修改元素值后,结果是:['传智教育', 'heima', 'python']
"""

# 3.在指定下标位置插入新元素
mylist.insert(1, 'best')
print(f'列表插入元素后,结果是:{mylist}')
"""
列表插入元素后,结果是:['传智教育', 'best', 'heima', 'python']
"""

# 4.在列表的尾部追加单个新元素
mylist.append('黑马程序员')
print(f'列表在追加了新元素后,结果是:{mylist}')
"""
列表在追加了新元素后,结果是:['传智教育', 'best', 'heima', 'python', '黑马程序员']
"""

# 5.在列表的尾部追加一批新元素
mylist2 = [1, 2, 3]
mylist.extend(mylist2)
print(f'列表在追加了新元素后,结果是:{mylist}')
"""
列表在追加了新元素后,结果是:['传智教育', 'best', 'heima', 'python', '黑马程序员', 1, 2, 3]
"""

# 6.删除指定下标索引的元素(2种方式)
mylist = ['cast', 'heima', 'python']
# 6.1方式1:del 列表[下表]
del mylist[2]
print(f'列表删除元素后结果是:{mylist}')
"""
列表删除元素后结果是:['cast', 'heima']
"""
# 6.2 方式2:列表.pop(下标)可以返回给新的变量
mylist = ['cast', 'heima', 'python']
element = mylist.pop(2)
print(f'通过pop方法取出元素后列表内容:{mylist},取出的元素是:{element}')
"""
通过pop方法取出元素后列表内容:['cast', 'heima'],取出的元素是:python
"""

# 7.删除某元素在列表中的第一个匹配项
mylist = ['cast', 'cast', 'heima', 'heima', 'python']
mylist.remove('cast')
print(f'通过remove方法移除元素后,列表的结果是:{mylist}')
"""
通过remove方法移除元素后,列表的结果是:['cast', 'heima', 'heima', 'python']
"""

# 8.清空列表
mylist.clear()
print(f'列表被清空了,结果是{mylist}')
"""
列表被清空了,结果是[]
"""

# 9.统计某元素在列表中的数量
mylist = ['cast', 'cast', 'heima', 'heima', 'python']
count = mylist.count('heima')
print(f'列表中heima的数量是:{count}')
"""
列表中heima的数量是:2
"""

# 10.统计列表内全部元素的数量
mylist = ['cast', 'cast', 'heima', 'heima', 'python']
count = len(mylist)
print(f'列表所有元素的数量是:{count}')
"""
列表所有元素的数量是:5
"""

# 经过上述对列表的学习,可以总结出列表有如下特点:
# 可以容纳多个元素(上限为2**63—1、9223372036854775807个)
# 可以容纳不同类型的元素(混装)
# 数据是有序存储的(有下标序号)
# 允许重复数据存在
# 可以修改(增加或删除元素等)


"""
以下来源菜鸟教程
"""
# 11反向列表中元素
mylist = ['cast', 'cast', 'heima', 'heima', 'python']
mylist.reverse()
print(f'列表反转后结果是:{mylist}')
"""
列表反转后结果是:['python', 'heima', 'heima', 'cast', 'cast']
"""

# 12对原列表进行排序
# 在Python中,list 列表的 sort() 方法用于对列表进行就地排序,
# 即直接修改原列表而不返回新的列表。sort() 方法有两种用法:
# 在这两种用法中,sort() 方法都会直接修改原始列表,并根据指定的规则对其进行排序。
# 12.1
my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
new_list = my_list.sort()
print(new_list)  # 输出:[1, 1, 2, 3, 4, 5, 5, 6, 9]

# 12.2
# 通过 key 参数和 reverse 参数,你可以指定自定义的排序顺序。key 参数用于指定一个函数,
# 该函数将作用于列表中的每个元素,根据函数的返回值进行排序。reverse 参数默认为 False,
# 如果设置为 True,则列表将按降序排列。
my_list = ['apple', 'banana', 'cherry', 'durian', 'vegetable']
my_list.sort(key=len)
print(my_list)  # 输出:['apple', 'banana', 'cherry', 'durian', 'vegetable']

my_list.sort(key=len, reverse=True)
print(my_list)  # 输出:['vegetable', 'banana', 'cherry', 'durian', 'apple']

# 13复制列表
# 在Python中,list 的 copy() 方法用于创建列表的浅拷贝。浅拷贝会创建一个新列表对象,
# 该对象包含原始列表中的相同元素的引用,而不是元素的副本。这意味着对原始列表或其内部元素
# 的更改不会影响到拷贝后的列表。
original_list = [1, 2, 3, 4, 5]
copied_list = original_list.copy()

print(original_list)  # 输出:[1, 2, 3, 4, 5]
print(copied_list)    # 输出:[1, 2, 3, 4, 5]

# 修改原始列表
original_list[0] = 100
print(original_list)  # 输出:[100, 2, 3, 4, 5]
print(copied_list)    # 输出:[1, 2, 3, 4, 5],拷贝后的列表不受影响


def reverseWords(sentence):
    # 通过空格将字符串分隔符,把各个单词分隔为列表
    input_words = sentence.split(' ')
    # 翻转字符串
    # 假设列表 list = [1,2,3,4],
    # list[0]=1, list[1]=2 ,而 -1 表示最后一个元素 list[-1]=4 ( 与 list[3]=4 一样)
    # inputWords[-1::-1] 有三个参数
    # 第一个参数 -1 表示最后一个元素
    # 第二个参数为空,表示移动到列表末尾
    # 第三个参数为步长,-1 表示逆向
    input_words = input_words[-1::-1]
    # 重新组合字符串
    output = ' '.join(input_words)
    return output


if __name__ == '__main__':
    result = input('请输入要反转的句子:')
    rw = reverseWords(result)
    print(rw)

列表的常用操作-从嵌套列表中抽取指定列

import pandas as pd

# 假设`my_list`是一个如下所示的嵌套列表,该嵌套列表可以用来表示数学上的矩阵,
# 如果要取出矩阵第一列的元素构成一个列表,我们可以这样写。
my_list = [
    [1, 1, 2, 2],
    [5, 6, 7, 8],
    [3, 3, 4, 4],
]
col1, *_ = zip(*my_list)
# 这里我们会得到一个如下所示的列表,刚好是矩阵的第一列
print(list(col1))  # [1, 5, 3]

# 以此类推,如果想取出矩阵第二列的元素构成一个列表,可以用如下所示的方法。
_, col2, *_ = zip(*my_list)
print(list(col2))  # [1, 6, 3]

# 至此,如果要实现矩阵的转置操作,我们也可以按照上面的思路写出下面的代码。
print([list(x) for x in zip(*my_list)])
# [[1, 5, 3], [1, 6, 3], [2, 7, 4], [2, 8, 4]]

# 也可以用pandas
df = pd.DataFrame(my_list)
print(df.iloc[:, 0].tolist())  # [1, 5, 3]
print(df.iloc[:, 1].tolist())  # [1, 6, 3]
print(df.T.values.tolist())  # [[1, 5, 3], [1, 6, 3], [2, 7, 4], [2, 8, 4]]

列表的常用操作-处理列表中的空值和零值

# 处理列表中的空值和零值
# 假设列表对象对应的变量名为`my_list`,如果列表中有空值(`None`)和零值,我们可以用下面的方式去掉空值和零值。
my_list = ['cast', 'heima', 'python', 'heima', 'heima', 'python', '', 0]
print(list(filter(bool, my_list)))  # ['cast', 'heima', 'python', 'heima', 'heima', 'python']
print(my_list)  # ['cast', 'heima', 'python', 'heima', 'heima', 'python', '', 0]

# 对应的列表生成式语法如下所示。
print([x for x in my_list if x])  # ['cast', 'heima', 'python', 'heima', 'heima', 'python']

列表的常用操作-对两个或多个列表对应元素进行操作

# Python内置函数中的`map`函数可以对一个可迭代对象中的元素进行“映射”操作,
# 这个函数在批量处理数据时非常有用。但是很多人都不知道,这个函数还可以作用于多个可迭代对象,
# 通过传入的函数对多个可迭代对象中的对应元素进行处理,如下所示。
my_list = [11, 13, 15, 17]
thy_list = [2, 4, 6, 8, 10]
new_list = list(map(lambda x, y: x + y, my_list, thy_list))
print(new_list)  # [13, 17, 21, 25]

# 同样的操作也可以用`zip`函数配合列表生成式来完成。
my_list = [11, 13, 15, 17]
thy_list = [2, 4, 6, 8, 10]
print([x + y for x, y in zip(my_list, thy_list)])  # [13, 17, 21, 25]

列表的常用操作-截断列表元素

my_list = ['cast', 'heima', 'python', 'heima', 'heima', 'python']
# 截断列表元素
my_list = my_list[:3]
my_list = my_list[2:]
# print(my_list)  # ['python']

del my_list[3:]
del my_list[:2]
print(my_list)  # ['python']

# 哪种方法更好?
# 性能: 从性能角度看,直接修改原列表的操作(使用del)可能会略优于创建新列表的操作,因为后者涉及到额外的内存分配。但这点差异在大多数现代计算环境中微不足道,除非处理极大规模数据集。
# 内存使用: 如果你不需要保留原列表,则使用切片创建新列表(如my_list = my_list[:3])会占用额外的内存空间。
# 原列表是否需要保持不变: 如果需要保留原列表的完整性,应该使用切片创建新列表。
# 代码可读性: 选择最能清晰表达你意图的方法也很重要。比如,如果你的目的是明确地删除某些元素,使用del可能更直观。

列表的常用操作-按最长列表实现zip操作

my_list = ['cast', 'heima', 'python', 'heima', 'heima', 'python']
# 按最长列表实现zip操作
# 列表中元素的个数是由`zip`函数中长度最小的可迭代对象决定的
print(list(zip('abc', [1, 2, 3, 4])))  # [('a', 1), ('b', 2), ('c', 3)]
# 如果希望由`zip`函数中长度最大的可迭代对象来决定最终迭代出的元素个数
from itertools import zip_longest
print(list(zip_longest('abc', [1, 2, 3, 4])))  # [('a', 1), ('b', 2), ('c', 3), (None, 4)]
# iteration 迭代

列表的常用操作-深拷贝和浅拷贝

import copy
my_list = ['cast', 'heima', 'python', 'heima', 'heima', 'python']
# 快速拷贝一个列表
# 如果希望快速拷贝一个列表对象,可以通过切片操作来实现,但是切片操作仅实现了浅拷贝,简单的说就是切片创建了新的列表对象,
# 但是新列表中的元素是和之前的列表共享的。如果希望实现深拷贝,可以使用`copy`模块的`deepcopy`函数。
# 浅拷贝
# thy_list = my_list[:3]
# print(thy_list)  # ['cast', 'heima', 'python']
# # 或者
# import copy
# thy_list = copy.copy(my_list)
#
# # 深拷贝
# import copy
# thy_list = copy.deepcopy(my_list)

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 在Python中,深拷贝(deep copy)和浅拷贝(shallow copy)是两种复制对象的方式,
# 它们在处理对象的嵌套结构(如列表中含有其他列表、字典等复杂数据结构)时表现出不同行为。

# 浅拷贝(Shallow Copy)
# 浅拷贝创建了一个新对象,这个新对象的顶层结构是原对象的精确副本,但对于其中嵌套的子
# 对象(如列表中的列表、字典的值是另一个字典等),浅拷贝只会复制它们的引用,而不是递归地
# 复制这些子对象本身。这意味着原对象和拷贝对象共享同一层级下子对象的内存地址,改变其中一个的子对象会影响到另一个。

original_list = [[1, 2], [3, 4]]
shallow_copy = copy.copy(original_list)

original_list[0][0] = 'X'
print(original_list)  # [['X', 2], [3, 4]]
print(shallow_copy)  # [['X', 2], [3, 4]]
# 在上面的例子中,修改original_list的第一个子列表的第一个元素,也影响到了shallow_copy对应的元素,因为它们指向同一个子列表。

# 深拷贝(Deep Copy)
# 深拷贝也会创建一个新的对象,但它会递归地复制原对象中所有层级的元素,包括所有的子对象。这意味着无论对象
# 的嵌套结构有多深,深拷贝都会创建完全独立的拷贝,修改其中一个对象的任何部分都不会影响到另一个对象。

original_list = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(original_list)

original_list[0][0] = 'X'
print(original_list)  # [['X', 2], [3, 4]]
print(deep_copy)      # [[1, 2], [3, 4]]

# 总结
# 浅拷贝适用于顶层结构简单复制且不希望修改顶层结构的情况,或者确定不会修改嵌套对象时。
# 深拷贝则在需要完全独立的拷贝,包括所有嵌套结构时使用,尤其当后续操作可能修改深层次的数据结构时。

列表的常用操作-统计列表元素出现次数

my_list = ['cast', 'heima', 'python', 'heima', 'heima', 'python']

# 统计列表元素出现次数
# 方法一:(更高效)
from collections import Counter

dict(Counter(my_list))
print(Counter(my_list))  # Counter({'heima': 3, 'python': 2, 'cast': 1})

# 方法二:(效率低),每次count()调用都要遍历整个列表
print({x: my_list.count(x) for x in set(my_list)})  # {'cast': 1, 'python': 2, 'heima': 3}

# 方法三
from itertools import groupby

print({key: len(list(group)) for key, group in groupby(sorted(my_list))})  # {'cast': 1, 'heima': 3, 'python': 2}

列表的常用操作案例

# 有一个列表,内容是:[21,25,21,23,22,20],记录的是一批学生的年龄
#
# 请通过列表的功能(方法),对其进行
# 1.定义这个列表,并用变量接收它
# 2.追加一个数字31,到列表的尾部
# 3.追加一个新列表[29,33,30],到列表的尾部
# 4.取出第一个元素(应是:21)
# 5.取出最后一个元素(应是:30)
# 6.查找元素31,在列表中的下标位置

# 定义这个列表,并用变量接收他,

student_age = [21, 25, 21, 23, 22, 20]

# 追加一个数字31,到列表的尾部
student_age.append(31)
print(f'学生年龄列表在追加了数字31后,结果是:{student_age}')

# 追加一个新列表,到列表的尾部
student_age2 = [29, 33, 30]
student_age.extend(student_age2)
print(f'学生年龄列表在追加了新列表后,结果是:{student_age}')

# 取出第一个元素
element = student_age.pop(0)
print(f'学生年龄列表在取出第一个元素后,结果是:{student_age}, 取出的元素是{element}')

# 取出最后一个元素
element2 = student_age.pop(-1)
print(f'学生年龄列表在取出最后一个元素后,结果是:{student_age}, 取出的元素是{element2}')

# 查找元素31,在列表中的下标位置
index = student_age.index(31)
print(f'查找元素31在列表中的下标位置是:{index}')

列表的循环遍历


# index = 0
# while index < len(列表):
#     元素 = 列表[index]
#     对元素进行处理
#     index += 1

"""
演示对list列表的循环,使用while和for循环2中方式
"""


def list_while_func():
    """
    使用while循环遍历(依次取出并处理)列表的演示函数
    :return: None
    """
    my_list = ['传智教育', '黑马程序员', 'Python']
    # 循环控制变量通过下标索引来控制,默认0
    # 每一次循环将下标索引变量+1
    # 循环条件:下标索引变量 < 列表的元素数量

    # 定义一个变量来标记列表的下标
    index = 0      # 初始值为0
    while index < len(my_list):
        # 通过index变量取出对应下标的元素
        element = my_list[index]
        print(f'列表的元素:{element}')

        # 至关重要,将循环变量(index)每一次循环都+1
        index += 1


def list_for_func():
    """
    使用for循环遍历列表的演示函数
    :return: None
    """
    my_list = [1, 2, 3, 4, 5]
    # for 临时变量 in 数据容器
    for element in my_list:
        print(f'列表的元素:{element}')


# 调用函数
list_while_func()
list_for_func()


# while循环和for循环,都是循环语句,但细节不同:
#
# ·在循环控制上:
# ·while循环可以自定循环条件,并自行控制
# *for循环不可以自定循环条件,只可以一个个从容器内取出数据
#
# ·在无限循环上:
# ·while循环可以通过条件控制做到无限循环
# ·for循环理论上不可以,因为被遍历的容器容量不是无限的
#
# *在使用场景上:
# *while循环适用于任何想要循环的场景
# ·for循环适用于,遍历数据容器的场景或简单的固定次数循环场景

列表的循环遍历案例

# 定义一个列表,内容是:[1,2,3,4,5,6,7,8,9,10]
# 遍历列表,取出列表内的偶数,并存入一个新列表对象中
# 使用while循环和for循环各操作一次
# 通过while循环,从列表:[1,2,4,5,6,8,9,16取出偶数,组成新列表:[2,4,6,8,10]
# 通过for循环,从列表:[1,2,3,4,5,6,7,8,9,10]中取出偶数,组成新列表:[2,4,6,8,10]


def list_while_func():
    """
    使用while循环遍历(依次取出并处理)列表的演示函数
    :return:
    """
    my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    new_list = []
    index = 0
    while index < len(my_list):
        # 通过index变量取出对应下标的元素
        if my_list[index] % 2 == 0:
            new_list.append(my_list[index])  # 需要添加my_list[index]而不是整个my_list
        # 至关重要,将循环变量(index)每一次循环都+1
        index += 1

    print(f'组成的新列表是:{new_list}')


list_while_func()


def list_for_func():
    my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    new_list_for = []

    for num in my_list:
        if num % 2 == 0:
            new_list_for.append(num)
    print(f"通过for循环,从列表{my_list}中取出偶数, 组成新列表:{new_list_for}")


list_for_func()

列表的循环遍历案例2

original_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
new_list_while = []
index = 0

while index < len(original_list):
    if original_list[index] % 2 == 0:
        new_list_while.append(original_list[index])
    index += 1

print("使用while循环生成的新列表:", new_list_while)
"""
使用while循环生成的新列表: [2, 4, 6, 8, 10]
"""

# 错误代码


def list_while_func():
    """
    使用while循环遍历(依次取出并处理)列表的演示函数
    :return:
    """
    my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    new_list = []
    index = 0
    while index < len(my_list):
        # 通过index变量取出对应下标的元素
        if my_list[index] % 2 == 0:
            new_list.append(my_list)
        # 至关重要,将循环变量(index)每一次循环都+1
        print(f'组成的新列表是:{new_list}')

        index += 1


list_while_func()

# 在你的代码中,你希望取出列表中的偶数,但是在处理偶数时有一点小错误。
# 你的代码中,你把整个my_list列表追加到new_list中,而不是仅追加当前偶数。
# 以下是已修复的代码,现在,只有偶数会被追加到 new_list 中。


def list_while_func():
    """
    使用while循环遍历(依次取出并处理)列表的演示函数
    :return:
    """
    my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    new_list = []
    index = 0
    while index < len(my_list):
        # 通过index变量取出对应下标的元素
        if my_list[index] % 2 == 0:
            new_list.append(my_list[index])
        # 至关重要,将循环变量(index)每一次循环都+1
        index += 1
    print(f'组成的新列表是:{new_list}')


list_while_func()

"""
组成的新列表是:[2, 4, 6, 8, 10]
"""
# 显示“从外部作用域隐藏名称 'index'”
# 我明白了,你遇到了 linter 或静态代码分析工具(例如 Flake8、pylint 等)的提示。
# 如果你想隐藏 'index',你可以使用 for 循环来遍历列表,而不是使用 while 循环。
# 这样,index 变量就会在 for 循环的局部作用域内,不会影响到函数的其余部分。

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 3415226167@qq.com
资源 相册