Python 工匠 第三章 容器类型

news/2024/11/29 1:28:35/

基础知识

列表常用操作

list(iterable)可以将任何一个可迭代对象转换成列表

>>> from collections.abc import Iterable
>>> isinstance("ABC", Iterable)
True
>>> list("ABC")
['A', 'B', 'C']
>>> chars = list("ABC")
>>> del chars[1:]
>>> chars
['A']

遍历时换取下标

>>> for i, c in enumerate(chars, start=2):
...     print(i, c)
...
2 A
3 B
4 C

列表推导式

>>> nums = [1, 2, 3, 4]
>>> [n * 10 for n in nums if n % 2 == 0]
[20, 40]

不要写太复杂的列表推导式(不易读)

不要把推导式当作代码量更少的循环

[process(task) for task in tasks]

推导式的核心在于可以返回值,上面这种更应该直接循环

理解列表的可变性

mutable:list, dict, set
immutable: int, float, str, bytes, tuple

python 在进行函数调用传参时,传递的是“变量所指对象的引用”(pass-by-object-reference)。

常用元组操作

>>> a = 1, 2, 3
>>> a
(1, 2, 3)
>>> type(a)
<class 'tuple'>

逗号才是解释器判定元组的依据

函数返回多个结果,就是返回元组

没有元组推导式

>>> nums = (1, 2, 3, 4, 5, 6)
>>> results = (n * 10 for n in nums if n % 2 == 0)
>>> results
<generator object <genexpr> at 0x000001D7ADE90E40>
>>> tuple(results) # generator对象仍是可迭代类型
(20, 40, 60)

存放结构化数据

和列表不同,在一个元组里出现类型不同的值是常见的事情

>>> user_info = ("Tom", 24, True)

具名元组 namedtuple

user_info[1] 虽然能取到24, 但是不知道这个数字时年龄还是其他的意思

>>> from collections import namedtuple
>>> UserInfo = namedtuple('UserInfo', 'name, age, vip')
>>> user1 = UserInfo('Alice', 21, True)
>>> user1[1]
21
>>> user1.age
21

或者使用typing.NamedTyple + 类型注解

>>> from typing import NamedTuple
>>> class UserInfo(NamedTuple):
...     name:str
...     age:int
...     vip:bool
...
>>> user2 = UserInfo('Bob', 12, False)
>>> user2.age
12

字典常用操作

遍历字典

>>> movies = {'name': 'Burning', 'year': 2018}
>>> for key in movies:
...     print(key, movies[key])
...
name Burning
year 2018
>>> for key, value in movies.items():
...     print(key, value)
...
name Burning
year 2018

访问不存在的字典键

>>> movies["rating"]
Traceback (most recent call last):File "<stdin>", line 1, in <module>
KeyError: 'rating'
# 1
>>> if 'rating' in movies:
...     rating = movies['rating']
... else:
...     rating = 0
...
>>> rating
0
# 2
>>> try:
...     rating = movies['rating']
... except KeyError:
...     rating = 0
...
>>> rating
0
# 3
>>> movies.get('rating', 0)
0

使用setdefault取值并修改

>>> try:
...     movies['rating'] += 1
... except KeyError:
...     movies['rating'] = 0
...
>>> movies
{'name': 'Burning', 'year': 2018, 'rating': 0}

or

>>> movies = {'name': 'Burning', 'year': 2018}
>>> movies.setdefault('rating', 0) # rating不存在,则设为0
0
>>> movies
{'name': 'Burning', 'year': 2018, 'rating': 0}
>>> movies.setdefault('rating', 1) # rating存在,则返回其值
0

使用pop方法删除不存在的键

可以使用del d[key] 删除字典某个键,如果要删除的键不存在,则KeyError
or
d.pop(key, None) 若key存在,返回key对应的value; 反之返回None

当然,pop的主要用途是取出键对应的值

字典推导式

>>> d1 = {'foo': 3, 'bar': 4}
>>> {key: value * 10 for key, value in d1.items() if key == 'foo'}
{'foo': 30}

字典的有序性和无序性

python3.7(3.6)后字典有序
from collections import OrderdDict

相比自带的字典有序,OrderDict有以下特点:

  1. 名字就体现其有序性
  2. 比较时键的顺序有影响(普通字典比较时忽略顺序)
  3. .move_to_end()等普通字典没有的方法

集合常用操作

无序可变

不可变集合 frozenset

.add() 添加新成员

>>> f_set = frozenset(['foo', 'bar'])
>>> f_set
frozenset({'bar', 'foo'})
>>> f_set.add('apple')
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'add'

集合运算

交集 &
并集 |
差集 - (前一个集合有,后一个集合没有的东西)
还有 symmetric_difference, issubset等

集合只可以存放可哈希对象

>>> invalid_set = {'foo', [1, 2, 3]}
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

可哈希性

不可变的内置类型,如str, int, tuple, frozenset等,都是可哈希的
可变的内置类型,如dict, list等,都是不可哈希的
对于不可变容器类型,如tuple, forzenset等,仅当其所有成员都不可变时,它是可哈希的
用户定义的类型默认都是可哈希的

深拷贝和浅拷贝

>>> nums = [1, 2, 3, 4]
>>> nums_copy = nums # 只是改变指向,没有任何拷贝操作
>>> nums[2] = 30
>>> nums, nums_copy
([1, 2, 30, 4], [1, 2, 30, 4])

