Python语法查缺补漏 第四章:序列、集合和字典

一、可变类型和不可变类型

1. 可变类型

即可以对该类型对象中保存的元素值做修改。如列表、字典都是可变类型。

对于可变类型对象来说,内容一样,内存地址也不同;只改变对象中的某个元素,内存不会改变。

2. 不可变类型

即该类型对象所保存的元素值不允许修改,只能通过给对象整体赋值来修改对象所保存的数据。但此时实际就是创建了一个新的不可变类型的对象,而不是修改原对象的值。如数字、字符串、元组都是不可变类型。

对于数字和字符串来说,内容一样内存地址就是一样的;而对于元组来说,即便内容一样,内存地址也不同。

二、列表

1. 元素深复制

(1) 通过元素截取实现深复制

ls1 = [1, 2, 3]
ls2 = ls1[:]
ls1[2] = 0
print(ls1, ls2)

输出为:

[1, 2, 0] [1, 2, 3]

(2) deepcopy()

import copy

ls1 = [1, 2, 3]
ls2 = copy.deepcopy(ls1)
ls1[2] = 0
print(ls1, ls2)

输出为:

[1, 2, 0] [1, 2, 3]

2. 查找元素

ls.index(x)
通过列表中的index方法可以根据指定值查找第一个匹配的列表元素的位置。

3. 插入元素

ls.insert(index, x)
将元素x插入的ls列表下表为index的位置上。

4. 删除元素

del ls[index]
使用del语句可以删除ls列表中下标为index的这个元素。
如果要删除列表中的连续多个元素,也可以截取列表中的这些元素并将其幅为空列表。

5. 最大值和最小值

max(ls)min(ls)可以获取一个列表中最大元素和最小元素的值。

6. 统计元素出现次数

ls.count(x)
使用count方法可以统计某个值在列表中出现的次数。

7. 元素排序

ls.sort(key=None, reverse=False)
使用列表中的sort方法可以对列表中的元素按照指定规则进行排序。其中key接收一个函数,通过该函数获取用于排序时比较大小的数据;reverse指定将列表中的元素按升序(False,默认值)还是降序(True)排列。

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def __str__(self):
        return '姓名为:%s,分数为:%d'%(self.name, self.score)

ls = [Student('张三', 82), Student('李四', 76), Student('王五', 99)]
ls.sort(key=lambda stu:stu.score, reverse=True)  # 将对象的score属性作为用于排序时比较大小的依据
for stu in ls:
    print(stu)

输出为:

姓名为:王五,分数为:99
姓名为:张三,分数为:82
姓名为:李四,分数为:76

这个例子中sort方法的位置参数key=lambda stu:stu.score表示将lambda函数传入对象的score属性作为返回值。

这里key也可以传入一个元组,比如key=lambda stu:(stu.score, stu.name),这样排序会依据元组中靠前元素作为第一指标,在遇到相等情况才会考虑后一指标。比如在本情况下,列表会先根据score进行排序,在遇到score相等的情况下才会根据name排序。

也可以先定义一个函数,可以达成一样的作用。

def getscore(stu):
    return stu.score

ls = [Student('张三', 82), Student('李四', 76), Student('王五', 99)]
ls.sort(key=getscore, reverse=True)
for stu in ls:
    print(stu)

输出为:

姓名为:王五,分数为:99
姓名为:张三,分数为:82
姓名为:李四,分数为:76

三、元组

1. 创建元祖

如果使用()创建的元组中只包含单个元素,则需要在这唯一的一个元素后面添加逗号,否则小括号会被认为是括号元素符,而不会被认为是在创建元组。

a, b = (784,), (784)
print(a, type(a))
print(b, type(b))

输出为:

(784,) <class ‘tuple’>
784 <class ‘int’>

2. 拼接元组

与列表一样,可以使用拼接运算符“+”和重复元素符“*”。

3. 最大值与最小值

max(t)min(t)可以获取一个元组中最大元素和最小元素的值。

四、集合

1. 创建

可以使用一对大括号{}或者set函数创建集合,如果要创建空集合则只能使用set函数(空的{}是空字典)。

