(1)变量名不能以数字开头
(2)变量名区分大小写
(3)变量名可以用汉字
(4)x,y=y,x可以实现x,y值互换
用单引号或者双引号将内容引起
用单还是双取决于字符串中有没有不可避免的单或双引号,以免系统误会
是在不能避免单双引号冲突时,可以用转义字符代替【加上去\即可转义】
原始字符串:转义字符需要正常使用,不作为转义字符时,可以在前面加上r,表示原始字符串,转义不生效
示例:print(r"D:\wenjianjiaA\wenjianjiaB\wenjianjiaC")
一句话末尾加 \ 表示这句话还未结束
实例:print("abc\n\
def")
或者可以通过将代码用括号包裹起来表示这是同一句代码
长字符串:前后用三个单引号或双引号,实现跨行字符串,即不用\n即可做换行。
示例:
“”“你好呀
我不用\n就可以换行了
怎么样”“”
字符串相加就是拼接
示例:“520”+“1314”,最后得到5201314
字符串乘以数字就是重复
示例:“我每天爱你3000遍”*3000,最后得到重复3000次的这句话
字符串输出【print】
print(i,"*",j,"=",i*j,end = "\t")
当不同类型进行拼接用“,”隔开,默认结束为换行符,当需要其它结束方式可以设置end=来进行设定。
随机数的使用【random】
import random
random.randint(1,10) #获取1-10的随机整数
x = random.getstate() #获取随机数的种子
random.setstate(x) #将随机数的种子重新设置,使得随机数复现
浮点数运算【decimal:十进制的】
import decimal
a = decimal.Decimal(0.1) #实例化decimal对象
b = decimal.Decimal(0.2)
print(a + b) #0.3
c = decimal.Decimal(0.3)
print(a + b == c) #True
整数
浮点数
由于Python的浮点数采用的是IEEE754标准存储浮点数,则浮点数在运算过程中会存在精度丢失,如0.1+0.2=0.300000000000000000004,所以往往导入decimal库来进行浮点数运算【decimal见4-2】
复数
x = 1 + 2j
x.real #1.0
x.imag #2.0
常见运算
a//b 地板除【向下取整】
divmod(a,b)【同时得到地板除和余数】
divmod(-3,2) = (-2,1)
abs(-520) = 520【取绝对值】
abs(3+4j)= 5【取复数的模】
int()【转整数】
float()【转浮点数】
complex()【转复数】
pow(2,3) = 2 ** 3 = 8【幂运算】
pow(2,3,5) => 2**3%5 = 3 【幂后求余】
表示为False的情况
#定义为False的对象
bool(False)
bool(None)
#值为0的数组类型
bool(0)
bool(0.0)
bool(0j)
bool(Decimal(0))
bool(Fraction(0,1))#分子为0分母为1的有理数
#空的序列和集合
bool('')
bool([])
bool(())
bool({})
bool(set())
bool(range(0))
布尔类型其实是特殊的整型类型
True + False # 1
True * False # 0
逻辑运算符
运算符 | 含义 |
---|---|
and | 左右同为True,结果为True |
or | 左右其中有一个True,结果为True |
not | True为False,False为True |
真值测试
Python中的所有类型均支持真值测试
3<4 and 4<5
#True
3 and 4
#4
"abc" or "bcd"
#'abc'
短路逻辑
3 and 4#4
3 or 4#3
从Python的角度看,无需完成所有运算,只需要把能确定结果的第一个结果输出即可,后面的不再进行运算
算数优先级
(not 1 or 0 and 1 or 3 and 4 or 5 and 6 or 7 and 8 and 9) == 4
(not 1) or (0 and 1) or(3 and 4) or( 5 and 6 )or (7 and 8 and 9) == 4
标号越大优先级越高【注:先 not 再 and 最后 or 】
if语法
small = a if a < b else b
print(small)
while -else语法
while i < 5:
print("循环内i的值为" + str(i))
if i == 2:
break
i += 1
else:
print("循环结束")
else中的语句仅在循环正常遍历结束后才运行,当通过break或return而退出时不运行
for-in语法
for each in "abcdefg":
print(each)
# a
# b
# c
# d
# e
# f
# g
sum = 0
for i in range(1000001):#求1000000以内的和
sum += i
print(sum)
#500000500000
列表中由[]括起来,其中可以存放所有类型的元素
arr = [1,2,3,4,5,"上山打老虎"]
for each in arr:
print(each)
# 1
# 2
# 3
# 4
# 5
# 上山打老虎
列表支持索引访问
arr[0] # 1
arr[1] # 2
arr[2] # 3
arr[3] # 4
arr[4] # 5
arr[5] # "上山打老虎"
列表中最后一个元素的两种方式
length = len(arr)
arr[length] # "上山打老虎"
arr[-1] # "上山打老虎"
arr[-2] # 5[倒数第二个元素就是-2]
列表切片
arr[0:3]
# [1, 2, 3]
arr[:3]
# [1, 2, 3]
arr[3:6]
# [4, 5, '上山打老虎']
arr[3:]
# [4, 5, '上山打老虎']
arr[:]
# [1, 2, 3, 4, 5, '上山打老虎']
arr[0:6:2]
# [1, 3, 5]
arr[::2]
# [1, 3, 5]
arr[::-2]
# ['上山打老虎', 4, 2]
arr[::-1]
# ['上山打老虎', 5, 4, 3, 2, 1]
列表的增删改查
增
append()增加单个对象
extend()增加一个课迭代的对象
s = [1,2,3]
s.append(4)
s # [1,2,3,4]
s.extend([5,6,7])
s # [1, 2, 3, 4, 5, 6, 7]
对比下面例子
m = [1,2,3]
m[len(m):]=[4]
m # [1, 2, 3, 4]
m[len(m):]=[5,6,7]
m # [1, 2, 3, 4, 5, 6, 7]
由于切片可以切出空片,即
m[len(m):]
# []
那么就可以对切出的空片进行赋值,从而实现对列表的扩展
insert(a,b) a:插入位子,b插入元素
删
改
通过索引修改单个元素
通过切片修改连续位置的多个元素
sort() 进行排序【从小到大】
reverse() 将列表中的元素反转
num = [1,5,4,6,2]
num.sort()
num # [1, 2, 4, 5, 6]
num.reverse()
num # [6, 5, 4, 2, 1]
num = [1,5,4,6,2]
num.sort(reverse=True)
num # [6, 5, 4, 2, 1]
查
count(元素) 查找某个元素出现的次数
index(元素) 查找某个元素在列表中第一个索引值
index(元素,a,b) 查找某个元素在a到b之间的第一个索引值
copy() 将一个列表拷贝到另一个列表【浅拷贝】
nums = [2,3,4,5,3,1,7,6,6]
num1 = nums.copy()
num1 # [2, 3, 4, 5, 3, 1, 7, 6, 6]
num2 = nums[:]
num2 # [2, 3, 4, 5, 3, 1, 7, 6, 6]
列表的运算
“+” 拼接两个列表
[1,2,3]+[4,5,6] # [1, 2, 3, 4, 5, 6]
“*” 列表中的元素重复3次
[1,2,3]*3 # [1, 2, 3, 1, 2, 3, 1, 2, 3]
嵌套列表
A=[0]*3
A # [0, 0, 0]
for i in range(3):
A[i] = [0]*3
A # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
A[1][1] = 1
A # [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
对比下面的例子:
B = [[0]*3]*3
B # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
B[1][1] = 1
B # [[0, 1, 0], [0, 1, 0], [0, 1, 0]]
用is可以检测是否指向同一个存储单元
A[0] is A[1]
# False
B[0] is B[1]
# True
原因为B中*3是对其进行重复引用而非复制3份
深拷贝与浅拷贝
浅拷贝:
copy或者切片拷贝两种方法,在一维列表中进行将所有内容进行拷贝,但是在二维列表中,浅拷贝仅仅拷贝外层的对象,在包含嵌套对象时拷贝只是其引用。
x = [[1,2,3],[4,5,6],[7,8,9]]
y = x.copy()
y # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
x[1][1] = 0
x # [[1, 2, 3], [4, 0, 6], [7, 8, 9]]
y # [[1, 2, 3], [4, 0, 6], [7, 8, 9]]
当x的数据被修改,y由于是x的浅拷贝,所以y对应的数据也被修改。此时需要进行深拷贝。
深拷贝
import copy
# copy模块的浅拷贝
x = [[1,2,3],[4,5,6],[7,8,9]]
y = copy.copy(x)
x[1][1] = 0
x # [[1, 2, 3], [4, 0, 6], [7, 8, 9]]
y # [[1, 2, 3], [4, 0, 6], [7, 8, 9]]
# copy模块的深拷贝
x = [[1,2,3],[4,5,6],[7,8,9]]
y = copy.deepcopy(x)
x[1][1] = 0
x # [[1, 2, 3], [4, 0, 6], [7, 8, 9]]
y # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
列表推导式
oho = [1,2,3,4,5]
oho = [i * 2 for i in oho]
oho # [2,4,6,8,10]
x = [i for i in range(10)]
x # [0,1,2,3,4,5,6,7,8,9]
x = [i + 1 for i in range(10)]
x # [1,2,3,4,5,6,7,8,9,10]
s = [[0] * 3 for i in range(3)]
s # [[0,0,0],[0,0,0],[0,0,0]]
even = [i for i in range(10) if 1 % 2 == 0]
even # [0,2,4,6,8]
matrix = [[1,2,3],
[4,5,6],
[7,8,9]]
res = [j for i in matrix for j in i]
res # [1, 2, 3, 4, 5, 6, 7, 8, 9]
[[x, y] for x in range(10) if x % 2 == 0 for y in range(10) if y % 3 == 0]
# [[0, 0], [0, 3], [0, 6], [0, 9], [2, 0], [2, 3], [2, 6], [2, 9], [4, 0], [4, 3], [4, 6], [4, 9], [6, 0], [6, 3], [6, 6], [6, 9], [8, 0], [8, 3], [8, 6], [8, 9]]
元组可以用括号进行包裹,也可以不带括号,直接用逗号隔开
rhyme = (1,2,3,"abc")
rhyme # (1, 2, 3, 'abc')
real = 1,2,3,'abc'
real # (1, 2, 3, 'abc')
元组内的元素不可以被修改,但元组中的元素指向一个可变列表则是列表里的内容是可以修改的
元组也可以进行切片,切片并不是再原始序列上进行修改,而是重新生成序列
元组同样像列表一样可以进行count()和index()
nums = 1,2,4,6,6,4,8,5,6,3
nums.count(6) # 3
nums.index(6) # 3
元组可以进行运算 “+”, “ * ”
nums = 1,2,3
nums * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3)
元组可以嵌套
num1 = 1,2,3
num2 = 4,5,6
num1,num2 # ((1, 2, 3), (4, 5, 6))
元组支持迭代
不存在元组推导式
生成一个元素的元组
type((123,))
<class 'tuple'>
元组的打包和解包【只要是可迭代的对象都可以】
t = (123,"abc",3.14)
x,y,z = t
x # 123
y # 'abc'
z # 3.14
序列包含可变序列和不可变序列,可变序列【列表】,不可变序列【元组、字符串】
运算 “ + ”、“ * ”
增量赋值
s=[1,2,3]
id(s) # 1977787638016
s=s*2
s # [1, 2, 3, 1, 2, 3]
id(s) # 1977787638016
当s为可变序列时,增量赋值不会改变其对应的存储结构
s=(1,2,3)
id(s) # 1977789553472
s=s*2
s # (1, 2, 3, 1, 2, 3)
id(s) # 1977788747200
当s为不可变序列,增量赋值相当于重新产生一个对象并赋值给s
is 和 not is 同一性运算符,判断是指向同一对象
x = "FishC"
y = "FishC"
x is y # True
x = [1,2,3]
y = [1,2,3]
x is y # False
in 和 not in 检测序列中是否包含某个元素
"C" in "aCC" # True
del 删除一个或多个指定的对象
x = 123
y = "abc"
del x,y
x
#Traceback (most recent call last):
# File "", line 1, in
# x
#NameError: name 'x' is not defined
x = [1,2,3,4,5]
del x [1:4]
x # [1,5]
x = [1,2,3,4,5]
del x [::2]
x # [2,4] 从第一个元素删除,步径为2
x = [1,2,3,4,5]
del x[:]
x # [] 相当于
x = [1,2,3,4,5]
x.claer()
序列相关函数
列表、元组、字符相互转换
list()、tuple()、str()
min()、max()找可迭代对象的最大最小值
min(s ,default = " ")可以通过default设定返回默认值
len()、sum()
s = [1,0,0,8,6]
len(s) # 5
sum(s) # 15
sum(s, start = 100) # 115
sorted()可以对任何可迭代对象进行排序,返回值为列表
【注意:】区分sorted()和sort()
s = [1,2,3,0,6]
sorted(s) # [0, 1, 2, 3, 6]
s # [1, 2, 3, 0, 6]序列未发生变化
s.sort()
s # [0, 1, 2, 3, 6]序列本身发生了变化
sorted(s,reverse = True) # [6, 3, 2, 1, 0]
s = ["Apple","Banana","Book","Pen","Fish"]
# 默认是按首字母的ASCII码来排序
sorted(s) # ['Apple', 'Banana', 'Book', 'Fish', 'Pen']
# 同样可以选择函数的返回结果进行排序
sorted(s, key = len)# ['Pen', 'Book', 'Fish', 'Apple', 'Banana']
reversed()产生一个迭代器
s # ['Apple', 'Banana', 'Book', 'Pen', 'Fish']
s.reverse()
s # ['Fish', 'Pen', 'Book', 'Banana', 'Apple']
rev = reversed(s) # 获取一个迭代器对象
list(rev) # ['Apple', 'Banana', 'Book', 'Pen', 'Fish']
tuple(reversed(range(0,10)))
# (9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
all():判断序列中是否所有元素为真
any():判断序列中是否存在元素为真
x = [0,1,1]
all(x) # False
any(x) # True
enumerate()
产生一个枚举对象,与索引构成元组
seasons = ["Spring","Summer","Fall","Winter"]
list(enumerate(seasons))
# [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
list(enumerate(seasons,start = 10))
# [(10, 'Spring'), (11, 'Summer'), (12, 'Fall'), (13, 'Winter')]
zip()拉链,将两个列表拉链起来组成一个新的元组对象
x = [1,2,3]
y = [4,5,6]
zipped = zip(x,y)
list(zipped)
# [(1, 4), (2, 5), (3, 6)]
z = [7,8,9]
list(zip(x,y,z))
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
z = "abcde"
list(zip(x,y,z))
# [(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c')]以最短的为主进行拉链
import itertools
zipped = itertools.zip_longest(x,y,z)
list(zipped)
# [(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c'), (None, None, 'd'), (None, None, 'e')]
map() 根据提供的函数对指定的可迭代对象的每个元素进行运算,并将返回运算结果的迭代器,当长度不一致时采用最短的运算
mapped = map(ord,"abc")
list(mapped)
# [97, 98, 99]
filter()【过滤器】 与map()函数的区别时map()函数返回的是计算结果的迭代器,而filter返回的是计算结果为真的迭代器。
fil = filter(str.islower,"abCdeFg")
list(fil)
# ['a', 'b', 'd', 'e', 'g']
迭代器和可迭代对象
fil = filter(str.islower,"abCdeFg")
list(fil)
# ['a', 'b', 'd', 'e', 'g']
list(fil)
# []
可迭代对象是可以进行进行多次遍历【列表、元组、字符串】
通过iter()可以将可迭代对象转换为迭代器
x = [1,2,3,4,5]
y = iter(x)
type(x)
#
type(y)
#
可以通过next()函数将迭代器中的元素逐个拿出来,没有则报错
x = [1,2,3,4,5]
y = iter(x)
next(y) # 1
next(y) # 2
next(y) # 3
next(y) # 4
next(y) # 5
next(y)
#Traceback (most recent call last):
# File "", line 1, in
# next(y)
#StopIteration
###可以设定next在迭代器没有元素后输出指定信息
z = iter(x)
x = [1,2,3]
z = iter(x)
next(z,"end") # 1
next(z,"end") # 2
next(z,"end") # 3
next(z,"end") # 'end'
字典的创建
直接创建
x = {"a":"张三","b":"李四"}
type(x)
#
x["b"] # '李四'
x["c"] = "王五"
x # {'a': '张三', 'b': '李四', 'c': '王五'}
每一个字典元素的结构为键:值对,通过键进行存取和写入元素。
dict()函数创建字典
b = dict(a="张三",b="李四")
b # {'a': '张三', 'b': '李四'}
注意:key中不能存在引号,原因等在【函数】章节解决
dict()中添加可迭代对象
c = dict([("a","张三"),("b","李四")])
c # {'a': '张三', 'b': '李四'}
d = dict({"a":"张三","b":"李四"})
d # {'a': '张三', 'b': '李四'}
混合法
e = dict({"a":"张三","b":"李四"},c="王五")
e # {'a': '张三', 'b': '李四', 'c': '王五'}
dict()中添加迭代器
f = dict(zip(["a","b","c"],["张三","李四","王五"]))
f # {'a': '张三', 'b': '李四', 'c': '王五'}
字典的相关操作
增
dict.fromkeys()从无到有初始化键值对
d = dict.fromkeys("Fish",250)
d # {'F': 250, 'i': 250, 's': 250, 'h': 250}
【注】字典和列表的区别:字典的key不可以重复,而列表元素可以重复
删
pop(元素)弹出对应key的值
d.pop('F') # 250
popitem()弹出最后一个字典元素的值
d.popitem()
# ('h', 250)
del()删除指定字典元素或者删除字典
del d['i']
d # {'s': 250}
clear()清空字典中的内容,但字典仍然还存在,可以添加
改
修改单个元素
d['s'] = 115
d.update([others]) 可以传入一个键值对,传入一个字典,或者传入一个键值对的可迭代对象
d.update({'i':105,'h':104})
d.update(F=70,s=100)
d # {'F': 70, 'i': 105, 's': 100, 'h': 104}
查
基本查找方法
d['c']
get()方法,在查找失败时可以输出默认对象
d.get('c',"no_c")
setdefault()如果查找成功则返回对应key的value,若查找失败则修改key的值
d # {'F': 70, 'i': 105, 's': 100, 'h': 104}
d.setdefault('F','100') #70
d.setdefault('M','100') #'100'
d # {'F': 70, 'i': 105, 's': 100, 'h': 104, 'M': '100'}
字典视图对象
keys = d.keys()
keys # dict_keys(['a', 'b', 'c', 'd'])
values = d.values()
values # dict_values([123, 123, 123, 123])
items = d.items()
items # dict_items([('a', 123), ('b', 123), ('c', 123), ('d', 123)])
e = d.copy()浅拷贝
len(d) 返回d的长度
in/not in 判断是否在列表中的key当中
iter(d) 将字典中的键返还为迭代器
it = iter(d)
next(it) # 'a'
next(it) # 'b'
next(it) # 'c'
next(it) # 'd'
在python3.7以后可以使用reversed()进行逆向排序
list(reversed(d))
# ['d', 'c', 'b', 'a']
字典推导式
d = {'F':70,'i':105,'s':104,'h':112}
b = {v:k for k,v in d.items()}
b # {70: 'F', 105: 'i', 104: 's', 112: 'h'}
c = {v:k for k,v in d.items() if v>100}
c # {105: 'i', 104: 's', 112: 'h'}
###通过字典推导式计算每个字符的编码值
d = {x:ord(x) for x in "abc"}
d # {'a': 97, 'b': 98, 'c': 99}
###由于字典的key中不包含重复值,故仅留三组键值对
d = {x:y for x in [1,3,5] for y in [2,4,6]}
d # {1: 6, 3: 6, 5: 6}
集合的特点
集合的表示
type({"one"})
#
{s for s in "abcdefg"}
#{'b', 'g', 'd', 'a', 'f', 'e', 'c'}
set([1,2,3,3,3,4])
# {1, 2, 3, 4}
s = [1,2,3,3,3,4]
len (s) == set(s)
# False 则说明由重复元素
t = frozenset("Fish")
t # frozenset({'h', 'F', 'i', 's'})
集合的内置方法
浅拷贝copy()
s = [1,2,3,3,3,4]
t = s.copy()
t # [1, 2, 3, 3, 3, 4]
集合是否与另一个可迭代对象构成的集合相关联【具有相同的元素】isdisjoint()
s = set("abcde")
s.isdisjoint("bcdef")
# False 说明由是与之相关的
s.isdisjoint("fgh")
# True 说明是与之无关的
集合是否是另一个可迭代对象元素构成集合的子集issubset()
s = set("abc")
s.issubset("abcdefg")
# True
集合是否是另一个可迭代对象元素构成集合的超集issuperset()
s = set("abcde")
s.issuperset("abc")
#True
并集union()
s.union("cdefg")
# {'d', 'b', 'a', 'g', 'f', 'e', 'c'}
###支持多参数
s.union("cdefgh",{1,2,3})
# {1, 2, 3, 'b', 'g', 'h', 'd', 'a', 'f', 'e', 'c'}
交集intersection() 支持多参数
差集difference() 支持多参数
对称差集symmetric_difference() 不支持多参数
集合中对于部分运算方法是可以通过数学符号来运算【注意只有集合之间才可以进行运算,可迭代对象不可以参与运算】
# 子集
s <= set("abc")
# 真子集
s < set("abc")
# 超集
s > set("abc")
# 真超级
s >= set("abc")
# 交集
set("abc")|set({1,2,3})
# {1, 2, 3, 'b', 'a', 'c'}
# 并集
set("abc")&set("bcd")
# {'b', 'c'}
# 差集
set("abcdefg")-set("cdefghi")
# {'b', 'a'}
# 对称差集
set("abcdefg")^set("cdefghi")
# {'b', 'h', 'i', 'a'}
可变集合的特有方法
update修改集合中的内容
s = set("abc")
s # {'c', 'a', 'b'}
s.update([1,1],"23")
s # {1, 'a', 'c', '3', '2', 'b'}
intersection_update()交集修改集合内容
difference_update()差集修改集合内容
symmetric_difference_update()对称差集修改集合内容
add()将元素插入集合
s = set("abc")
s # {'c', 'b', 'a'}
s.add("45")
s # {'c', 'b', '45', 'a'}
s.add((1,2,3))
s # {'a', (1, 2, 3), 'c', 'b', '45'}
注意update是将可迭代对象中每个元素插入到集合当中,而add方法是将可迭代对象当成一个整体进行插入
remove(elem)删除元素,若元素不存在则抛出异常
discard(elem)删除元素,若元素不存在则静默处理
pop()随机弹出元素
clear()清空集合
可哈希
只有可哈希的对象才可以作为字典的键或者集合的元素
字符串、元组由于是不可变的,所以是可哈西的
列表由于是可变的,所以不可哈希
hash()当为不可变对象可以求出唯一一个hash值,而当为可变对象则抛出异常,整数的hash值为其本身
{"abc":123}
{'abc': 123}
{[1,2,3]:123}
#Traceback (most recent call last):
# File "", line 1, in
# {[1,2,3]:123}
#TypeError: unhashable type: 'list'
同样,由于集合set也是可变的,故不可以在集合中嵌套集合,而可以通过frozenset来嵌套
s = {"abc"}
s # {'abc'}
m = {s,"d","e"}
#Traceback (most recent call last):
# File "", line 1, in
# m = {s,"d","e"}
#TypeError: unhashable type: 'set'
def myfunc():
pass # 占位符,无意义
myfunc()
def say(string,times):
for i in range(times):
print(f"i love {string}")
say("python",5)
"""
i love python
i love python
i love python
i love python
i love python
"""
如果在函数定义没有写return语句则默认返回一个None值
位置固定的参数成为位置参数,选定关键字的参数成为关键字参数
def myfunc(o,vt,s):
return "".join((o,vt,s))
print(myfunc("a","b","c"))
# abc
print(myfunc(o = "a",vt = "b",s = "c"))
abc
【注意】位置参数必须在关键字参数之前
print(myfunc("a",vt = "b",s = "c"))
# abc
默认参数
def myfunc(vt,s="苹果",o="石头"):
return "".join([vt,s,o])
print(myfunc("我爱"))
# 我爱苹果石头
【注意】默认参数必须在非默认参数之后
help函数
help(abs)
"""
Help on built-in function abs in module builtins:
abs(x, /)
Return the absolute value of the argument.
"""
【注意】在help函数中斜杠左边仅可以使用位置参数而斜杠右边可以使用位置参数或者关键字参数。在自己定义的函数也如此,例:
# 在“/”之前的函数 ==仅能== 用位置而“/”右边的可以使用关键字参数
def func(a,/,b,c)
# 在“*”之前的函数可以位置而“*”右边的 ==仅能== 使用关键字参数
def func(a,*,b,c)
收集参数【打包参数】
通过在形参前面加*使得收集多个元素,收集到的元素实质上是元组
def myfunc(*args):
return args
print(myfunc(1,3,4))
# (1, 3, 4)
通过在形参前面加**使得收集多个键值对,通过关键字参数收集到的键值对构成字典
def myfunc(**args):
return args
myfunc(a=1,b=2,c=3)
# {'a': 1, 'b': 2, 'c': 3}
此处解释了为什么在字典中使用dict()不需要使用引号,因为收集函数中将关键字参数转换为键值对传入
综合案例:
def myfunc(a,*b,**c):
print(a,b,c)
myfunc(1,2,3,4,x=5,y=6,z=7)
# 1 (2, 3, 4) {'x': 5, 'y': 6, 'z': 7}
解包参数
args = (1,2,3,4)
def myfunc(a,b,c,d):
print(a,b,c,d)
myfunc(*args)
# 1 2 3 4
kwargs = {'a':1,'b':2,'c':3,'d':4}
myfunc(**kwargs)
# 1 2 3 4
作用域
局部作用域
全局作用域
global语句:用于在函数内部声明当前的变量是全局变量【不推荐使用】
x = 100
def myfunc():
global x
x = 200
print(x) # 100
myfunc()
print(x) # 200
嵌套函数
def funA():
x = 520
def funB():
x = 886
print("In funB x = ",x)
funB()
print("In funA x = ",x)
funA()
# In funB x = 886
# In funA x = 520
nolocal:在内部修改外部作用域
def funA():
x = 520
def funB():
nonlocal x
x = 886
print("In funB x = ",x)
funB()
print("In funA x = ",x)
funA()
# In funB x = 886
# In funA x = 886
【注意 】global修改的是函数体外的全局变量,nonlocal修改的是上一层嵌套的函数变量
闭包【工厂函数】
def power(exp):
def exp_of(base):
return base ** exp
return exp_of
power(2)
# .exp_of at 0x000001BF0E4C3E20>
在工厂函数中,返回的是一个内层函数对象,这样就可以直接访问内层函数的内容。其中return语句无需给函数名称加()。嵌套函数中内层函数可以存储记忆外层函数作用域中的变量。
square = power(2)
cube = power(3)
square(2) # 4
cube(3) # 27
def outer():
x = 0
y = 0
def inner(x1,y1):
nonlocal x,y
x += x1
y += y1
print(f"x={x},y={y}")
return inner
func = outer()
func(1,1)
# x=1,y=1
func(2,-1)
# x=3,y=0
装饰器
【前要】python可以将一个函数作为参数传入到另一个函数
def myfunc():
print("正在调用myfunc")
def report(func):
print("正在调用report")
func()
print("func调用完毕")
report(myfunc)
# 正在调用report
# 正在调用myfunc
# func调用完毕
【案例】时间管理大师
def time_master(func):
print("开始计时")
start_time = time.time()
func()
end_time = time.time()
print(f"共用时{(end_time - start_time):.2f}s")
def myfunc():
time.sleep(2)
print("In the myfunc")
time_master(myfunc)
# 开始计时
# In the myfunc
# 共用时2.02s
【装饰器语法糖】:在不修改原有代码的前提下实现函数功能
import time
def time_master(func):
def call_func():
print("开始计时")
start_time = time.time()
func()
end_time = time.time()
print(f"共用时{(end_time - start_time):.2f}s")
return call_func
@time_master
def myfunc():
time.sleep(2)
print("the program is end")
myfunc()
开始计时
the program is end
共用时2.01s
【装饰器本质】
import time
def time_master(func):
def call_func():
print("开始计时")
start_time = time.time()
func()
end_time = time.time()
print(f"共用时{(end_time - start_time):.2f}s")
return call_func
def myfunc():
time.sleep(2)
print("the program is end")
myfunc = time_master(myfunc)
myfunc()
【实质】在使用myfunc函数时并非直接调用myfunc()而是先将myfunc作为参数传入time_master中得到返回值后重新复制给myfunc进而产生一个函数对象,从而再通过myfunc()进行函数调用
【给装饰器传递参数】
import time
def show_time(msg):
def time_master(func):
def call_func():
print("开始计时")
print(msg)
start_time = time.time()
func()
end_time = time.time()
print(f"共用时{(end_time - start_time):.2f}s")
return call_func
return time_master
@show_time(msg="这是最外层的消息")
def myfunc():
time.sleep(2)
print("the program is end")
myfunc()
lambda表达式【匿名函数】
lambda 参数:表达式
【传统函数与lambda的对比】
def squareX(x):
return x ** 2
squareY = lambda y: y ** 2
print(squareX(3)) # 9
print(squareY(3)) # 9
调用lambda表达式的方法和调用函数的方法一样,都是通过函数名()来调用
【lambda和函数的区别】
lambda由于是一个表达式语句,故可以放在参数中
lambda由于是一个表达式可以放在不允许def出现的地方
y = [lambda x: x ** 2, 2, 3]
print(y[0](y[1])) # 4
【应用】
mapped = map(lambda x: ord(x) + 10, "apple")
print(list(mapped))
# [107, 122, 122, 118, 111]
print(list(filter(lambda x: x % 2, range(10))))
# [1, 3, 5, 7, 9]
生成器:用yield表达式代替return语句即可,在每次调用提供一个数据,并记住当时状态,在yield被调用后停止在yield语句,知道下次调用后继续执行生成器语句
def couter():
i = 0
while i <= 5:
yield i
i += 1
for i in couter():
print(i)
生成器可以看做一个可迭代对象,同样支持next()
for i in couter():
print(i)
print("-------------")
c = couter()
print(next(c))
print(next(c))
print(next(c))
print(next(c))
print(next(c))
生成器表达式–利用推导的方式产生生成器
t = (i ** 2 for i in range(10))
print(next(t)) # 0
print(next(t)) # 1
print(next(t)) # 4
print(next(t)) # 9
print(next(t)) # 16
【注意】和列表推导式的区别
x = [i for i in range(10)]
x # [0,1,2,3,4,5,6,7,8,9]
列表推导式是将表达式的结果构成一个列表,外面包裹[]
生成器推导式产生的是一个可迭代器,外面包裹()
递归–函数调用自身的过程
def factIter(n):
if n == 1:
return 1
else:
return n * factIter(n - 1)
print(factIter(5))
汉诺塔
def hanoi(n, x, y, z):
if n == 1:
print(x, "-->", z) # 如果只有一层,直接将x移动到z
else:
hanoi(n - 1, x, z, y) # 将x上面的n-1层移动到y
print(x, "-->", z) # 将最下面的从x移动到z
hanoi(n - 1, y, x, z) # 将y上面的n-1层移动到z
n = int(input("请输入汉诺塔层数"))
hanoi(n, 'A', 'B', 'C')
函数文档
def printfunc():
"""
测试
:parameter none
:return: none
"""
print("测试")
help(printfunc())
在函数最前面写入备注
类型注释 -函数作者对用户的提示
def times(s: str = "abc", n: int = 3) -> str:
return s * n
print(times("张三", 3)) # 张三张三张三
内省 : 获取对象相关的信息,语法是__关键字__
times.__name__ # 查询函数名称
times.__annotations__ # 查询函数原型
times.__doc__ # 查询函数注释
高阶函数:接收函数作为参数的函数functools
functools.reduce(函数对象,可迭代对象)
def add(a, b):
return a + b
import functools
print(functools.reduce(add, [1, 2, 3, 4, 5])) # 15
【实质】
add(add(add(add(1,2),3),4),5)
【阶乘】
print(functools.reduce(lambda x, y: x * y, range(1, 11))) # 3628800
functools.partial偏函数:对函数进行二次包装【实质是一个闭包】
import functools
square = functools.partial(pow, exp=2)
print(square(2))
@functools.wraps(func)
标准库 functools 中的 wrap 函数用于包装函数, 不改变原有函数的功能, 仅改变原有函数的一些属性, 例如 __name__
, __doc__
, __annotations__
等属性
【注意】'w’打开文件时文件就会被清空重新写入
路径处理 -pathlib 的基础使用
【列出子目录】
>>> from pathlib import Path # 导入模块
>>> p = Path('.')
>>> [x for x in p.iterdir() if x.is_dir()]
[PosixPath('.pip'), PosixPath('.pki'), PosixPath('.ansible'), PosixPath('.ssh'), PosixPath('.cache')]
【查询路径属性】
>>> p = Path('.')
>>> p.exists() # 判断是否存在
True
>>> p.is_dir() # 判断是否为文件夹
True
>>> p.is_file() # 判断是否为文件
False
>>> p.is_absolute() # 判断是否为绝对路径
False
>>> path = Path('/tmp/aaa.txt')
>>> path.name # 获取文件名
'aaa.txt'
>>> path.stem # 获取文件名,不带后缀
'aaa'
>>> path.suffix # 获取文件后缀
'.txt'
>>> path.parent # 获取上级目录
PosixPath('/tmp')
>>> path.root # 获取根路径
'/'
>>> path.parts # 将路径分割成元祖
('/', 'tmp', 'aaa.txt')
>>> path.stat() # 获取文件信息
os.stat_result(st_mode=33188, st_ino=134896383, st_dev=64768, st_nlink=1, st_uid=0, st_gid=0, st_size=4, st_atime=1645078071, st_mtime=1645078071, st_ctime=1645078071)
>>> path.resolve() # 获取绝对路径
PosixPath('/tmp/aaa.txt')
>>> path.cwd() # 获取当前路径
PosixPath('/tmp')
>>> path.home() # 获取家目录
PosixPath('/root')
【文件修改】
当target
是string
时,重命名文件或文件夹;当target
是Path
时,重命名并移动文件或文件夹。
path.rename(target)
重命名当前文件或文件夹,如果target
所指示的文件或文件夹已存在,则覆盖原文件。
path.replace(target)
path为空文件夹的时候,删除该文件夹
>>> path = Path('/tmp/aaa')
>>> path.exists()
True
>>> path.rmdir()
>>> path.exists()
False
删除文件或目录,目录非空触发异常。
>>> path = Path('/tmp/bbb')
>>> path.unlink()
Traceback (most recent call last):
File "" , line 1, in <module>
File "/usr/local/python3/lib/python3.8/pathlib.py", line 1324, in unlink
self._accessor.unlink(self)
IsADirectoryError: [Errno 21] Is a directory: '/tmp/bbb'
根据路径创建文件夹,parents=True
时,会依次创建路径中间缺少的文件夹。
>>> path = Path('/tmp/aaa/bbb/ccc')
>>> path.mkdir()
Traceback (most recent call last):
File "" , line 1, in <module>
File "/usr/local/python3/lib/python3.8/pathlib.py", line 1287, in mkdir
self._accessor.mkdir(self, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/aaa/bbb/ccc'
>>> path.mkdir(parents=True)
with上下文管理器
不需要手动关闭文件,确保资源的释放
保证程序中只要打开文件都能正确关闭
f = open("test.txt","w")
f.write("hello, python")
print(1 / 0)
f.close()
【注意】由于1/0是不合法的,故程序会被中断ZeroDivisionError: division by zero且不会写入文档。于是为了避免这种问题的出现,可以用with上下文管理器
with open("test.txt", "w") as f:
f.write("hello python")
print(1/0)
【注意】with上下文管理器可以保证文件的正常关闭
pickle【泡菜】将python对象保存为文件形式【序列化】
dump存储为二进制文件
import pickle
x, y, z = 1, 2, 3
s = "hello python"
l = ["abc", 520, 3.14]
d = {"a": 1, "b": 2}
with open("test.pkl", "wb") as f:
pickle.dump(x, f)
pickle.dump(y, f)
pickle.dump(z, f)
pickle.dump(s, f)
pickle.dump(l, f)
pickle.dump(d, f)
load解析文件
import pickle
with open("test.pkl", "rb") as f:
x = pickle.load(f)
y = pickle.load(f)
z = pickle.load(f)
s = pickle.load(f)
l = pickle.load(f)
d = pickle.load(f)
print(x, y, z, s, l, d, sep="\n")
#########################
# 解包
with open("test.pkl", "rb") as f:
x, y, z, s, l, d = pickle.load(f)
print(x, y, z, s, l, d, sep="\n")
捕获异常
try:
1/0
except ZeroDivisionError:
print("error")
【注意】
当except后无具体异常类型,则捕获全体异常
当except后跟什么类型捕获什么类型的异常
出现异常执行except中代码块儿的内容
当except捕获的异常与try中的异常不一致还会报错
as可以将异常原因捕捉到一个对象中
try:
1 / 0
except ZeroDivisionError as e:
print(e)
# division by zero
可以将except需要补货的异常封装到元组中检测
try:
1 / 0
except (ZeroDivisionError,ValueError,TypeError):
pass
可以对异常逐个检测
try:
1 / 0
520+"python"
except ZeroDivisionError:
print("除数不能为0")
except ValueError:
print("值不正确")
except TypeError:
print("类型不正确")
try-except-else
如果try中的内容没发生异常,则执行else中的内容
try-except-finally
不论except内容是否执行,finally均会执行,常用来用收尾工作
try-finally
try:
while True:
pass
finally:
print("end")
异常的内嵌
raise语句
raise ValueError("值不正确")
Traceback (most recent call last):
File “O:\Python_Demo\Exception.py”, line 1, in
raise ValueError(“值不正确”)
ValueError: 值不正确
【注意】raise用来直接生成错误信息,但必须定义已经存在的错误类型而不能自定义错误类型
【下例】替换其他错误类型
try:
1 / 0
except:
raise ValueError("值不正确")
Traceback (most recent call last):
File “O:\Python_Demo\Exception.py”, line 2, in
1 / 0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “O:\Python_Demo\Exception.py”, line 4, in
raise ValueError(“值不正确”)
ValueError: 值不正确
【下例】异常链,将ZeroDivisionError与ValueError链接
raise ValueError("error") from ZeroDivisionError
Traceback (most recent call last):
File "O:\Python_Demo\Exception.py", line 1, in
raise ValueError("error") from ZeroDivisionError
ValueError: error
assert断言–用来调试
s = "abc"
assert s == "abc"
assert s != "abc"
Traceback (most recent call last):
File “O:\Python_Demo\Exception.py”, line 3, in
assert s != “abc”
AssertionError