一、数据类型
不可变数据 | 可变数据类型 |
---|---|
Number(数字) | List(列表) |
String(字符串) | Set(集合) |
Tuple(元组) | Dictionary(字典) |
二、分支和循环
1、分支
1)一种情况
基本语法:
if condition:
statement(s)
2)两种情况
基本语法:
if condition:
statement(s)
else:
statement(s)
3)多种情况
基本语法:
if condition1:
statement(s)
elif condition2:
statement(s)
elif condition3:
statement(s)
...
else:
statement(s)
4)合并语句
基本语法
条件成立时执行的语句 if condition else 条件不成立时执行的语句
eg.
level = ("D" if 0 <= score <60 else
"C" if 60 <= score <80 else
"B" if 80 <= score <90 else
"A" if score >= 90 else
"S" if score == 100 else
"请输入0——100之间的分值")
分支结构的嵌套
理论上可以无限嵌套,但要注意代码的美观和可读性
2、循环
1)while循环
while condition:
statement(s)
死循环:死循环是可以被设计的
#1 break
while True:
answer = input("主人,我可以退出循环了吗?")
if answer == "可以":
break
print("诶,好累")
else
:
当循环条件不再为真时,else语句才会被执行。因此使用break中断循环不会执行else。
#2 continue
i = 0
while i < 10:
i += 1
if i % 2 == 0:
continue #如果是偶数就跳过循环
print(i) #最后只输出奇数
eg.九九乘法表
i = 1
while i <= 9:
j = 1
while j <= i:
result = i*j
print(j, '*', i, '=', result, end= " ")
j += 1
print() #这里表示换行
i += 1
2)for循环
eg.找出10以内的所有素数
for n in range(2,10):
for x in range(2,n):
if n % x == 0:
print(n, "=", x, "*", n//x)
break
else:
print(n,"是一个素数")
三、列表
列表可以容纳不同数据类型的数据,列表本质是一个序列
1、创建列表
eg.
[1,2,3,4,5,"上山打老虎"] #无名列表
rhyme = [1,2,3,4,5,"上山打老虎"] #有名列表
元素下标:
元素 | 1 | 2 | 3 | 4 | 5 | “上山打老虎” |
---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 |
元素 | 1 | 2 | 3 | 4 | 5 | “上山打老虎” |
---|---|---|---|---|---|---|
下标 | -6 | -5 | -4 | -3 | -2 | -1 |
2、列表切片:
rhyme[0:3]
rhyme[:3] #从开始到下标3
rhyme[3:6]
rhyme[3:] #从下标3到末尾
rhyme[0:6:2]
rhyme[::2] #设置step
rhyme[::-1] #倒序输出
3、更改列表
1)增加元素
heros = ["钢铁侠","绿巨人"]
#1 append
heros.append("黑寡妇")
#2 extend
heros.extend(["鹰眼", "灭霸", "雷神"])
Attention:
extend()方法的参数必须是一个可迭代对象(简单理解是可以使用for循环),新的内容是追加到源列表最后一个元素的后面
使用切片添加元素
s = [1, 2, 3, 4, 5]
s[len(s):] = [6, 7, 8] #把6, 7, 8添加到列表的末尾
2)添加元素
s = [1, 3, 4, 5]
s.insert(1, 2) #在下标为1的位置添加元素2
s.insert(0, 0) #在开头的位置添加元素0
s.insert(len(s),6) #在末尾的位置添加元素6
3)删除元素
heros = ["钢铁侠", "灭霸", "蜘蛛侠", "鹰眼", "绿巨人"]
#1 remove
heros.remove("灭霸")
Attention:
1、存在多个匹配的元素,那么只删除第一个
2、指定元素不存在,程序报错
#2 pop
heros.pop(2)
4)替换元素
heros[4]="钢铁侠"
heros[3:]=["武松", "林冲", "李逵"]
5)元素排序
nums = [3, 1, 4, 5, 2, 7, 6]
nums.sort() #排序
nums.reverse() #倒序
#也可以一步到位
nums.sort(reverse=True)
6)查找元素
nums.count(3) #返回列表中3的个数
heros.index("绿巨人") #返回“绿巨人”这个元素的下标
heros.index("绿巨人", 1, 4) #从下标1~4查找“绿巨人”这个元素下标
7)列表复制
属于浅拷贝!!!
nums_copy1 = nums.copy()
nums_copy2 = nums[:]
8)清空列表
heros.clear()
9)列表的加法和乘法
列表的加法:拼接
列表的乘法:重复
4、列表嵌套
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
访问嵌套列表
for i in matrix:
for each in i:
print(each, end=' ')
print()
访问单独元素:
matrix[1][2]
通过循环创建二维列表
for i in range(3)
A[i] = [0] * 3
is
:同一性运算符
判断两个变量是否指向同一个对象
B = [[0] * 3] * 3
#此列表外层3个元素指向同一个对象,因此牵一发则动全身
#对于内嵌的列表,乘号不是拷贝,而是对同一个位置进行3次引用