集合中不能包含有重复值的元素,如果创建集合或向集合中插入元素时,指定的元素具有重复值,则集合会自动过滤掉重复值的元素,使得每种取值的元素只保留一个。

2. 插入集合元素

  1. s.add(x) 其作用是把x作为一个新的元素插入到集合s中,其中x必须是一个可哈希对象。
  2. s.update(x) 其作用是把x拆分成多个元素后再将这多个元素插入到集合中,其中x必须是一个可迭代对象。
s1, s2 = set(), set()
string = 'Python'
s1.add(string)
# s1.add([1, 2, 3])
s2.update(string)
# s2.update(3)
print(s1)
print(s2)

输出为:

{‘Python’}
{‘y’, ‘P’, ‘h’, ‘o’, ‘t’, ‘n’}

注意: 其中s1不可以add[1, 2, 3]因为列表不是可哈希对象;s2不可以update整数3是因为整数不是可迭代对象。

3. 集合的运算

(1) 交集、并集和差集

  1. s1.intersection(s2) 计算s1和s2的交集并返回
  2. s1.union(s2) 计算s1和s2的并集并返回
  3. s1.difference(s2) 计算s1和s2的差集(在s1中但不在s2中的元素的集合)并返回
  4. s1.symmetric_difference(s2) 计算s1和s2的对称差集(只包含s1中或s2中的元素的集合)并返回

(2) 子集和父集

  1. s1.issubset(s2) 如果s1是s2的子集,返回True;否则返回False
  2. s1.issuperset(s2) 如果s1是s2的父集,返回True;否则返回False

五、字典

1. 初始化字典元素

d.fromkeys(seq, value) 其中,d是一个已创建的字典对象;seq是一个包含了字典所有键名的序列;value是一个可选参数,其指定了各元素的初始值,默认情况下所有元素的值被赋为None。最终,fromkeys方法会返回一个新的字典。

d = {}.fromkeys(['name', 'sno', 'score'], 'Unknown')

输出为:

{‘name’: ‘Unknown’, ‘sno’: ‘Unknown’, ‘score’: ‘Unknown’}

注意: 如果使用的字典对象中原来已有其他元素,则调用fromkeys方法后原有的元素都会被清除。

2. 修改/插入元素

给指定键的元素赋值时,如果该键在字典中已存在,则会将该键对应的元素值做修改;如果该键在字典中不存在,则会在字典中插入一个新元素。

另外,用字典中的update方法可以一次性修改或插入多个元素。

  1. d1.update(d2) 用另一个字典对象d2的元素修改或插入字典对象d1的元素。
  2. d.update(键1=值1, 键2=值2, ... , 键N=值N) 用键值列表修改或插入字典对象d的元素。

3. 删除元素

  1. del d[key] 可以删除字典d中键为key的元素。
  2. d.pop(key, default) 从字典d中删除键为key的元素并返回该元素的值,如果d中不存在键为key的元素,则返回default参数的值(如果有的话)。

4. 判断字典中是否存在键

  1. d.get(key, default=None) 作用是从字典d中获取键为key的元素的值并返回。如果在字典d中不存在键为key的元素,则返回default参数的值(默认为None)。
  2. 使用成员运算符in:key in d,返回True或False

5. 拼接字典

假设d1和d2是带拼接的两个字典,dMerge用于保存拼接后的字典。

  1. dMerge = dict(d1, **d2)
  2. dMerge = d1.copy()
    dMerge.update(d2)

6. 字典中元素个数

len(d) 和列表一样,可以返回字典中的元素个数。

7. 清除字典中所有元素

d.clear() 可以一次将字典中的所有元素都清除。

8. 获取字典中键/值集合

  1. d.keys() 返回一个包含d中所有键的对象;
  2. d.values() 返回一个包含d中所有值的对象;
  3. d.items() 返回一个按(键,值)方式遍历得对象。
d = dict(zip(['one', 'two'], [1, 2]))
print([key for key in d.keys()])  # 键
print([value for value in d.values()])  # 值
print([item for item in d.items()])  # 键和值构成的元组
for key, value in d.items():  # 分别获取一组键和值
    print(key, value)

[‘one’, ‘two’]
[1, 2]
[(‘one’, 1), (‘two’, 2)]