深浅拷贝区别:浅拷贝无法解决嵌套对象被修改的问题!

浅拷贝

1 copy.copy()

>>> import copy
>>> nums = [1, 2, 3, 4]
>>> nums_copy = copy.copy(nums)
>>> nums[2] = 30
>>> nums, nums_copy
([1, 2, 30, 4], [1, 2, 3, 4])

2 推导式

>>> d = {'foo': 1}
>>> d2 = {key: value for key, value in d.items()}
>>> d['foo'] = 2
>>> d, d2
({'foo': 2}, {'foo': 1})

3 各容器类型的内置函数

>>> d = {'foo': 1}
>>> d2 = dict(d.items())
>>> d, d2
({'foo': 1}, {'foo': 1})>>> nums = [1, 2, 3, 4]
>>> nums_copy = list(nums)
>>> nums, nums_copy
([1, 2, 3, 4], [1, 2, 3, 4])

4 全切片

>>> nums = [1, 2, 3, 4]
>>> nums_copy = nums[:]
>>> nums, nums_copy
([1, 2, 3, 4], [1, 2, 3, 4])

5 某些类型自提供浅拷贝

>>> nums = [1, 2, 3, 4]
>>> nums_copy = nums.copy()
>>> nums, nums_copy
([1, 2, 3, 4], [1, 2, 3, 4])>>> d = {'foo': 1}
>>> d2 = d.copy()
>>> d, d2
({'foo': 1}, {'foo': 1})

深拷贝

>>> items = [1, ['foo', 'bar'], 2, 3]
>>> items_copy = copy.copy(items)
>>> items[0] = 100
>>> items[1].append('xxx')
>>> items, items_copy
([100, ['foo', 'bar', 'xxx'], 2, 3], [1, ['foo', 'bar', 'xxx'], 2, 3])
>>> id(items[1]), id(items_copy[1])
(2025849749952, 2025849749952)

可以看到,浅拷贝后item[1]和item_copy[1]对应的仍是同一个对象

items_copy = copy.deepcopy(items)

案例故事


http://www.ppmy.cn/news/1620.html

相关文章

SVM(支持向量机)基本形式推导

据说在dl之前是SVM撑起了ml的半片天&#xff0c;学习后发现SVM是由纯粹的数学推导、转化、求解、优化“堆砌”而来&#xff0c;不如说是数学撑起了ml&#xff0c;ml是数学的学科。以下根据老师ppt上讲解的思路讲讲个人对SVM基本形式推导的理解。 margin&#xff08;间隔&#x…

Linux——匿名管道、命名管道及进程池概念和实现原理

目录 一.什么是匿名管道 二.如何使用匿名管道 &#xff08;一&#xff09;.pipe原理 &#xff08;二&#xff09;.pipe使用 三.命名管道概念及区别 &#xff08;一&#xff09;.什么是命名管道 &#xff08;二&#xff09;.与匿名管道的联系和区别 四.命名管道的使用 &…

【Python百日进阶-数据分析】Day124 - Plotly Figure参数:饼图(二)

文章目录metacustomdata 自定义数据domain 域automarginmarker 标记textfont 文字字体textinfo 文本信息direction 方向holehoverlabel 悬停标签insidetextfont 内部文字字体insidetextorientation 内部文本方向outsidetextfont 外部文本字体rotation 旋转scalegroupsort 排序u…

华为机试真题 C++ 实现【连接器问题】【2022.11 Q4新题】

目录 题目 思路 考点 Code 题目 有一组区间[a0,b0],[a1,b1],…(a,b表示起点,终点),区间有可能重叠、相邻,重叠或相邻则可以合并为更大的区间; 给定一组连接器[x1,x2,x3,…](x表示连接器的最大可连接长度,即x>=gap),可用于将分离的区间连接起来,但两个…

GIT分布式版本控制系统 | 命令讲解入门

Git概述 Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。 也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件&#xff1b;分布式相比于集中式的最大区别在于开发者可以提交到本地&#xff0c…

【免费赠送源码】Springboot喵喵宠物医院管理系统ti5f6计算机毕业设计-课程设计-期末作业-毕设程序代做

【免费赠送源码】Springboot喵喵宠物医院管理系统ti5f6计算机毕业设计-课程设计-期末作业-毕设程序代做 【免费赠送源码】Springboot喵喵宠物医院管理系统ti5f6计算机毕业设计-课程设计-期末作业-毕设程序代做本源码技术栈&#xff1a; 项目架构&#xff1a;B/S架构 开发语言…

[go学习笔记.第十八章.数据结构] 1.基本介绍,稀疏数组,队列(数组实现),链表

一.基本介绍 1.数据结构(算法)的介绍 (1).数据结构是一门研究算法的学科&#xff0c;自从有了编程语言也就有了数据结构,学好数据结构可以编写出更加漂亮&#xff0c;更加有效率的代码 (2).要学习好数据结构就要多多考虑如何将生活中遇到的问题用程序去实现解决 (3).程序&…

Linux UART编程 驱动蓝牙芯片

在熟悉了UART概念后&#xff0c;我们要学以致用&#xff0c;在Linux用起来来驱动起来蓝牙芯片&#xff01; 我们直接借用man来看下&#xff0c;命令如下&#xff1a; man termios 1.头文件引用 #include <termios.h> #include <unistd.h> 2.串口打开关闭 open…