大家好,小编为大家解答python中zip函数的作用的问题。很多人还不知道pythonzip函数的作用,现在让我们一起来看看吧!
大家好,本文将围绕python中2f的用法展开说明,python中2f和2d是一个很多人都想弄明白的事情,想搞清楚python中{:.2f}需要先了解以下几个事情。
Source code download: 本文相关源码
一、数据类型
二、分支和循环
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中断循环不会执行elsepython作品展示。
#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,"上山打老虎"] #有名列表
元素下标:
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
(2)
4)替换元素
heros[4]="钢铁侠"
heros[3:]=["武松", "林冲", "李逵"]
5)元素排序
nums = [3, 1, 4, 5, 2, 7, 6]
() #排序
nums.reverse() #倒序
#也可以一步到位
(reverse=True)
6)查找元素
nums.count(3) #返回列表中3的个数
heros.index("绿巨人") #返回“绿巨人”这个元素的下标
heros.index("绿巨人", 1, 4) #从下标1~4查找“绿巨人”这个元素下标
7)列表复制
属于浅拷贝!!!
nums_copy1 = ()
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 = (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 fishcx.casefold()
所有字母小写(还可以处理其他语言字符)i love fishcx.title()
所有单词的首字母大写,其他小写I Love Fishcx.swapcase()
大小写翻转i lOVE fISHcx.upper()
所有字母大写I LOVE FISHCx.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 整数
#2 浮点数
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()
判断是否所有元素的值都为Trueany()
判断是否存在元素的值为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(""))
s <= set("") #结果返回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 = ()
func()
stop = ()
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 = ()
func()
stop = ()
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))
原文地址1:https://blog.csdn.net/2301_81895257/article/details/135813343
python手册 http://www.78tp.com/python/