one 1
two 2

注意: 如果直接在字典上做遍历,则每次只能获取到一个元素的键,然后再通过键来获取该元素的值。

六、切片

new_ls = ls[beg:end:step]

七、列表生成表达式

1. for循环+if条件句

ls = [x ** 2 for x in range(0, 10) if x%2==1]
print(ls)

输出为:

[1, 9, 25, 49, 81]

2. 多重for循环

ls1, ls2 = [0, 1], [2, 3]
ls = [x*y for x in ls1 for y in ls2]
print(ls)

输出为:

[0, 0, 2, 3]

八、生成器

当一个列表中包含大量元素时,如果一次性生成这些元素并保存在列表中,将占用大量的内存空间(有的情况下可用内存甚至无法满足存储需求)。

对于这个问题,我们可以用过生成器(generator)来解决,即根据需要计算并获取列表中某个元素的值。

1. 使用for循环的生成器

将列表生成表达式中的一对中括号改成小括号即可得到生成器,对于生成器对象,也可以像其他可迭代对象一样使用for循环遍历对象中的每一个元素。

g = (x**2 for x in range(0, 10))
for i in g:
    print(i, end=' ')
print(type(g))

输出为:

0 1 4 9 16 25 36 49 64 81 <class ‘generator’>

2. 使用yield关键字的生成器

当在循环中遇到yield关键字的时候,会直接返回一个值,相当于return。但return之后函数会中断,yield之后函数会继续执行。

def faclist(n):
    result = 1
    for i in range(2, n + 2):  # i是在2到n+1的范围内以此取值的
        yield result  # 遇到yield会暂停执行并返回result,下次执行时继续在此处开始执行
        result *= i

for i in faclist(10):
    print(i, end=' ')
print(type(faclist(10)))

输出为:

1 2 6 24 120 720 5040 40320 362880 3628800 <class ‘generator’>

注意: 这里range(2, n+2)表明循环是从2到n+1的,但其实循环范围是2到n。看结果最后一项是3628800也可以看出只计算了10的阶乘。没有计算第11项的原因是,在执行最后一个循环时,yield先把最后一次的结果返回了,才计算了第十一项。

九、迭代器

1. 迭代器的定义

可直接使用for循环遍历的对象统称为可迭代对象(Iterable)。

迭代器(Iterator)是指有__iter__()方法和__next__()方法的对象,可以通过next函数不断获取下一个值。并不是所有可迭代对象都是迭代器。

可以使用isinstance方法判断一个对象是否是可迭代对象或迭代器。

from _collections_abc import Iterable, Iterator

ls = [1, 2, 3, 4, 5]
g = (x for x in range(1,6))
print(isinstance(ls, Iterable), isinstance(ls, Iterator))
print(isinstance(g, Iterable), isinstance(g, Iterator))

输出为:

True False
True True

2. 迭代器的使用

iter(iterable) 对于可迭代对象,iter函数可以得到迭代器。
next(iterator) 对于迭代器,可以使用next函数不断获取下一个元素,当所有元素都获取完毕后再调用next函数,就会引发StopIteration异常。

ls = [1, 2]
it = iter(ls)
print('第一个元素:', next(it))
print('第二个元素:', next(it))
# print('第三个元素', next(it))  # 取消注释就会引发StopIteration异常

输出为:

第一个元素: 1
第二个元素: 2

3. 自定义迭代器

如果我们要自己实现一个类,使得该类的对象是迭代器,则需要在类中实现__iter__方法和__next__这两个方法。

from _collections_abc import Iterator

class Faclist:
    def __init__(self):
        self.n = 1  # 初始化元素值
        self.fac = 1  # 初始化阶乘结果

    def __next__(self):
        self.fac *= self.n  # 计算阶乘
        self.n += 1  # 乘数加一
        return self.fac

    def __iter__(self):  # 该方法用来返回一个迭代对象
        return self

facs = Faclist()
print('Faclist是迭代器:', isinstance(facs, Iterator))
for i in range(1, 6):
    print(next(facs), end=' ')

输出为:

Faclist是迭代器: True
1 2 6 24 120

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值