字典的关键符号是大括号({})和冒号(:),冒号的左边称为字典的 “键”,右边称为字典的 “值”,在字典中,只要我们提供键,就可以获取其对应的值。方法跟序列类似,只不过这次在方括号中,咱们使用的是键,而非索引值序列中的元素可以重复,字典中的项不可重复
创建字典:>>> a = {"吕布":"口口布", "关羽":"关习习", "刘备":"刘baby"}>>> b = dict(吕布="口口布", 关羽="关习习", 刘备="刘baby")注意这种写法要求不能往键上面加引号,尽管它是一个字符串>>> c = dict([("吕布","口口布"), ("关羽","关习习"), ("刘备","刘baby")])>>> d = dict({"刘备": "刘baby", "关羽": "关习习", "吕布": "口口布"})>>> e = dict({"吕布":"口口布", "刘备":"刘baby"}, 关羽="关习习")
增:fromkeys(iterable[, value])>>> d = dict.fromkeys("Fish", 250)
>>> d
{'F': 250, 'i': 250, 's': 250, 'h': 250}如果不指定 value 参数,则采用默认值 None
删:
pop()
如果 pop() 一个不存在的键,那么会抛出异常,可以指定一个 default 参数
跟 pop() 方法类似的还有一个 popitem(),在 Python3.7 之前,它是随机删除一个键值对,在 Python3.7 之后,它删除的是最后一个加入字典的键值对
del 关键字也可以删除一个指定的字典元素,如果 del 直接加上字典的变量名就是将整个字典给干掉,如果只希望清空字典中的内容,可以使用 clear() 方法
d = {1, 2, 3, 4, 5} 才是集合,d = {} 则是一个空字典
字典中,同样一个值是否可以出现两次,但是同样一个键就不能出现两次啦,如果同一个键被赋值两次,那么后一个值将覆盖前一个,所以字典的键必须是独一无二的,但值则不必
本帖最后由 成成是我 于 2022-12-17 16:35 编辑
2022.12.17
改
想要同时修改多个键值对,可以使用字典的 update() 方法,可以同时给它传入多个键值对,也可以直接给它传入另外一个字典,或者一个包含键值对的可迭代对象
>>> d.update(F=70, i=105, s=115, h=104, C=67)
>>> d.update({'F':70, 'i':105, 's':115, 'h':104, 'C':67})
>>> d.update([('F',70), ('i',105), ('s',115), ('h',104), ('C',67)])默认删除不存在会抛出异常,a.pop("不存在的键"),"弹出的默认值"
查
最简单的查方法就是你给它一个键,它返回你对应的值,如果指定的键不存在于字典中,那么会报错,更好的方法是使用 get() 方法,它可以传入一个 default 参数,指定找不到键时返回的值
查找一个键是否存在于字典中,如果在,返回它对应的值;如果不在,给它指定一个新的值,这么做的一个显而易见的好处就是不会破坏到已经存在的键值对
>>> d.setdefault('C', "code")
67
>>> d
{'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67}
>>> d.setdefault('c', "code")
'code'
>>> d
{'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67, 'c': 'code'}
视图对象
items()、keys() 和 values() 三个方法分别用于获取字典的键值对、键和值三者的视图对象
视图对象即字典的动态视图,意味着当字典内容发生改变时,视图对象内容也相应地改变
浅拷贝: copy() 方法,浅拷贝第一层的修改是不会相互影响的,但是对于嵌套层,可就不是这么一回事咯
获取字典的键值对数量和逐个遍历迭代器: len() 函数,next()
判断某个键是否存在于字典中: in 和 not in
字典转化为列表: list() 函数,得到的是字典中所有的 “键” 构成的列表,得到所有的 “值”,应该使用 list(d.values())
将字典的键构成一个迭代器: iter() 函数
对字典内部的键值对进行逆向操作: reversed() 函数
嵌套
>>> d = {"吕布": {"语文":60, "数学":70, "英语":80}, "关羽": {"语文":80, "数学":90, "英语":70}}
字典推导式
>>> d = {'F':70, 'i':105, 's':115, 'h':104, 'C':67}
>>> b = {v:k for k,v in d.items()}
>>> b
{70: 'F', 105: 'i', 115: 's', 104: 'h', 67: 'C'}
>>> d
{'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67}也可以加上筛选的条件
>>> c = {v:k for k,v in d.items() if v > 100}
>>> c
{105: 'i', 115: 's', 104: 'h'}利用字典推导式,我们就可以轻易地让 Python 帮你求出字符串的编码值
>>> d = {x:ord(x) for x in "FishC"}
>>> d
{'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67}
创建集合
创建一个集合通常有三种方法:
[*]使用花括号,元素之间以逗号分隔:{"FishC", "Python"}
[*]使用集合推导式:{s for s in "FishC"}
[*]使用类型构造器,也就是 set():set("FishC")
集合最大的特性就是唯一性,集合中所有元素都是独一无二的,并且也是无序的(随机性,无序性)
可以使用 in 和 not in 来判断某个元素是否存在于集合中
访问集合:迭代>>> for each in s:
... print(each)
...
F
h
i
s
C集合必杀技 —— 去重>>> set()
{1, 2, 3, 5}
集合的方法,集合的各种方法大合集 -> https://fishc.com.cn/thread-203569-1-1.htmlcopy() 方法isdisjoint(other) 方法,检测两个集合之间是否不相干,可以使用 isdisjoint(other) 方法
Python运算符<=,检测子集<,检测真子集>和>=,检测超集和真超集|(管道符),并集&(and 符号),交集-,差集^(脱字符),对称差集注意:使用运算符的话,符号两边都必须是集合类型的数据才可以,不然会报错
本帖最后由 成成是我 于 2022-12-18 17:32 编辑
2022.12.18
冻结的集合
Python 将集合细分为可变和不可变两种对象,前者是 set(),后者是 frozenset():被冻结的集合(frozenset())是不支持修改的
使用冻结的集合,主要也是为了防止内容被肆意修改,起到一个保护的作用。另外还有重要的一点,就是只有使用 frozenset 对象,才可以创建嵌套集合(因为集合内部的元素必须是可哈希的)。使用 set 对象,无法创建嵌套集合
update(*others) 方法使用 others 容器中的元素来更新集合;add(elem) 方法则是单纯地往集合里面添加一项数据
update(*others) 方法使用 others 容器中的元素来更新集合:小技巧:文档中标记为*other则支持对个参数,other单个参数
difference(*others) 方法是计算差集并将结果返回为一个新的集合,difference_update(*others) 方法则是直接使用新的结果更新集合。因此,前者 set 和 frozenset 对象均使用,后者仅 set 对象可用
intersection_update(*others)、difference_update(*others) 和 symmetric_difference_update(other) 分别是使用前面讲过的交集、差集和对称差集的方式来更新集合
add(elem) 方法:单纯地往集合里添加数据
remove(elem) 或者 discard(elem) 方法:在集合中删除某个元素
remove(elem):删除指定的elem元素,若elem不存在,抛出异常
discard(elem) :删除指定的elem元素,若elem不存在,静默处理
pop() 方法:随机从集合中弹出一个元素(删除),存储随机,弹出即随机
clear() 方法:集合清空
可哈希:嘻哈值在程序整个生命周期中保持不变
hash() 函数:获取一个对象的哈希值
Python 中大多数不可变对象是可哈希的,而那些可变的容器则不哈希
嵌套的集合
集合嵌套不可哈希
通过frozenset() 对象让集合嵌套可哈希
>>> x = frozenset(x)
>>> y = {x, 4, 5}
>>> y
{frozenset({1, 2, 3}), 4, 5}
本帖最后由 成成是我 于 2022-12-19 20:20 编辑
2022.12.19
函数的作用
大多数情况下,函数是通过参数和返回值与外部进行通信的
Python 函数的主要作用就是打包代码
有两个显著的好处:
[*]可以最大程度地实现代码重用,减少冗余的代码
[*]可以将不同功能的代码段进行封装、分解,从而降低结构的复杂度,提高代码的可读性
创建和调用函数
我们使用 def 语句来定义函数,紧跟着的是函数的名字,后面带一对小括号,冒号下面就是函数体,函数体是一个代码块,也就是每次调用函数时将被执行的内容,调用这个函数,只需要在名字后面加上一对小括号
pass 是一个空语句,表示不做任何事情,经常是被用来做一个占位符使用的
函数的参数
从调用角度来看,参数可以细分为:形式参数(parameter)和实际参数(argument)
其中,形式参数是函数定义的时候写的参数名字(比如下面例子中的 name 和 times);实际参数是在调用函数的时候传递进去的值(比如下面例子中的 "Python" 和 5)
>>> def myfunc(name, times):
... for i in range(times):
... print(f"I love {name}.")
...
>>> myfunc("Python", 5)
I love Python.
I love Python.
I love Python.
I love Python.
I love Python.
函数的返回值
return 语句,执行到return语句,立刻返回其结果。函数则不会执行return 之后的其他语句
如果一个函数没有通过 return 语句返回,它也会自己在执行完函数体中的语句之后,悄悄地返回一个 None 值
一个函数能够在同时将多个返回值打包成元组的形式返回多个值
>>> def myfunc():
... return 1, 2, 3
...
>>> myfunc()
(1, 2, 3)但是不能写成这样:
>>> def myfunc():
... return 1
... return 2
... return 3
...
>>> myfunc()
1因为 Python 一旦执行了 return 语句,就会立刻返回,从而跳出函数体,而不理会后面是否还有其它语句
位置参数
在通常的情况下,实参是按照形参定义的顺序进行传递的,由于在定义函数的时候,就已经把参数的名字和位置确定了下来,我们将 Python 中这类位置固定的参数称之为位置参数。
关键字参数(多参数时有奇效)
如果同时使用位置参数和关键字参数,那么需要注意一下使用顺序,因为位置参数必须是在关键字参数之前,之间也不行
默认参数(定义时指定,如果调用时传入新值则替换,否则使用默认值)
默认参数的意义就是当用户没有输入该参数的时候,有一个默认值可以使用,不至于造成错误
如果用户指定了该参数值,那么默认的值就会被覆盖
如果要使用默认参数,那么应该把它们摆在最后
默认参数是存在于函数定义中的,而关键字参数是在函数调用中发挥作用
只能使用位置参数
help() 函数查看函数文档的时候呢,经常会在函数原型的参数中发现一个斜杠(/)
斜杠左侧的参数必须传递位置参数(直接传入值),不能是关键字参数(不能指定名字),斜杠右侧随意
只能使用关键字参数:*(左边参数既可以是位置或关键字参数,右边必须是关键字参数)
>>> def abc(a, *, b, c):
... print(a, b, c)这样,参数 a 既可以是位置参数也可以是关键字参数,但参数 b 和参数 c 就必须是关键字参数
感谢整理,温故而知新 2022.12.24
收集参数
定义收集参数即使在形参的前面加上星号(*)来表示
收集参数可以使用连续的两个星号(**)将参数们打包为字典,对于这种情况,在传递参数的时候就必须要使用关键字参数了,因为字典的元素都是键值对嘛,所以等号(=)左侧是键,右侧是值
解包参数
一个星号(*)和两个星号(**)在形参上使用称之为参数的打包,在实参上的使用即解包参数
2022.12.26
通常一个变量的总是由他所在代码中被赋值的位置来决定的
同名变量,函数中则调用局部变量值,函数外部则调用全局变量值,全局变量可以在函数内部被访问到,却无法在内部修改其值,一旦修改python自动创建同名的“局部变量”来覆盖
局部作用域
在函数 myfunc() 中定义的,局部变量只在函数内生效,与函数外的同名全局变量属于不同地址,作用域仅限于该函数,如果我们尝试在函数的外部访问这个变量,那么就会报错
全局作用域
在任何函数的外部去定义一个变量,作用域就是全局的
如果在函数中存在一个跟全局变量同名的局部变量,在函数中,局部变量就会覆盖同名的全局变量的值
内部函数可以访问到外部函数的变量,但却无法修改它
global 语句(不推荐使用)
通常我们无法在函数内部修改全局变量的值,除非使用 global 语句破除限制
嵌套函数
在外部函数 funA() 里面嵌套了一个内部函数 funB(),那么这个内部函数是无法被直接调用的(想要调用 funB(),必须得通过 funA())
nonlocal 语句
通常我们无法在嵌套函数的内部修改外部函数变量的值,除非使用 nonlocal 语句破除限制
跟global的区别是,global语句修改的是函数体外的全局变量,nonlocal修改的是上一层嵌套的函数变量,若有多层嵌套也只修改上一层,上一层要是没有局部变量,直接报错
LEGB 规则
只要记住 LEGB,那么就相当于掌握了 Python 变量的解析机制。
其中:
[*]L 是 Local,是局部作用域
[*]E 是 Enclosed,是嵌套函数的外层函数作用域
[*]G 是 Global,是全局作用域
[*]B 是 Build-In,也就是内置作用域
不要起BIF同名的变量名
本帖最后由 成成是我 于 2022-12-29 15:16 编辑
2022.12.27
嵌套作用域的特性
对于嵌套函数来说,外层函数的作用域是会通过某种形式保存下来的,它并不会跟局部作用域那样,调用完就消失
闭包
所谓闭包(closure),也有人称之为工厂函数(factory function)
工厂函数就是能产生函数的函数,实现闭包必须要用到嵌套函数
总结:
1.利用嵌套函数的外层作用域具有记忆能力这个特性,让数据保存在外层函数的参数或者变量中
2.将内层函数作为返回值给返回
本帖最后由 成成是我 于 2022-12-29 16:24 编辑
2022.12.29
装饰器
装饰器本质上也是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能
使用了装饰器,我们并不需要修改原来的代码,只需要在函数的上方加上一个 @time_master,然后函数就能够实现统计运行时间的功能了,这个 @ 加上装饰器名字其实是个语法糖,装饰器原本的样子应该这么调用的
@time_master语法糖 等价于myfunc = time_master(myfunc)
给装饰器传递参数,添加多一层嵌套函数来传递参数
如果存在多个装饰器装饰同一个函数,那么它们的调用顺序应该是自下而上依次执行
本帖最后由 成成是我 于 2022-12-30 07:47 编辑
2022.12.30
lambda 表达式(“一行流”代码核心)
lambda arg1, arg2, arg3, ... argN : expression等价于:
def <lambda>(arg1, arg2, arg3, ... argN):
... return expression
lambda 是个关键字,然后是冒号,冒号左边是传入函数的参数,冒号后边是函数实现表达式以及返回值
传统定义的函数,函数名就是一个函数的引用,而 lambda 表达式,整个表达式就是一个函数的引用
与 map() 和 filter() 函数搭配使用
map() 函数会根据提供的函数对指定的可迭代对象的每个元素进行运算,并将返回运算结果以迭代器的形式返回
filter() 函数函数会根据提供的函数对指定的可迭代对象的每个元素进行运算,并将运算结果为真的元素,以迭代器的形式返回(注意:返回的是元素本身)
lambda 是一个表达式,而非语句,所以它能够出现在 Python 语法不允许 def 语句出现的地方,这是它的最大优势
但由于所有的功能代码都局限在一个表达式中实现很容易出错,因此,lambda 通常只能实现那些较为简单的需求,def 语句则负责用于定义功能复杂的函数,去处理那些复杂的工作
页:
1
[2]