5、深拷贝
变量不是一个盒子
赋值的过程其实是引用
x = [1 ,2 ,3]
y = x #改变x的同时y也会改变
若想获得独立的列表需要使用拷贝
但对于嵌套列表来说,情况又会有所不同。浅拷贝知识拷贝了外层的对象,对于嵌套对象,拷贝的只是其引用。

import copy
x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
y = copy.copy(x) #浅拷贝
z = copy.deepcopy(x) #深拷贝,改变x不会改变z
6、列表推导式
1)一般的列表推导式
基本语法:
[expression for target in iterable]
eg.
oho = [1, 2, 3, 4, 5]
oho = [i * 2 for i in oho] #oho中的每一个元素乘以2
oho = [i + 1 for i in oho] #oho中的每一个元素加1
code = [ord(c) for c in "Fishc"] #将每个字符串转化为对应的编码
matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
col2 = [row[1] for row[1] in matrix] #获取每行第二列
diag = [matrix[i][i] for i in range(len(matrix))] #获取主对角线上的元素
列表推导式创建二维列表
S = [[0] * 3 for i in range(3)]
2)添加条件语句的列表推导式
基本语法:
[expression for target in iterable if condition]
eg.
even = [i + 1 for i in range(10) if i % 2 == 0]
#输出[1, 3, 5, 7, 9]
先执行for语句,再执行if语句,最后再执行前面的expression
3)嵌套的列表推导式
基本语法:
[expression for target1 in iterable1
for target2 in iterable2
...
for targetN in interableN]
eg.二维列表降级为一维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flatten = [col for row in matrix for col in row]
#下面是利用嵌套循环的等价写法
flatten = []
for row in matrix:
for col in row:
flatten.append(col)
#嵌套列表推导式中,外层循环放在前面,内层循环放在后面
四、元组
列表是方括号,元组是圆括号,且括号可以省略(但一直加上圆括号可以提高可读性!)
rhyme = 1, 2, 3, 4, 5, "上山打老虎"
元组是不可变的,但如果元组的元素是可变的例如列表,那么可以改变其内容,因为实质上未改变元组元素实际上是指向的列表的地址,没有发生改变。
创建只有一个元素的元组
x = (520,)
1、元组切片
元组支持切片操作,因为切片并非修改,而是以某种特定的方式导出
rhyme[::-1] #倒序输出
2、查找元素
和列表一样,元组可以使用count()和index()实现查询功能
3、元组的加法和乘法
s = (1, 2, 3)
t = (4, 5, 6)
s + t #元组拼接(1, 2, 3, 4, 5, 6)
s * 3 #元组重复(1, 2, 3, 1, 2, 3, 1, 2, 3)
w = s, t #元组嵌套((1, 2, 3), (1, 2, 3))
4、打包和拆包
适用于任何的序列类型
t = (123, "Fishc", 3.14) #打包
x, y, z = t #拆包
五、字符串
1、大小写字母变换
x = "I Love FishC"
方法 | 效果 | 结果 |
---|---|---|
x.capitalize() | 首字母大写,其他小写 | I love fishc |
x.casefold() | 所有字母小写(还可以处理其他语言字符) | i love fishc |
x.title() | 所有单词的首字母大写,其他小写 | I Love Fishc |
x.swapcase() | 大小写翻转 | i lOVE fISHc |
x.upper() | 所有字母大写 | I LOVE FISHC |
x.lower() | 所有字母小写(只可以处理英文) | i love fishc |
2、左中右对齐
x = "新年好!"
方法 | 效果 |
---|---|
x.center(10) | 居中对齐 |
x.ljust(10) | 左对齐 |
x.rjust(10) | 右对齐 |
x.zfill(10) | 左侧用0填补 |
通过参数自主设定填充的内容
x.center(9,"呀") #结果是"呀呀呀新年好!呀呀呀"
3、查找
方法 | 作用 |
---|---|
count(sub[,start[,end]]) | 查找子字符串在字符串中出现的次数,可以限制查找开始和结束的位置 |
find(sub[, start[, end]]) | 查找子字符串在字符串中出现的下标(正序) |
rfind(sub[, start[, end]]) | 查找子字符串在字符串中出现的下标(逆序) |
index(sub[, start[, end]]) | 和find类似(正序) |
rindex(sub[, start[, end]]) | 和find类似(逆序) |
Attention:
index和find类似,但不同的是,在查找不到子字符串时会出现异常(find返回-1)
4、替换
expandtabs([tabsizs=8])
使用空格代替tab
replace(old, new, count=-1)
旧字符串替换为新字符串
maketrans(intab, outtab)
制作替换表格
table = str.maketrans("ABCDEFG", "1234567")
"I love Fishc".tanslate(table) #利用表格进行替换,结果是"I love 6ish3"
5、判断
方法 | 作用 |
---|---|
x.startswith(prefix[, start[, end]]) | 判断子字符串是否出现在字符串的起始位置 |
x.endwith(suffix[, start[, end]]) | 判断子字符串是否出现在字符串的结束位置 |
x.istitle() | 判断字符串中每个单词的首字母是否大写 |
x.isupper() | 判断字符串每个字母是否都是大写 |
x.islower() | 判断字符串每个字母是否都是小写 |
x.isalpha() | 判断字符串每个字符是否都是字母 |
x.isspace() | 判断字符串每个字符是否都是空白字符 |
x.isprintable() | 判断字符串每个字符是否都是可打印字符 |
x.isdecimal() | 判断字符串每个字符是否都是十进制数字 |
x.isdigit() | 判断字符串每个字符是否都是数字 |
x.isnumeric() | (罗马数字,中文一二三……返回True) |
x.isalnum() | (上面三个任意一个返回True就返回True) |
x.isidentifier() | 判断字符串是否是一个合格的python标识符 |
x.iskeyword() | 判断字符串是否是python的保留标识符 |
Attention:
1、x.startwith()和x.endwith()中的子字符串可以使用元组包含多个被判断的字符串
2、转义字符例如\n是不可打印的
3、x.iskeyword()需要先import keyword
6、截取
方法 | 作用 |
---|---|
lstrip(chars=None) | 去除左侧空白 |
rstrip(chars=None) | 去除右侧空白 |
strip(chars=None) | 去除两侧空白 |
removeprefix(prefix) | 去除左侧具体子字符串 |
removesuffix(suffix) | 去除右侧具体子字符串 |
Attention:
chars可以设为其他参数
7、拆分&拼接
方法 | 作用 |
---|---|
x.partition(sep) | 从左向右找分隔符,将原字符串分割为一个三元组 |
x.repartition(sep) | 从右向左找分隔符,将原字符串分割为一个三元组 |
x.split(sep, maxsplit) | 从左向右找分隔符,将原字符串分割为一个列表 |
x.rsplit(sep, maxsplit) | 从右向左找分隔符,将原字符串分割为一个列表 |
x.splitlines(keepends=False) | 从左向右按行分割,将原字符串分割为一个列表 |
x.join(iterable) | 将参数中的多个字符串使用x拼接起来 |
Attention:
1、sep默认为None,maxsplit默认为-1,maxsplit用于设定切的刀数
2、keepends=True,则保留换行符
3、使用join拼接字符串在拼接量较大的时候效率要比+高得多
8、格式化字符串
year = 2010
"鱼C工作室成立于 {} 年".format(year)
括号内可以添加要填充的内容的下标或关键字参数
"{}看到{}就很激动!".format("小甲鱼", "漂亮的小姐姐")
#输出"小甲鱼看到漂亮的小姐姐就很激动!"
"{1}看到{0}就很激动!".format("小甲鱼", "漂亮的小姐姐")
#输出"漂亮的小姐姐看到小甲鱼就很激动!"
"我叫{name},我爱{fav}".format(name="小甲鱼", fav="Python")
格式化字符串的参数:
[[fill]align][sign][#][0][width][grouping_option][.precision][type]
1)align选项
值 | 含义 |
---|---|
‘<’ | 强制字符串在可用空间内左对齐(默认) |
‘>’ | 强制字符串在可用空间内右对齐 |
‘=’ | 强制将填充放置在符号(如果有)之后但在数字之前的位置 |
‘^’ | 强制字符串在可用空间内居中对齐 |
eg.
":^10".format(250) #冒号前面是位置索引,^后面是可用空间大小,为10个字符
#输出为' 250 '
2)0选项
eg.
"{:010}".format(250) #输出为'0000000250'
"{:010}".format(-250) #输出为'-000000250'
Attention:
感知正负的0填充只对数字有效
3)填充选项
eg.
"{1:%>6}{0:%<6}".format(520, 250) #输出为'%%%250520%%%'
4)符号选项
值 | 含义 |
---|---|
‘+’ | 正数在前面添加正号(+),负数在前面添加负号(-) |
‘-’ | 只在负数前面添加负号(-),默认行为 |
空格 | 正数在前面添加一个空格,负数在前面添加负号(-) |
‘,’ | 使用逗号作为千分符 |
‘_’ | 使用下横线作为千分符 |
eg.
"{:+} {:-}".format(520, 250) #输出为'+520 250'
5)精度选项
对于[type]设置为’f’或’F’的浮点数来说,是限定小数点后显示多少个数位
对于[type]设置为’g’或’G’的浮点数来说,是限定小数点前后一共显示多少个数位
对于非数字类型来说,是限定最大字段的大小
对于整数类型来说,则不允许使用[.precision]选项
eg.
{:.2f}.format(3.1415) #输出为'3.14'
{:.2g}.format(3.1415) #输出为'3.1'
{:.6}.format("I love FishC") #输出为'I love'
6)类型选项
#1 整数
值 | 含义 |
---|---|
‘b’ | 将参数一二进制的形式输出 |
‘c’ | 将参数以Unicode字符的形式输出 |
‘d’ | 将参数以十进制的形式输出 |
‘o’ | 将参数以八进制的项式输出 |
‘x’或’X’ | 将促使以十六进制的形式输出 |
‘n’ | 和’d’类似,不同之处在于它会使用当前语言环境设置的分隔符插入到恰当的位置 |
None | 和’d’一样 |
#2 浮点数
值 | 作用 |
---|---|
‘e’ | 将参数以科学计数法的形式输出(用’e’表示指数,默认精度为6) |
‘E’ | 将参数以科学计数法的形式输出(用’E’表示指数,默认精度为6) |
‘f’ | 将参数以定点表示法的形式输出(不是数用’nan’标识,无穷用’inf’,默认精度为6) |
‘F’ | 将参数以科学计数法的形式输出(不是数用’NAN’标识,无穷用’INF’,默认精度为6) |
‘g’ | 通用格式,小数用’f’表示,大数用’e’表示 |
‘G’ | 通用格式,小数用’F’表示,大数用’E’表示 |
‘n’ | 和’g’类似,不同之处在于它会使用当前语言环境设置的分隔符插入到恰当的位置 |
‘%’ | 以百分比形式输出 |
None | 和’g’类似,不同之处在于当使用定点表示法是小数点至少显示一位 |
eg.
"{:.{prec}f}".format(3.1415, prec=2) #输出为'3.14'
f-字符串:
在字符串前面加一个前缀’f’或’F’
f"1+2={1+2}, 2的平方是{2*2}, 3的立方是{3*3*3}"
六、序列
列表、元组和字符串的共同点:
1、都可以通过索引获取每一个元素
2、第一个元素的索引值是0
3、都可以通过切片的方法获取一个范围
4、都有很多共同的运算符
列表、元组和字符串统称为序列
1、序列运算符
可以作用于序列的运算符:‘+’ ‘*’
检测对象的id值是否相同的运算符:‘is’ ‘is not’
判断某个元素是否包含在序列中:‘in’ ‘not in’
删除指定的元素或对象:‘del’
eg.
x = [1, 2, 3, 4, 5]
del x[1:4] #得到结果[1, 5]
x = [1, 2, 3, 4, 5]
del x[::2] #得到结果[2, 4]
2、函数
1)列表、元组和字符串相互转换
函数 | 作用 |
---|---|
list() | 将一个可迭代对象转换为列表 |
tuple() | 将一个可迭代对象转换为元组 |
str() | 将一个可迭代对象转换为字符串 |
2)最小值和最大值
函数 | 作用 |
---|---|
min(iterable, *[, key, default]) | 返回最小元素 |
max(iterable, *[, key, default]) | 返回最大元素 |
Attention:
如果传入的对象是字符串,则比较编码值,大写字母的编码值在小写字母前
3)长度和求和
函数 | 作用 |
---|---|
len() | 长度 |
sum() | 求和 |
Attention:
对于32位平台,len()函数的范围上限是2^31-1 对于64位平台,len()函数的范围上限是2^63-1
eg.
sum(s, start=100) #表示从100开始加
4)排序
函数 | 作用 |
---|---|
sorted() | 从小到大排序(设定参数reverse可以实现从大到小)(设定参数key可以干预排序方式) |
reversed() | 返回一个迭代器(使用list可以转换为列表) |
Attention:
sorted(s)返回一个全新的列表,s.sort()改变原来的列表
eg.
t.sorted(key=len) #根据长度来排序
5)真假
函数 | 作用 |
---|---|
all() | 判断是否所有元素的值都为True |
any() | 判断是否存在元素的值为True |
6)enumerate()
返回一个枚举对象,它的功能将可迭代对象的每个元素及0开始的序号共同构成一个二元组的列表
eg.
seasons = ["Spring", "Summer", "Fall", "Winter"]
enumerate(seasons)
list(enumerate(seasons))
#结果是[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
7)zip()
创建一个可聚合多个可迭代对象的迭代器,它会将作为参数传入的每个可迭代对象的每个元素一次组合成元组,即第i个元组包含来自每个参数的第i个元素
eg.
x = [1, 2, 3]
y = [4, 5, 6]
zipped = zip(x, y)
list(zipped)
#结果是[(1, 4), (2, 5), (3, 6)]
Attention:
如果有可迭代对象的长度不同,则舍弃多出来的,如果不想舍弃多出来的,可以使用itertools.zip_longest()函数,需要先import itertools
8)map()
根据提供的函数对指定的可迭代对象的每个元素进行运算,并将返回运算结果的迭代器
eg.
mapped = map(ord, "FishC") #ord函数的作用是将一个字符转化为编码值
list(mapped)
#结果是[70, 105, 115, 104, 67]
mapped = map(pow, [2, 3, 10], [5, 2, 3]) #pow函数的作用是次方
list(mapped)
#结果是[32, 9, 1000]
9)filter()
根据提供函数对指定的可迭代对象的每个元素进行运算,并将运算结果为真的元素,以迭代器的形式返回
eg.
list(filter(str.islower, "FishC"))
#结果是['i', 's', 'h']
迭代器和可迭代对象
一个迭代器肯定是一个可迭代对象
可迭代对象可以对其进行重复的操作,而迭代器是一次性的
iter()
:将一个可迭代对象转化为迭代器
next()
:针对迭代器,将其中的元素一个一个提取出来
七、字典
1、创建字典
1)方法1
a = {"吕布":"口口布", "关羽":"关习习"}
2)方法2
b = dict(吕布="口口布", 关羽="关习习")
Attention:
键上不能加引号
3)方法3
c = dict([("吕布", "口口布"), ("关羽", "关习习")])
4)方法4
d = dict({"吕布":"口口布", "关羽":"关习习"})
5)方法5
e = dict(zip["吕布", "关羽"], ["口口布", "关习习"])
2、更改字典
1)增加元素
基本语法:
fromkeys(iterable[,values])
用于创建一个所有值都相等的字典
eg.
d = dict.fromkeys("Fish", 250)
#创建的字典为{'F': 250, 'i': 250, 's': 250, 'h': 250}
d['F'] = 70
#修改后的字典为{'F': 70, 'i': 250, 's': 250, 'h': 250}
d['C'] = 67
#增加元素后的字典为{'F': 250, 'i': 250, 's': 250, 'h': 250, 'C': 67}
Attention:
字典和序列的一个区别在于,字典中不会出现重复的键,而序列可以有重复的元素
2)删除元素
#1 pop()
基本语法:
pop(keys[, default]) #删除字典中指定的键值对
popitem() #删除字典中最后加入的一组键值对
eg.
d.pop('s') #返回s所对应的值
#2 del
del d['i'] #删除字典中指定的键值对
del d #删除字典
#3 clear()
d.clear() #清空字典中的内容
3)修改元素
d = dict.fromkeys("FishC")
#初始字典为{'F': None, 'i': None, 's': None, 'h': None, 'C': None}
d.update({'i': 105, 'h': 104})
#更新后字典为{'F': None, 'i': 105, 's': None, 'h': 104, 'C': None}
d.update(F='70', C='67')
#更新后字典为{'F': '70', 'i': 105, 's': None, 'h': 104, 'C': '67'}
4)查找元素
d['C'] #返回67,如果找不到元素则会报错
#1 in & not in
判断键是否在字典中
if 'C' in d:
print d['C']
#2 get()
基本语法:
get(key[, default]) #default设置找不到键时返回的值
#3 setdefault()
基本语法:
setdefault(key[, default]) #如果找不到键则为其添加值
视图对象
keys = d.keys
values = d.values
items = d.items()
5)copy()
e = d.copy() #拷贝
6)len()
len(d) #获取字典的长度
7)in¬ in
'C' in d #判断C是否在字典中
8)iter()
e = iter(d) #将字典变换为迭代器
3、嵌套
d = {"吕布":{"语文": 60, "数学": 70}, "关羽":{"语文": 80, "数学": 90}}
d["吕布"]["数学"] #返回70
d = {"吕布": [60, 70], "关羽": [80, 90]}
d["吕布"][1] #同样返回70
4、字典推导式
d = {'F': 70, 'i': 80, 's': 67, 'h': 78}
c = {v:k for k,v in d.items() if v > 70} #添加筛选的字典推导式
#结果是{80: 'i', 78: 'h'}
八、集合
集合具有不重复性,集合中的元素是唯一的
eg.判断列表中元素是否重复
s = [1, 2, 2, 3, 5]
len(s) == len(set(s))
1、创建集合
{"FishC", "Python"}
{s for s in "FishC"}
set("FishC")
Attention:
集合中的元素是无序的,所以无法通过下标索引
2、集合方法
1)copy()
拷贝
2)isdisjoint()
判断两个集合是否没有交集
s = set("FishC")
s.isdijoint(set("Python")) #可以直接传入"Python"
3)issubset()
判断是否是另一个集合的子集
s.issubset(set("www.FishC.com"))
s <= set("www.FishC.com") #结果返回True
s < set("FishC") #结果返回False
4)issuperset()
判断是否是另一个集合的超集
s.issuperset(set("Fish"))
s >= set("Fish") #结果返回True
s <= set("FishC") #结果返回False
5)union()
计算并集
s.union(1, 2, 3)
s | {1, 2, 3}
6)intersection()
计算交集
s.intersection("Fish")
s & set("Fish")
7)difference()
计算差集
s.difference("Python")
s - set("Python")
Attention:
以上几种集合运算的方法均支持多元素
8)symmetric_difference()
计算对称差集,先排除两个集合所有的共同元素,再将剩余所有的元素组成一个集合
s.symmetric_difference("Python")
s ^ set("Python")
Attention:
使用方法参数只要是可迭代对象即可,而使用运算符则只能是集合
3、可变集合和不可变集合
t = frozenset("FishC") #创建一个不可变集合
下面介绍只适用于可变集合的方法:
1)更新集合
基本语法:
update(*others)
Attention:
others表示支持多个参数
intersection_update(*others) #使用交集的方式更新集合
difference_update(*others) #使用差集的方式更新集合
symmtric_difference_update(*others) #使用对称差集的方式更新集合
2)插入元素
基本语法:
s.add("45")
3 )删除元素
#1 remove()
s.remove("s")
#2 discard()
s.discard("s")
Attention:
remove()和discard()的区别在于remove()移除集合中不存在的元素会报错,而discard()会静默处理
#3 pop()
随机弹出一个元素
s.pop()
可哈希:
不可变的对象可哈希hash()
只有可哈希的对象才可以作为字典的键和集合的元素
因此如果要使用嵌套集合,则一定要使用frozenset()
九、函数
1、创建和调用函数
def myfunc():
for i in range(3):
print("I love FishC.")
myfunc()
1)函数的参数
def myfunc(name, times): #name和times是形式参数,形参
for i in range(times):
print("I love {name}.")
myfunc("Python", 5) #"Python"和5是实际参数,实参
#1 位置参数
def myfunc(s, vt, o):
return "".join((o, vt, s))
myfunc("小甲鱼", "打了", "我") #返回"我打了小甲鱼"
#2 关键字参数
def myfunc(s, vt, o):
return "".join((o, vt, s))
myfunc(o="我", vt="打了", s="小甲鱼") #返回"我打了小甲鱼"
Attention:
位置参数必须在关键字参数之前
默认参数:
def myfunc(s, vt, o="小甲鱼"):
return "".join((o, vt, s))
myfunc("香蕉", "吃") #返回"小甲鱼吃香蕉"
Attention:
1、默认参数需要放在最后面 2、帮助文档函数/左边的参数只能使用位置参数,*右边的参数只能使用关键字参数
#3 收集参数
def myfunc(*args):
print("有{}个参数".format(len(args)))
print("第2个参数是:{}".format(args[1]))
myfunc("FishC", "Python")
#返回结果为:
#有2个参数
#第2个参数是:Python
Attention:
1、实现多个形参依靠的是元组的打包功能,*就是打包
(对于实参来说,*是是相反的功能即解包,可以将一个元组拆成多个参数)
2、实现多个返回值也是依靠的元组
3、除了收集参数如果还有其他的参数就需要使用关键字参数
#4 键值对作为参数
def myfunc(**kwargs):
print(kwargs)
myfunc(a=1, b=2, c=3)
#返回结果是{'a': 1, 'b': 2, 'c': 3}
Attention:
同样地,对于实参来说,**实现与形参相反的功能,可以将键值对拆包为多个参数
2)函数的返回值
def div(x, y):
if y == 0:
return "除数不能为零!!"
else:
return x / y
Attention:
1、函数只要执行了return语句就不会再执行后面的语句
2、定义函数时没有显示地返回值的话也会默认返回一个None
2、作用域
1)全局作用域
定义在任何函数的外面
2)局部作用域
定义在函数内部,也仅作用于函数内部
如果在存在同名的全局变量,函数内部仍会优先使用局部变量
global
强制将函数内部的变量更改为全局变量
x = 880
def myfunc():
global x
x = 520
print(x) #结果是520
3、嵌套函数
def funcA():
x = 520
def funcB():
x = 880
print("in funcB, x=", x)
funcB()
print("in funcA, x=", x)
#返回结果是:
# in funcB, x= 880
# in funcA, x= 520
Attention:
1、内部函数无法在外部被调用
2、内部函数可以访问外部函数的变量却无法对其进行修改
nonlocal()
在内部函数修改外部的值
def funA():
x = 520
def funB():
nonlocal x
x = 880
print("in funcB, x=", x)
funcB()
print("in funcA, x=", x)
#返回结果是:
# in funcB, x= 880
# in funcA, x= 880
LEGB:
局部作用域(Local)>嵌套函数的外层函数作用域(Enclosed)>
全局作用域(Global)>内置作用域(Build-In)
str = "小甲鱼把str给毁了"
#由于BIF属于内置作用域,故如果将str作为全局变量就会对其进行覆盖
4、闭包
调用内部函数
def funA():
x = 880
def funcB():
print(x)
return funcB
funcA() #返回funcB的地址
funcA()() #打印880
Attention:
外层函数变量的作用域会被保存下来,可以在内部函数中引用
def power(exp):
def exp_of(base):
return base ** exp
return exp_of
square = power(2)
cube = power(3)
eg.通过闭包保护游戏内角色位置
orgin = (0, 0) #原点坐标
legal_x = [-100, 100] #x轴合法范围
legal_y = [-100, 100] #y轴合法范围
def creat(pos_x=0, pos_y=0):
def moving(direction, step):
nonlocal pos_x, pos_y
new_x = pos_x + direction[0] * step
new_y = pos_y + direction[1] * step
if new_x < legal_x[0]:
pos_x = legal_x[0]
elif new_x < legal_x[1]:
pos_x = legal_x[1]
else:
pos_x = new_x #检验x轴位置是否合法
if new_y < legal_y[0]:
pos_y = legal_y[0]
elif new_y < legal_y[1]:
pos_y = legal_y[1]
else:
pos_y = new_y #检验y轴位置是否合法
return pos_x, pos_y
return moving
move = creat()
print("向右移动20步后,位置是:", move([1,0], 20))
Attention:
通过闭包,pos_x和pos_y就无法轻易地被访问到,且由于嵌套函数的外层作用域具有记忆功能,因而可以很好地实现位置的存储和保护
5、装饰器
def time_master(func):
print("开始运行程序...")
start = time.time()
func()
stop = time.time()
print("结束运行...")
print(f"一共耗费了{(stop-start):.2f}秒。")
def myfunc():
time.sleep(2)
print("Hello FishC.")
time_master(myfunc)
#开始运行程序...
#Hello FishC.
#结束运行...
#一共耗费了2.00秒。
使用装饰器修改后的程序:
def time_master(func):
call_func():
print("开始运行程序...")
start = time.time()
func()
stop = time.time()
print("结束运行...")
print(f"一共耗费了{(stop-start):.2f}秒。")
return call_func
@time_master
def myfunc():
time.sleep(2)
print("Hello FishC.")
myfunc()
Attention:
1、@time_master是语法糖,其相当于在定义myfunc()之后,调用myfunc()之前运行以下语句:
myfunc = time_master(myfunc) myfunc()
将myfunc作为参数传入time_master,此时不会执行call_func(),而是会将call_func()返回,然后再赋值给myfunc,myfunc就不是之前的那个myfunc了,而是经过装饰的myfunc
2、多个装饰器执行顺序是由下往上,离定义函数最近的先装饰
6、lambda表达式
基本表达式:
lambda arg1, arg2, arg3, ... argN : expression
eg.平方
squareX = lambda x : x * x
squareX(3) #返回9
lambda表达式可以使用在函数不允许出现的的地方,例如列表:
y = [lambda x : x * x, 2, 3]
y[0](y[1]) #将y[1]作为参数传进去,返回4
7、生成器
生成器是一种特殊的迭代器,每次调用生成一个数据,类似于一个生产机器,而列表和元组则是容器
语法上使用yield代替原先函数中的return
def counter():
i = 0
while i <= 5:
yield i
i += 1
for i in counter(): #每次调用执行到yield i就生成一个数据,暂停并保留状态
print(i) #输出结果是0, 1, 2, 3, 4, 5
eg.斐波那契数列
def fib():
back1, back2 = 0, 1
while True:
yield back1
back1, back2 = back2, back1 + back2
f = fib()
next(f)
生成器支持next语句
生成器表达式
(i ** 2 for i in range(10))