零基础学python
打印
#sep是几个字符中间依靠什么连接,默认空字符
print('hello jwq','zhn','zzz',sep='|')
#end是结尾什么连接,默认\n,换行
print('hello',end=',')
数值类型
#int 整型 type() 里面是判断类型
num=1
print(type(num))
#打印内容<class 'int'>
#float 浮点型
num=0.5
print(type(num))
#打印内容<class 'float'>
#bool 布尔类型 False True 大小写固定写法 这两个也可以当做整型False=0 True=1
num=True
print(type(num))
#打印内容<class 'bool'>
#complex 复数型 其中的2为实部,3为虚部,j为虚数单位,这个也只能是j
num=2+3j
print(type(num))
#打印内容<class 'complex'>
num1=2+3j
num2=3+2j
print(num1+num2)
#打印内容(5+5j)
#str 字符串类型
num='123'
print(type(num))
#打印内容<class 'str'>
格式化输出
#%s格式化输出 占位符 注意% name 中间空一格,不空也能输出,最好空一下
name='jwq'
print('我的名字:%s' % name)
#%d 整数输出 其中的4位数字位数,刚好为顶格,有多前面会加空格(前面设置了0(如04)除外,会用0补齐),少了还是正常显示
name='jwq'
age=12
print('我的名字:%s,我的年龄:%04d' % (name,age))
#%f 浮点数 默认后面补6位,遵循四舍五入 .2一定要加点,不加就是整数(会变成默认6位),加了位数就不遵循四舍五入了,直接舍去
age=1.2337
print('%.2f' % age)
#%% 后面加()就行了
print('我是%%的%%' % ())
#输出 我是%的%
#f格式化 类似于模板语法
name='jwq'
age=18
print(f'我的名字:{name},我的年龄:{age}')
#输出 我的名字:jwq,我的年龄:18
算数运算符
#加法
print(1+1)
#输出 2
#减法
print(1-1)
#输出 0
#乘法
print(1*1)
#输出 1
#除法 商一定是浮点型,且除数不能为0,向下取整,只要未被除尽一直除,不四舍五入
print(1/3)
#输出 0.3333333333333333
#取余 除法取余数
print(4%3)
#输出 1
#幂 相当于2的3次方
print(2**3)
#输出 8
#取整除 若有浮点数,也会用浮点数
print(3//2)
#输出 1
#如下
print(5.6//2)
print(5//2.0)
#都输出 2.0
#优先级顺序 可以用()调整优先级
幂>乘除取余取整除>加减
#+= 赋值运算符 等同于a1=a1+1
a1=1
a1+=a1
print(a1)
#输出 2
#+= 赋值运算符 等同于a1=a1-1
a1=1
a1-=a1
print(a1)
#输出 0
输入函数
name=input("请输入你的名字:")
print(name)
#输出 请输入你的名字:123
#输出 123
转义符
#制表符 \t 通常占用四个字符
print('姓名\t年龄\t电话')
#输出 姓名 年龄 电话
#换行符 \n
print('姓名\n年龄\n电话')
#输出 姓名
#输出 年龄
#输出 电话
#回车符 \r 将当前位置移到最开头
print('姓名\r年龄\r电话')
#输出 电话
#反斜杠 \\
print('姓名\\年龄\\电话')
#输出 姓名\年龄\电话
#r 就是里面不转义,取消转义
print(r'姓名\\年龄\\电话')
#输出 姓名\\年龄\\电话
if判断
age=19
if age<18:
print("你还没有成年哦!")
else:
print('你成年了')
#输出 你成年了
#在写一个成绩判断
score=input('请输入你的成绩:')
if score<'60':
print("成绩不合格!")
else:
print(f'成绩合格了,成绩为{score}')
#输入 请输入你的成绩:99
#输出 请输入你的成绩:99
比较运算符
# ==
print(100 == 100)
#输出 True
# !=
print(100 != 100)
#输出 False
# > <
print(100 > 90)
print(100 < 90)
#输出 True
#输出 False
逻辑运算符
# and 两边都为真才是真,一边为假就是假
print(100>90 and 90>80)
#输出 True
# or 一边为真就是真
print(100>90 or 90<80)
#输出 True
# not 表示相反结果 本来为假,加入了not就为真
print(not 100<90)
#输出 True
三目运算(三元表达式)
age=19
print("你还没有成年哦!") if age<18 else print('你成年了')
#输出 你成年了
#elif 第n个判断条件
age=19
if age<18:
print("你还没有成年哦!")
elif 18<age<23:
print('你在读大学哦')
elif age>23 :
print('你已经长大了')
#输出 你在读大学哦
# if嵌套
score=input('请输入你的成绩:')
if score<'60':
print('成绩不合格')
else :
if '60'<score<'80':
print('成绩及格')
elif '80'<score<'90':
print('成绩良好')
else:
print('成绩优秀')
#输入 请输入你的成绩:91
#输出 成绩优秀
循环
# while循环 如果while循环条件一直为true,那么就是死循环,比如这里不加i+=1
i=1
while i<5:
print('继续努力!')
i+=1
#输出 继续努力!
#输出 继续努力!
#输出 继续努力!
#输出 继续努力!
# while循环嵌套
i=1
while i<3:
print('继续努力!')
i+=1
j=1
while j<3:
print('天天向上!')
j+=1
#输出 继续努力!
#输出 天天向上!
#输出 天天向上!
#输出 继续努力!
#输出 天天向上!
#输出 天天向上!
# for循环(迭代循环)
str='abcd'
for i in str :
print(i)
#输出 a
#输出 b
#输出 c
#输出 d
# range循环计数器 第一个参数是开始,第二个参数是结束,第三个是步长,遵循左闭右开
for i in range(0,3) :
print(i)
#输出 0
#输出 1
#输出 2
#做一个1+2+3+...+100的结果
num=0
for i in range(1,101) :
num+=i
print(f'最终的计算结果:{num}')
#输出 最终的计算结果:5050
# break 直接退出循环
num=0
for i in range(1,5) :
num+=i
print(i)
if num==3:
print('我等于3了,该直接退出了')
break
#输出 1
#输出 2
#输出 我等于3了,该直接退出了
# continue
num=0
for i in range(1,5) :
num+=i
print(i)
if num==3:
print('我等于3了,该退出当前循环了')
continue
#输出 1
#输出 2
#输出 我等于3了,该退出当前循环了
#输出 3
#输出 4
编码
# Unicode
name='jwq'
name1=name.encode()
name2=name1.decode()
print(name1)
print(name2)
#输出 b'jwq'
#输出 jwq
#uft-8
name='蒋先生'
name1=name.encode('utf-8')
name2=name1.decode('utf-8')
print(name1)
print(name2)
#输出 b'\xe8\x92\x8b\xe5\x85\x88\xe7\x94\x9f'
#输出 蒋先生
字符串运算符
# +
name='蒋先生'
name1='太帅了'
print(name+name1)
# *
name='蒋先生'
name1='太帅了\n'
print((name+name1)*2)
#输出 蒋先生太帅了
#输出 蒋先生太帅了
# in not in
name='jwq'
print('j' in name)
print('j' not in name)
#输出 True
#输出 False
#[] 下标开始从0开始,从右往左 -1开始
name='jwq'
print(name[0])
print(name[-1])
#输出 j
#输出 q
#切片
name='jwq'
print(name[0:2])
print(name[0:-1])
print(name[1:])
print(name[:1])
print(name[:])
print(name[0::2]) #步长为2去切
print(name[0:2:2])#0-2步长为2去切
#输出 jw
#输出 jw
#输出 #输出 wq
#输出 j
#输出 jwq
#输出 jq
#输出 j
字符串常见操作
# find,index 寻找字符串,如果存在就返回字符串所在下标,find如果不在则返回-1,index直接报错
name='jwq'
print(name.find('w'))
print(name.index('w'))
#输出 1
#输出 1
# count 某个字符在字符串中出现的次数,不存在显示0
name='jwqqwj'
print(name.count('w'))
#输出 2
# startswith 某个字符串是否在这个字符串开头,如果给定一个范围就在范围中寻找
# endswith 看结尾,其他同上
name='jwqqwj'
print(name.startswith('jwq'))
print(name.endswith('wj'))
#输出 True
#输出 True
# isupper 所有字母是否为大写
name='jwqqwj'
print(name.isupper())
# replace 替换
name='jwqqwj'
print(name.replace('j','z'))
print(name.replace('j','z',1))
#输出 zwqqwz
#输出 zwqqwj
#切割 根据指定的分割符来进行分割,这里以逗号为例
name='jwq,qwj'
print(name.split(','))
#输出 ['jwq', 'qwj']
# capitalize 第一个字符大写,其他都小写
name='jwq,qwj'
print(name.capitalize())
#输出 Jwq,qwj
# lower 全部小写
name='JWQQWJ'
print(name.lower())
#输出 jwqqwj
# upper 全部转为大写
name='jwqqwj'
print(name.upper())
#输出 JWQQWJ
list
list=[1,2,'jwq',3]
print(list)
#输出 [1,2,'jwq',3]
# append 添加对象
list=[1,2,'jwq',3]
list.append('zhn')
print(list)
#输出 [1, 2, 'jwq', 3, 'zhn']
# extend 分散添加 添加的对象一定是可迭代的
list=[1,2,'jwq',3]
list.extend('zhn')
print(list)
#输出 [1, 2, 'jwq', 3, 'z', 'h', 'n']
# insert 下标添加 指定位置如果有元素,则元素后移
list=[1,2,'jwq',3]
list.insert(4,'zhn')
print(list)
#输出 [1, 2, 'jwq', 3, 'zhn']
# [] 通过下标修改
list=[1,2,'jwq',3]
list[0]=3
print(list)
#输出 [3, 2, 'jwq', 3]
# in not in 元素是否存在字符串中
list=[1,2,'jwq',3]
print(2 in list)
print(2 not in list)
#输出 True
#输出 False
# del 删除元素
list=[1,2,'jwq',3]
del list[1]
print(list)
#输出 [1, 'jwq', 3]
# pop 删除指定下标元素 默认删除最后一个
list=[1,2,'jwq',3]
list.pop(1)
print(list)
#输出 [1, 'jwq', 3]
# remove 删除指定元素
list=[1,2,'jwq',3]
list.remove(2)
print(list)
#输出 [1, 'jwq', 3]
# sort 排序 默认从小到大
list=[1,55,3,18]
list.sort()
print(list)
#输出 [1, 3, 18, 55]
# reverse 倒序
list=[1,55,3,18]
list.reverse()
print(list)
#输出 [18, 3, 55, 1]
#列表推导式
list=[]
[list.append(i) for i in range(1,6)]
print(list)
[list.append(i) for i in range(1,6) if i%2==1]
print(list)
#输出 [1, 2, 3, 4, 5]
#输出 [1, 3, 5]
元组
# 元组 只有一个元素时,末尾加逗号 元组只能查询,不可以增删改
tup=(1,2,3,'jwq')
print(type(tup))
#输出 <class 'tuple'>
字典
# 字典键是惟一的,值可以重复
dic={'name':'jwq','age':18}
print(type(dic))
#输出 <class 'dict'>
# [键名] .get(键名) .get这个键名不存在,返回None
dic={'name':'jwq','age':18}
print(dic['name'])
print(dic.get('name'))
#输出 jwq
#输出 jwq
# 修改键值
dic={'name':'jwq','age':18}
dic['age']=20
print(dic)
#输出 {'name': 'jwq', 'age': 20}
# 添加元素
dic={'name':'jwq','age':18}
dic['size']=20
print(dic)
#输出 {'name': 'jwq', 'age': 18, 'size': 20}
#删除元素
dic={'name':'jwq','age':18}
del dic['name']
print(dic)
#输出 {'age': 18}
# pop 删除指定元素
dic={'name':'jwq','age':18}
dic.pop('name')
print(dic)
dic.popitem() #3.7版本以前随机删除,3.7以后默认删除最后一个
print(dic)
#输出 {'age': 18}
#输出 {'name': 'jwq'}
#清空字典
dic={'name':'jwq','age':18}
dic.clear()
print(dic)
#输出 {}
#长度
dic={'name':'jwq','age':18}
print(len(dic))
#输出 2
# keys() 返回所有键名
dic={'name':'jwq','age':18}
print(dic.keys())
#输出 dict_keys(['name', 'age'])
# values() 返回所有键值
dic={'name':'jwq','age':18}
print(dic.values())
#输出 dict_values(['jwq', 18])
# items() 键值对以元组的形式
dic={'name':'jwq','age':18}
print(dic.items())
#输出 dict_items([('name', 'jwq'), ('age', 18)])
集合
# 定义空集合使用set() 集合具有无序性,每次运行都是随机打乱的,数字除外,集合无序是因为涉及hash表,数字为什么不变,是因为hash中数字是它本身,不能修改集合中的值,集合有唯一性,可以自动去重,集合只有添加和删除
s={1,2,3}
print(type(s))
#输出 <class 'set'>
# add 添加 一次只能添加一个元素
s={1,2,3}
s.add(4)
print(s)
#输出 {1, 2, 3, 4}
# update 把传入元素拆分,一个个放进集合,由于无序性,每次运行都不一样 元素必须是能够被我们for循环取值的可迭代对象
s={1,2,3}
s.update('456')
print(s)
#输出{1, 2, 3, '4', '6', '5'}
# remove 删除元素
s={1,2,3}
s.remove(1)
print(s)
#输出 {2, 3}
# pop 默认删除第一个
s={1,2,3}
s.pop()
print(s)
#输出 {2, 3}
# discard 有这个值就删除,没有不做改变
s={1,2,3}
s.discard(2)
print(s)
#输出 {1, 3}
# & 交集
s1={1,2,3}
s2={2,3,4}
print(s1 & s2)
#输出 {2, 3}
# | 并集
s1={1,2,3}
s2={2,3,4}
print(s1 | s2)
#输出 {1, 2, 3, 4}
类型转换
# int() 浮点型强转为整型,去掉小数点
age=12.2
print(int(age))
#输出 12
# float() 整型强转为浮点型,加小数点
age=12
print(float(age))
#输出 12.0
# str() 整型强转为字符型
age=12
print(type(str(age)))
#输出 <class 'str'>
# eval 计算字符串里面数字 它也是可以实现list、dict、tuple和str之间的转换
a=eval('10+10')
print(a)
print(type(a))
#输出 20
#输出 <class 'int'>
# list 支持转换成list的类型:str、tuple、dict、set
a=(1,2,3)
print(list(a))
#输出 [1, 2, 3]
深浅拷贝
# 深浅拷贝只针对可变对象(可变对象定义看下面)
# 浅拷贝 赋值内存地址是一样的
list1=[1,2,3,4]
list2=list1
print('list1:',list1)
print('list2:',list2)
list1.append(5)
print('list1:',list1)
print('list2:',list2)
#输出 list1: [1, 2, 3, 4]
#输出 list2: [1, 2, 3, 4]
#输出 list1: [1, 2, 3, 4, 5]
#输出 list2: [1, 2, 3, 4, 5]
# 浅拷贝 copy id的内存地址是不同的 嵌套列表中一起改变了,因为他们的内存地址是一样的
import copy
list1=[1,2,3,4,[5,6,7]]
list2=copy.copy(list1)
print('list1:',list1)
print('list2:',list2)
list1.append(5)
print('list1:',list1)
print('list2:',list2)
list1[4].append(8)
print('list1:',list1)
print('list2:',list2)
print('list1[4]:',id(list1[4]))
print('list2[4]:',id(list2[4]))
#输出 list1: [1, 2, 3, 4, [5, 6, 7]]
#输出 list2: [1, 2, 3, 4, [5, 6, 7]]
#输出 list1: [1, 2, 3, 4, [5, 6, 7], 5]
#输出 list2: [1, 2, 3, 4, [5, 6, 7]]
#输出 list1: [1, 2, 3, 4, [5, 6, 7, 8], 5]
#输出 list2: [1, 2, 3, 4, [5, 6, 7, 8]]
#输出 list1[4]: 2033598556040
#输出 list2[4]: 2033598556040
#深拷贝(数据完全不共享) 可以看到无论是外层还是内层都是不一样的
import copy
list1=[1,2,3,4,[5,6,7]]
list2=copy.deepcopy(list1)
print('list1:',list1)
print('list2:',list2)
list1.append(5)
print('list1:',list1)
print('list2:',list2)
list1[4].append(8)
print('list1:',list1)
print('list2:',list2)
print('list1[4]:',id(list1[4]))
print('list2[4]:',id(list2[4]))
#输出 list1: [1, 2, 3, 4, [5, 6, 7]]
#输出 list2: [1, 2, 3, 4, [5, 6, 7]]
#输出 list1: [1, 2, 3, 4, [5, 6, 7], 5]
#输出 list2: [1, 2, 3, 4, [5, 6, 7]]
#输出 list1: [1, 2, 3, 4, [5, 6, 7, 8], 5]
#输出 list2: [1, 2, 3, 4, [5, 6, 7]]
#输出 list1[4]: 1585437960072
#输出 list2[4]: 1585437961480
可变对象
# 定义:变量对应的值可以改变,但是内存地址是不变的
# 常见可变类型 list、dict、set,拿字典、集合举例
dic={'name':'jwq','age':18}
print(id(dic['name']))
dic['name']='zhn'
print(id(dic['name']))
set={1,2,3,4}
print(set,id(set))
set.remove(1)
print(set,id(set))
#输出 2547392693280
#输出 2547392693560
#输出 {1, 2, 3, 4} 2864694744904
#输出 {2, 3, 4} 2864694744904
不可变对象
# 定义:变量对应的值不能被修改,如果修改就会生成一个新的值从而分配新的内存空间
n=10
print(n,id(n))
n=20
print(n,id(n))
#输出 10 1855956352
#输出 20 1855956672
函数
# 函数具有可复用性,必须在函数写完后调用
def login():
print('这是登录')
login()
#输出 这是登录
# 形参,实参 函数里面的a,b是形参,方法调用的则为实参 函数遇到return已经结束了,要是返回多个值则是以元组的形式
def buy1(a,b):
return a+b
def buy2(a,b):
return (a+b),a
print(buy1(1,2))
print(buy2(1,2))
#输出 3
#输出 (3, 1)
#默认参数 就是起始有一个默认值,可以不传实参
def buy(a=2):
return a
print(buy())
#输出 2
#默认参数要放在后面
def buy(b,a=2):
return b+a
print(buy(2))
#输出 4
#可变参数 这个参数不传则返回(),也可以传多个,他的返回形式为元组,最好形参写args,写别的也没事,就是规范点
def func(*args):
print(args)
func(1)
func('jwq','zhn')
#输出 (1,)
#输出 ('jwq', 'zhn')
# 关键字参数 这个参数不传则返回字典,也可以传多个,他的返回形式为字典dict
def func(**kwargs):
print(kwargs)
func()
func(name='jwq',age=18,phone='12345678901')
#输出 {}
#输出 {'name': 'jwq', 'age': 18, 'phone': '12345678901'}
# 函数调用 就是一个函数在另一个函数调用
def setName(name):
print(name)
def user(**kwargs):
setName('jwq')
print(kwargs)
user(age=18)
#输出 jwq
#输出 {'age': 18}
# 函数嵌套 定义:在一个函数中定义另一个函数
def setName(name): #外函数
print(name)
def user(**kwargs): #内函数
print(kwargs)
user(age=18) #这里一定要和内函数def对齐调用
setName('jwq')
#输出 jwq
#输出 {'age': 18}
# 作用域 在外部定义的是全局变量,在内部定义的是局部变量,局部变量只能在函数体内部使用
age=18
def fun():
print(age)
def func():
age=20
print(age)
fun()
func()
#输出 18
#输出 20
# global 修改全局变量 也可以在局部声明一个全局变量
age=18
def fun():
print(age)
def func():
global age #将局部变量声明为全局变量
age=20
print(age)
fun()
func()
print('修改后的全局变量',age)
#输出 18
#输出 20
#输出 修改后的全局变量 20
# nonlocal 用来声明外层的局部变量,只能在嵌套函数中使用,在外部函数先声明内部函数进行nonlocal声明,可以看到值都变为20了
age=18 #全局变量
def outer():#外函数
age=12 #局部变量
def inner(): #内函数
nonlocal age #nonlocal只能对上一级函数的局部变量进行修改
age = 20
print('inner: ', age)
inner()
print('outer: ', age)
outer()
#输出 inner: 20
#输出 outer: 20
# lambda 匿名函数 带形参 简单的可以采用lambda表达式
add=lambda a,b:a+b
print(add(1,3))
#输出 4
# 没有形参
setName=lambda : 'jwq'
print(setName())
#输出 jwq
# 形参默认值 后面返回要用元祖形式tuple
setName=lambda name,age=18:(name,age)
print(setName('jwq'))
#输出 ('jwq', 18)
# lambda 结合if,相当于把返回值当做函数体去写判断条件
comp=lambda a,b : 'a<b' if a<b else 'a>b'
print(comp(1,2))
#内置函数 大写字母开头是内置常量名,小写字母开头是内置函数名
import builtins
print(dir(builtins))
#输出 ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError',...'vars', 'zip']
# abs 绝对值
import builtins
print(abs(-10.1))
#输出 10.1
# sum 求和 里面的对象必须是可迭代对象,比如元组、集合、数组等字符串除外
print(sum([1,2,3]))
print(sum((1,2,3)))
print(sum({1, 2, 3}))
#输出 6
#输出 6
#输出 6
# min最小值 max最大值
print(min([1,2,3]))
print(max([1,2,3]))
print(min([-1,2,3,-5],key=abs)) #这个地方key=abs加入后就是比绝对值
#输出 1
#输出 3
#输出 -1
# zip 打包为元组,对象也是可迭代对象,举例数组 如果元素不一致,按照最短的长度返回
list1=[1,2,3]
list2=[4,5,6]
print(zip(list1,list2))
for item in zip(list1,list2):
print(item)
print(list(zip(list1,list2))) #强转为对象返回
#输出 <zip object at 0x0000017F05995408>
#输出 (1, 4)
#输出 (2, 5)
#输出 (3, 6)
#输出 [(1, 4), (2, 5), (3, 6)]
# map 映射函数 参数为定义一个函数,要进行映射的可迭代对象 可迭代对象每一个都会去执行这个函数
list=[1,2,3]
def fun(a):
return a*5
mp=map(fun,list)
print(mp)
for item in mp:
print(item)
#输出 <map object at 0x000002271593C5C0>
#输出 5
#输出 10
#输出 15
# reduce 先把函数中的两个对象取出来进行计算,接下里在把这个值和下一个值进行计算,可以理解为累加,累乘 它有两个参数,第一个为函数,这个函数必须有两个参数,第二个为可迭代对象
from functools import reduce
list1=[1,2,3,4,5]
def sum(x,y):
return x+y
re=reduce(sum,list1)
print(re)
#输出 15
# 拆包 这里数组举例,当然可迭代对象都可以
list1=[1,2,3,4]
a,b,c,d=list1 #这里接受的个数要和数组中的个数一致
print('a:',a,'b:',b,'c:',c,'d:',d)
#输出 a: 1 b: 2 c: 3 d: 4
#函数里面可以这样使用
def fun(a,b,*args):
print(a,b)
print(args)
tup=(1,2,3,4,5)
fun(*tup)
#输出 1 2
#输出 (3, 4, 5)
异常
# 可以看到hello jwq就没输出了,因为走到哪里就报错了,程序不执行了
def fun():
raise Exception('报错了,走不下去了')
print('hello jwq')
fun()
#输出 raise Exception('报错了,走不下去了')
#输出 Exception: 报错了,走不下去了
#抛出自定义异常
def fun():
pw=input('请输入你的密码:')
if len(pw)>=6:
return '密码大于6位,输入成功'
else :
raise Exception('报错了,走不下去了')
try: #捕获异常是为了让程序继续往下运行,就是程序不会终止
print(fun())
except Exception as e: #把异常信息保存到变量里面
print(e)
#输入 请输入你的密码:123
#输出 报错了,走不下去了
模块
# 含义:一个py文件就是一个模块
# 模块分三种,第一种内置模块 如random、time、os、logging直接导入使用就可以了,第二种第三方模块(第三方库),下载方法就是 cmd中输入pip install 模块名,第三种自定义模块,就是自己项目中的定义的模块,命名遵循标识符规定以及变量的命名规范,并且不要和内置模块产生冲突
# 导入模块
# pytest.py
print('这是jwq的模块')
name='jwq'
def fun():
print('这是jwq的模块方法')
#test.py
import pytest
print(pytest.name)
#输出 这是jwq的模块
#输出 jwq
# 按需导入 导入模块只取自己需要的方法 不建议过多使用,因为同名变量或方法会产生冲突
#test.py
from pytest import fun,name
fun()
#输出 这是jwq的模块
#输出 这是jwq的模块方法
#输出 jwq
# 直接导入所有,用*
#test.py
from pytest import *
fun()
print(name)
#输出 这是jwq的模块
#输出 这是jwq的模块方法
#输出 jwq
# as 模块取别名
#test.py
import pytest as pt
pt.fun()
#输出 这是jwq的模块
#输出 这是jwq的模块方法
# 功能取别名
#test.py
from pytest import fun as f
f()
#输出 这是jwq的模块
#输出 这是jwq的模块方法
# 内置全局变量 __name__
#test.py
import pytest
pytest.fun()
#输出 这是jwq的模块
#输出 这是jwq的模块方法
# pytest.py 可以看到,单独运行的时候可以显示,而在test.py中导入时,不显示
print('这是jwq的模块')
name='jwq'
def fun():
print('这是jwq的模块方法')
if __name__ == '__main__' :
print('不会显示')
#输出 这是jwq的模块
#输出 不会显示
包
# 含义:就是项目结构中的文件夹/目录
# 跟普通文件夹的区别在于,这个包文件夹有__init__.py
# 作用:有效避免模块名称冲突问题,让结构更清晰
# 导包方式 from 包名 import py文件
from pack_01 import regist
print(regist.registFn())
# __all__ 这是一个列表,列表的元素表示要导入的模块
# pack_01中有两个py文件,分别为regist.py(中有一个registFn方法),login.py(中有一个loginFn方法)
# __init__.py
__all__=['regist','login']
# test.py 这样直接就可以导入这个pack_01包里面所有被注册的模块
from pack_01 import *
print(regist.registFn())
print(login.loginFn())
# 包的本质还是一个模块,包也可以包含包
# pack_01 __init__.py
from pack_01.pack_01_01 import *
__all__=['regist','login','user']
# pack_01_01(里面有一个user.py(中有一个userFn方法)) __init__.py
__all__=['user']
# test.py
from pack_01 import *
print(regist.registFn())
print(login.loginFn())
print(user.userFn())
递归函数
# 含义:一个函数在自己内部调自己本身的函数,那么这个函数就是递归函数
# 优点:简洁、逻辑清晰 缺点:耗内存、运行效率低
# 这里是一个累加函数
def add(n):
if n==1: #结束条件,没有的话就会一直调,会报错
return 1
return n+add(n-1)
print(add(2))
#输出 3
# 1 1 2 3 5 8 ... 裴波那契数列 第几个数是多少
def add(n):
if n<=1:
return n
return add(n-2)+add(n-1)
print(add(3))
#输出 2
闭包
# 条件:1、嵌套函数 2、内层函数调用外层函数变量 3、外层函数的返回值是内层函数的函数名
# outer 无形参
def outer():
n=18
def inner():
print(n)
return inner
print(outer())
outer()()
#输出 <function outer.<locals>.inner at 0x0000013F7BD35AE8>
#输出 18
# outer 加入形参
def outer(m):
n=18
def inner(o):
print(m+n+o)
return inner
print(outer(10))
outer(10)(10)
#输出 <function outer.<locals>.inner at 0x00000208F7AB5AE8>
#输出 38
#装饰器 好处是在不改变原有的功能下,添加新的功能
def setName():
print('jwq')
def fun(fn):
print('我的名字:')
fn()
fun(setName)
#输出 我的名字:
#输出 jwq
# 装饰器语法糖
def outer(fn):
def inner():
print('登录....')
fn()
return inner
@outer #在被装饰的函数前面加@函数名
def setName():
print('jwq')
setName()
#输出 登录....
#输出 jwq
# 内函数有形参
def outer(fn):
def inner(name):
print(name,'登录....')
fn(name)
return inner
@outer
def setName(name):
print('被装饰的函数')
setName('jwq')
#输出 jwq 登录....
#输出 被装饰的函数
#多个装饰器 最靠近被装饰函数的装饰器先被装饰,然后使用远的装饰器
def outer(fn):
def inner(name):
return name,'登录....'
fn(name)
return inner
def outer1(fn):
def inner(name):
return name,'登录2....'
fn(name)
return inner
@outer1
@outer
def setName(name):
print('被装饰的函数')
print(setName('jwq'))
#输出 ('jwq', '登录2....')
面向对象
# 创建对象并实例化
class People:
name='jwq'
age=18
def run(self,step): #这里一定要先加self
print(f'跑步跑了{step}步')
pp=People()
pp.name='zhn' #实例对象访问类对象
print(pp.name)
pp.run(100)
#输出 zhn
#输出 跑步跑了100步
# 类内部方法访问类对象
class People:
name='jwq'
age=18
def run(self,step):
print(f'{self.name}今年{self.age}跑步跑了{step}步')
pp=People()
pp.name='zhn'
print(pp.name)
pp.run(100)
#输出 zhn
#输出 zhn今年18跑步跑了100步
# __init__ 构造函数
class People:
def __init__(self,name,age):
self.name=name
self.age=age
def run(self,step):
print(f'{self.name}今年{self.age}跑步跑了{step}步')
pp=People('jwq',18)
pp.name='zhn'
print(pp.name)
pp.run(100)
#输出 zhn
#输出 zhn今年18跑步跑了100步
# __del__ 析构函数 就是全部执行完,在销毁
class People:
def __init__(self,name,age):
self.name=name
self.age=age
def __del__(self):
print('我被销毁了')
def run(self,step):
print(f'{self.name}今年{self.age}跑步跑了{step}步')
pp=People('jwq',18)
pp.run(100)
# del pp 删除这个实例对象
#输出 jwq今年18跑步跑了100步
#输出 我被销毁了
# 封装
class People:
name='jwq'
__age=12 #只能在内部被访问
def run(self):
self.__age=18 #在内部修改
print(f'{self.name}今年{self.__age}岁了')
pp=People()
print(pp.name)
# print(pp.__age) 这样就会报错,它属于私有对象,但是你可以这样print(pp._People__age)就不会报错,就改了个名字,但是不建议这么干
pp.run()
#输出 jwq
#输出 jwq今年18
# 继承
class People:
name='jwq'
__age=12
def run(self):
self.__age=18
print(f'{self.name}今年{self.__age}岁了')
class Boy(People):
pass #占位符,代码类里面不写任何东西,会自动跳过,不会报错
boy=Boy()
boy.run()
#输出 jwq今年18岁了
# 多重继承
class Father:
def sleep(self):
print('睡觉')
def run(self):
print('跑步')
class Son(Father):
pass
class GrandSon(Son):
pass
gs=GrandSon()
gs.run()
#输出 跑步
# 方法重写
class Father:
def sleep(self):
print('睡觉')
def run(self):
print('跑步')
class Son(Father):
pass #这个类不是派生类
class GrandSon(Son):#这个类是派生类 派生类就是不同于父类,有自己的属性方法
name='grandSon'
def run(self):
# Son.run(self)
super().run() # 推荐使用这种
print('跑100步')
gs=GrandSon()
gs.run()
#输出 跑步
#输出 跑100步
# 多继承 可以继承多个父类,避免多个父类存在同名方法,他会采取就近原则,从左往右去找寻方法
class Father:
def sleep(self):
print('睡觉')
def run(self):
print('跑步')
class Son(Father):
pass
class Mather:
def sing(self):
print('唱歌')
pass
class GrandSon(Son,Mather):
def run(self):
# Son.run(self)
super().run()
print('跑100步')
gs=GrandSon()
gs.sing()
gs.run()
print(GrandSon.__mro__) #他会采取__mro__从左往右去找寻方法
#输出 唱歌
#输出 跑步
#输出 跑100步
#输出 (<class '__main__.GrandSon'>, <class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Mather'>, <class 'object'>)
# 多态 定义一个统一的接口,一个接口多种实现,也就是写一个方法,接收共有的重写的方法
class Father:
def run(self):
print('跑步')
class Son(Father):
def run(self):
print('跑20步')
class GrandSon(Father):
def run(self):
print('跑100步')
def fun(obj):
obj.run()
son=Son()
gs=GrandSon()
fun(son)
fun(gs)
#输出 跑20步
#输出 跑100步
# @staticmethod 静态方法 既可以使用对象访问,也可以使用类访问 取消不必要的参数传递,有利于减少不必要的内存占用和性能消耗
class Person:
@staticmethod
def run():
print('在跑步')
Person.run()
pp=Person()
pp.run()
#输出 在跑步
#输出 在跑步
# classmethod 类方法,第一个参数必须为cls,类对象,
class Person(object):
@classmethod
def run(cls):
print('cls:',cls)
Person.run()
#输出 cls: <class '__main__.Person'>
# __new__ py程序一般先执行 __new__,在执行__init__,在重构__new__的时候,一定要继承super()
# __init__ 在温习一下,他是构造器
class Person(object):
def __init__(self):
print('这是__init__')
def __new__(cls, *args, **kwargs):
res=super().__new__(cls)
print('cls',cls)
return res
pp=Person()
print(pp)
#输出 cls <class '__main__.Person'>
#输出 这是__init__
#输出 <__main__.Person object at 0x00000226175CC5F8>
单例模式
# 可以理解为一个特殊的类,这个类只存在一个对象
# 好处在于可以节省内存空间,减少不必要的资源浪费
# 坏处在于多线程访问时容易引发线程安全问题
# 应用场景 回收站、音乐播放器、开发游戏软件(场景管理器)、数据库配置、数据库连接池的设计
# 通过判断obj==None的方式,可以看到分配的内存地址是相同的
class Person(object):
obj=None
def __init__(self):
print('这是__init__')
def __new__(cls, *args, **kwargs):
if cls.obj==None:
cls.obj = super().__new__(cls)
return cls.obj
pp1=Person()
print(pp1)
pp2=Person()
print(pp2)
#输出 这是__init__
#输出 <__main__.Person object at 0x00000293EE20C6A0>
#输出 这是__init__
#输出 <__main__.Person object at 0x00000293EE20C6A0>
# 通过导入的方式
# pytest.py
class Test(object):
def test(self):
print('这是测试')
te = Test()
# test.py
from pytest import te as te1
from pytest import te as te2
print(te1,id(te1))
print(te2,id(te2))
#输出 <pytest.Test object at 0x0000023C30BECEB8> 2457539104440
#输出 <pytest.Test object at 0x0000023C30BECEB8> 2457539104440
魔法方法&魔法属性
# 前面说的__init__ 、 __new__、
__del__ 等都是魔法方法
# __doc__ 魔法属性 类和函数的描述信息
class Person(object):
"""这是魔法属性""" #一定要用双引号,多行注释的写法
pass
print(Person.__doc__)
#输出 这是魔法属性
# __module__ 魔法属性 表示当前操作对象所在的模块
import pytest
te=pytest.Test()
print(te)
print(te.__module__)
#输出 <pytest.Test object at 0x000002E360A5C470>
#输出 pytest
# __class__ 魔法属性 表示当前操作对象所在的类
import pytest
te=pytest.Test()
print(te)
print(te.__class__)
#输出 <pytest.Test object at 0x000002233E59C470>
#输出 <class 'pytest.Test'>
# __str__() 魔法方法 返回一个字符串
class Test(object):
def __str__(self):
return '这是字符串' #这里必须要有返回值,且只能是字符串
te = Test()
print(te.__str__())
#输出 这是字符串
# __del__ 魔法方法 析构函数 就是全部执行完,在销毁 这个在前面有写
class People:
def __init__(self,name,age):
self.name=name
self.age=age
def __del__(self):
print('我被销毁了')
def run(self,step):
print(f'{self.name}今年{self.age}跑步跑了{step}步')
pp=People('jwq',18)
pp.run(100)
# del pp 删除这个实例对象
#输出 jwq今年18跑步跑了100步
#输出 我被销毁了
# __call__ 魔法方法 让一个实例对象变成一个可以调用的对象,像函数一样去调用,可调用对象:函数/内置函数和类都是可调用对象,通俗点就是可以带()调用的
# callable 判断一个对象是否为可调用对象
class Test(object):
def __call__(self, *args, **kwargs):
print('这是__call__')
te = Test()
te()
print(callable(te))
#输出 这是__call__
#输出 True
文件基础操作
# 文件:存储在某种长期存储设备上的一段数据
# 创建一个test.txt文件 里面我就写了jwq
# 文件的方法
f=open(r'E:\ai-study\test.txt') #打开文件的方法open r是取消转义的意思
print(f.name) #文件的名称
print(f.mode) #文件的目前处在什么模式 r表示只读,w表示只能写,a只能写,r+、w+、a+表示可读可写,若文件不存在r、r+会全部报错,w、w+和a、a+会创建,r+、w、w+覆盖,a和a+则是不覆盖,追加写
print(f.closed) #文件是否关闭
print(f.read()) #查看文件内容
f.close() #关闭文件
print(f.closed)
#输出 E:\ai-study\test.txt
#输出 r
#输出 False
#输出 jwq
#输出 True
# read(n) n表示从文件中读取的数据长度,没有传或者传负数,默认读所有
# readline() 一行一行的读取
# readline()利用循环读取所有数据
f=open(r'E:\ai-study\test.txt')
while True:
text=f.readline()
print(text)
if not text:
break
f.close()
print(f.closed)
#输出 jwq
#输出 zhn
#输出 True
# readlines() 把每一行数据转换为数组
f=open(r'E:\ai-study\test.txt')
print(f.readlines())
f.close()
print(f.closed)
#你要是看着\n不舒服,那就用for循环去取出来就好了
#输出 ['jwq\n', 'zhn']
#输出 True
# write() 写内容,你就会看到文件test.txt里面加上了jjj
f=open(r'E:\ai-study\test.txt','a+')
f. write('jjj')
f.close()
print(f.closed)
#输出 True
# 文件指针:标记从哪个位置开始读数据
# 文件定位操作 tell()、seek()
# tell() 显示当前文件的指针位置
# seek() 移动文件指针到指定位置
f=open(r'E:\ai-study\test.txt','w+')
f.write('jwq')
print('当前指针位置:',f.tell())
f.seek(0,0)
print('移动后指针位置:',f.tell())
print(f.read())
f.close()
print(f.closed)
#输出 当前指针位置: 3
#输出 移动后指针位置: 0
#输出 jwq
#输出 True
# with open 使用这种方式,可以看到不需要f.close()就可以关闭
with open(r'E:\ai-study\test.txt','w+') as f:
f.write('jwq')
f.seek(0,0)
print(f.read())
print(f.closed)
#输出 jwq
#输出 True
# encoding='utf-8' 有些小伙伴输入中文会乱码,是因为默认采用的是GBK的方式
with open(r'E:\ai-study\test.txt','w+',encoding='utf-8') as f:
f.write('我是')
f.seek(0,0)
print(f.read())
print(f.closed)
#输出 我是
#输出 True
# 图片复制
imgPath=r'E:\ai-study\img'
with open(imgPath+'\icon.png','rb') as f:
img=f.read()
with open(imgPath+'\icon1.png','wb') as f:
f.write(img)
#输出 可以看到这个img文件夹内多了一个icon1.png
# os
# rename 修改文件名称
import os
os.rename('pytest.py','pytest1.py')
#输出 可以看到文件名称改掉了
# remove 删除文件
import os
os.remove('test1.txt')
#输出 可以看到文件被删除了
# mkdir 创建文件夹
import os
os.mkdir('jwq')
#输出 可以看到文件夹创建了
# rmdir 删除文件夹
import os
os.rmdir('jwq')
#输出 可以看到文件夹删除了
# getcwd 获取当前目录
import os
print(os.getcwd())
#输出 E:\ai-study
# 获取目录列表 要是想要获取上级目录列表就加('../')
import os
print(os.listdir())
#输出 ['.idea', 'img', 'pack_01', 'pytest.py', 'test.py', 'test.txt', '__pycache__']
可迭代对象
# 迭代对象在前面已经讲过,这里不做特殊说明,列表、字典、集合等
# Iterable 判断是否为一个迭代对象
from collections.abc import Iterable
print(isinstance('123',Iterable))
#输出 True
# iter 迭代器 一个一个的取出来,但是超出会报错StopIteration异常
list = [1,2,3,4]
li=iter(list) #本质上面跟__iter__()是一样的
print(next(li)) #本质上面跟调用用li.__next__()是一样的
print(next(li))
#输出 1
#输出 2
# 可迭代对象不一定是迭代器对象,但是迭代器对象一定是可迭代对象,拥有__iter__的是可迭代对象,但是迭代器对象需要__iter__和__next__
from collections.abc import Iterable,Iterator
name='jwq'
print(isinstance(name,Iterable))
print(isinstance(name,Iterator))
#输出 True
#输出 False
# 自定义迭代器类
class MyInter(object):
def __init__(self):
self.num = 1
def __iter__(self):
return self
def __next__(self):
if self.num == 3:
raise StopIteration('终止迭代,数据取完了')
self.num += 1
return self.num
me = MyInter()
for i in me:
print(i)
#输出 2
#输出 3
# 生成器 定义:一边循环一边计算的机制
li = [i*5 for i in range(2)] #列表推导式
print(li)
ge = (i*5 for i in range(2)) #生成器推导式
print(next(ge))
print(next(ge))
#输出 [0, 5]
#输出 0
#输出 5
# 生成器函数 yield
def MyFn(n):
list=[]
i=0
while i<n:
list.append(i)
yield i
i+=1
print('list',list)
print(MyFn(3))
for i in MyFn(3):
print(i)
#输出 <generator object MyFn at 0x000001D0E74BE200>
#输出 0
#输出 1
#输出 2
#输出 list [0, 1, 2]
# 可迭代对象的范围是大于迭代器范围的大于生成器的范围
线程
# 线程之间的资源是共享的
from threading import Thread
import time
list=[]
#写入方法
def writeData():
for i in range(4):
list.append(i)
time.sleep(1) #这一步是为了等待一秒
print('写入的数据是:',list)
#读取方法
def readData():
print('读取的数据是:',list)
if __name__=='__main__':
#创建子线程
t1=Thread(target=writeData)
t2=Thread(target=readData)
#开启子线程
t1.start()
#阻塞线程
t1.join() #这个本质就是等待t1执行完,再往下走
# time.sleep(5) 当然你要是知道时间,那么也可以选择加一个等待 不建议
t2.start()
t2.join()
#输出 写入的数据是: [0, 1, 2, 3]
#输出 读取的数据是: [0, 1, 2, 3]
# 线程同步 两种方式:线程等待(join)、互斥锁(保证同一时刻只能有一个线程去操作)
# 互斥锁 上锁:acquire()、解锁:release() 这两个方法必须成对出现,要不然会形成死锁,它属于多线程去抢占资源,抢到锁的线程先执行
from threading import Thread,Lock
import time
num=0
n=10000
lock=Lock()
def num1Fn():
lock.acquire()
for i in range(n):
global num
num+=1
print('num1:',num)
lock.release()
def num2Fn():
lock.acquire()
for i in range(n):
global num
num += 1
print('num2:', num)
lock.release()
if __name__=='__main__':
#创建子线程
t1=Thread(target=num1Fn)
t2=Thread(target=num2Fn)
#开启子线程
t1.start()
t2.start()
#输出 num1: 10000
#输出 num2: 20000
# 多线程
from threading import Thread
import time
def run():
print('跑步')
def eat():
print('吃饭')
time.sleep(2)
print('吃好饭了')
if __name__=='__main__':
# 创建线程
t1=Thread(target=run)
t2=Thread(target=eat)
# 守护线程 必须放在start前面,主线程结束是子线程也跟着结束
t1.setDaemon(True)
t2.setDaemon(True)
t1.start()
t2.start()
# 阻塞线程,只有等子线程执行完,才会继续执行主线程
# t1.join() 所以想要完整的输出,那么必须加上这个join
# t2.join()
print('结束了')
#输出 跑步
#输出 吃饭
#输出 结束了
进程
# 概念:操作系统进行资源分配和调度的基本单位,是操作系统结构的基础
# 一个正在运行的程序或者软件就是一个进程
# 进程里面可以创建多个线程,多进程也可以完成多任务
# 进程的状态
# 1、就绪状态:运行的条件已满足,正在等待cpu执行
# 2、执行状态:cpu正在执行
# 3、等待(阻塞)状态:等待某个程序执行完
# 进程语法结构
from multiprocessing import Process
import os
def run():
print(f'run当前进程:{os.getpid()},主进程:{os.getppid()}')
print('跑步')
def eat():
print(f'eat当前进程:{os.getpid()},主进程:{os.getppid()}')
print('吃')
if __name__=='__main__':
# 创建子进程
p1=Process(target=run)
p2=Process(target=eat)
# 开启
p1.start()
p2.start()
print('p1-name: ',p1.name)
print('p2-name: ',p2.name)
print('p1-id: ',p1.pid)
print('p2-id: ',p2.pid)
#输出 p1-name: Process-1
#输出 p2-name: Process-2
#输出 p1-id: 10704
#输出 p2-id: 19244
#输出 run当前进程:10704,主进程:8480
#输出 跑步
#输出 eat当前进程:19244,主进程:8480
#输出 吃
# is_alive 存活状态
from multiprocessing import Process
import os
def run():
print('跑步')
def eat():
print('吃')
if __name__=='__main__':
# 创建子进程
p1=Process(target=run)
p2=Process(target=eat)
# 开启
p1.start()
p1.join() #join()同样也是阻塞进程
p2.start()
p2.join()
print('p1存活状态',p1.is_alive())
print('p2存活状态',p2.is_alive())
#输出 跑步
#输出 吃
#输出 p1存活状态 False
#输出 p2存活状态 False
# 进程中全局变量不共享
# 进程间的通信
# Queue(队列)
from queue import Queue
# Queue(n) n代表最多接收n条消息,零或者负值代表没有上限,直到内存的尽头
q=Queue(2)
q.put('jwq')
q.put('zhn')
print('full:',q.full()) #判断是否满了
print('qsize:',q.qsize()) #现在消息队列的数量
print(q.get()) #取出队列消息
print(q.empty()) #判断队列中消息是否为空
print(q.get())
print(q.empty())
print('full:',q.full())
#输出 full True
#输出 qsize: 2
#输出 jwq
#输出 False
#输出 zhn
#输出 True
#输出 full False
协程
# 这个是python语言独有的 他切换占用的资源最小
# 单线程下的开发,又称微线程
# 安装greenlet 命令: pip install greenlet
# greenlet是一个由c语言实现的协程模块,通过设置switch()来实现任意函数的切换
# greenlet是手动切换的,当遇到IO操作(input/output),程序会阻塞,而不能进行自动切换
# greenlet 可以在不同方法中切换
from greenlet import greenlet
def run():
print('跑步')
def eat():
print('吃饭')
g1.switch()
if __name__=='__main__':
# 创建协程对象
g1=greenlet(run)
g2=greenlet(eat)
g2.switch()
#输出 吃饭
#输出 跑步
# gevent 可以想象成greenlet的升级版
# 安装gevent 命令: pip install gevent
# gevent遇到IO操作时,会自动进行切换,属于主动式切换
# 在提醒一下,文件名不要和三方模块和内置模块名重名
# 下面可以看到gevent.sleep是同时进行,而不是等待结束了,在进行,自动切换了
import gevent
import time
def run():
print('跑步')
gevent.sleep(2)
print('跑完步了')
def eat():
print('吃饭')
gevent.sleep(1)
print('吃过饭了')
if __name__=='__main__':
# 创建协程对象
ge1=gevent.spawn(run)
ge2=gevent.spawn(eat)
ge1.join()
ge2.join()
# joinall 等待所有协程都执行结束在退出
# gevent.joinall([
# gevent.spawn(run),
# gevent.spawn(eat)
# ])
#输出 跑步
#输出 吃饭
#输出 吃过饭了
#输出 跑完步了
# monkey补丁,拥有在模块运行是替换功能,把 time.sleep()替换成gevent.sleep()
import gevent
from gevent import monkey
import time
# 这个必须放在被打补丁者的前面
monkey.patch_all()
def run():
print('跑步')
time.sleep(2)
print('跑完步了')
def eat():
print('吃饭')
time.sleep(1)
print('吃过饭了')
if __name__=='__main__':
gevent.joinall([
gevent.spawn(run),
gevent.spawn(eat)
])
#输出 跑步
#输出 吃饭
#输出 吃过饭了
#输出 跑完步了
# 多线程适合IO密集型操作(文件操作、爬虫等),多进程适合CPU密集型操作(科学及计算、对视频进行高清解码、计算圆周率等)
# 进程、线程、协程都是可以完成多任务的,自己根据实际情况选择那种方式
正则基础
# 正则表达式 字符串处理工具
# match 开头匹配
import re
res=re.match('jwq','jwqjwqjwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 3), match='jwq'>
#输出 jwq
# . 匹配任意一个字符
import re
res=re.match('.w','jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 2), match='jw'>
#输出 jw
# 匹配[]中列举的字符
import re
res=re.match('[jw].','jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 2), match='jw'>
#输出 jw
# \d 匹配0-9的数字
import re
res=re.match('.\d\d\d','131415926')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 4), match='j131'>
#输出 j131
# \D匹配非数字
import re
res=re.match('.\D','jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 2), match='jw'>
#输出 jw
# \s 匹配空格和tab键 tab键代表\s\s,两个空格
import re
res=re.match('\s',' jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 1), match=' '>
# \S 匹配非空白
import re
res=re.match('\S','jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 1), match='j'>
#输出 j
# \w 匹配单词字符,即a-z,A-Z,_,汉字
import re
res=re.match('\w','jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 1), match='j'>
#输出 j
# \W 匹配非单词字符
import re
res=re.match('\W','|jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
# * 代表匹配前一个字符出现0次或者无限次
# + 代表匹配前一个字符出现1次或者无限次,即至少一次
# ? 代表匹配前一个字符出现0次或者1次
# {m} 代表匹配前一个字符出现m次
# {m,n} 代表匹配前一个字符出现m次到n次
# 下面仅做*和{m}参考
import re
res=re.match('\W*','|~jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 2), match='|~'>
#输出 |~
import re
res=re.match('\W{3}','||~jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 3), match='||~'>
#输出 ||~
# ^ 表示以什么开头,但是在[^jw]表示相反,不以jw开头的
import re
res=re.match('^jw','jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 2), match='jw'>
#输出 jw
# $ 表示结尾
import re
res=re.match('.*q$','jwq')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 3), match='jwq'>
#输出 jwq
# | 匹配分组 匹配左右任意一个表达式
import re
res=re.match('.|\d','1234')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 1), match='1'>
#输出 1
# (ab)将括号中的字符作为一个分组
import re
res=re.match('\w*@(qq|163|126).com','1234@qq.com')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 11), match='1234@qq.com'>
#输出 1234@qq.com
# \num 匹配分组num匹配到的字符串
import re
res=re.match(r'<(\w*)><(\w*)>.*</(\2)></(\1)>','<html><body>login</body></html>')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 31), match='<html><body>login</body>#输出 </html>'>
#输出 <html><body>login</body></html>
# ?P<name> 分组起别名 ?P=name 引用别名为name分组匹配到的字符串
import re
res=re.match(r'<(?P<L1>\w*)><(?P<L2>\w*)>.*</(?P=L2)></(?P=L1)>','<html><body>login</body></html>')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 31), match='<html><body>login</body></html>'>
#输出 <html><body>login</body></html>
# search 扫描整个字符串并返回第一个成功匹配的对象,如果匹配失败,则返回None
import re
res=re.search('z','jwqzhnzzz')
print(res)
# 上一步数据匹配成功,使用group提取数据
print(res.group())
#输出 <_sre.SRE_Match object; span=(3, 4), match='z'>
#输出 z
# findall 从头到尾去匹配,找到所有匹配成功的数据,并形成一个列表
import re
res=re.findall('z','jwqzhnzzz')
print(res)
#输出 ['z', 'z', 'z', 'z']
# sub 第一个参数正则表达式,第二参数替换的新内容,第三参数字符串,第四参数替换的次数
import re
res=re.sub('z','zhn','jwqzzz',1)
print(res)
#输出 jwqzhnzz
# split 第一个参数正则表达式,第二个参数字符串,第三个参数分割次数(若是没有设置参数,则全部分割)
import re
res=re.split('z','jwqzzz',1)
print(res)
['jwq', 'zz']
# 贪婪匹配(默认就是贪婪匹配)在满足匹配时,尽可能多的的匹配更长的字符串
import re
res=re.match('jwqz*','jwqzzz')
print(res)
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 6), match='jwqzzz'>
#输出 jwqzzz
# 非贪婪匹配 在满足匹配时,尽可能匹配更短的的字符串,使用?来表示
import re
res=re.match('jwqz+?','jwqzzz')
print(res)
print(res.group())
#输出 <_sre.SRE_Match object; span=(0, 3), match='jwq'>
#输出 jwqz
os模块
import os
# os.name Windows操作系统返回nt,Linux操作系统返回posix
print(os.name)
# 读取当前环境变量名
print(os.getenv('path'))
# split 把目录名和文件名分离,以元组的形式返回
print(os.path.split(r'E:\ai-study\test.py'))
#输出 ('E:\\ai-study', 'test.py')
# dirname 目录名
print(os.path.dirname(r'E:\ai-study\test.py'))
#输出 E:\ai-study
# basename 文件名
print(os.path.basename(r'E:\ai-study\test.py'))
#输出 test.py
# exists 判断路径是否存在
print(os.path.exists(r'E:\ai-study\test.py'))
#输出 True
# isfile 判断文件是否存在
print(os.path.isfile(r'E:\ai-study\test.py'))
#输出 True
# isdir 判断目录是否存在
print(os.path.isdir(r'E:\ai-study'))
#输出 True
# abspath 获取当前路径下的绝对路径
print(os.path.abspath(r'test.py'))
#输出 E:\ai-study\test.py
# isabs 判断是否为绝对路径
print(os.path.isabs(r'E:\ai-study\test.py'))
#输出 True
sys模块
# 负责程序跟Python解释器的交互
import sys
# getdefaultencoding 获取系统默认编码模式
print(sys.getdefaultencoding())
#输出 utf-8
# 获取环境变量路径,以数组形式返回,第一项为当前所在的工作目录
print(sys.path)
# 获取当前操作平台名称
print(sys.platform)
#输出 win32
# 获取当前Python解释器的版本信息
print(sys.version)
time模块
# 时间模块
# time.sleep 时间延迟操作
import time
print('jwq')
time.sleep(1)
print('zhn')
#输出 jwq
# 这里可以看到间隔1秒才输出zhn
#输出 zhn
# time() 返回当前时间戳,以秒计算,从1970年1月1日 00:00:00开始到现在的时间差
print(time.time())
#输出 1740820441.4141
# localtime 将一个时间戳转换为当前时区的struct_time
print(time.localtime())
# print(time.localtime().tm_year) 你要取出里面的值只需.就行,这里已年为例
#输出 time.struct_time(tm_year=2025, tm_mon=3, tm_mday=1, tm_hour=17, tm_min=17, tm_sec=30, tm_wday=5, tm_yday=60, tm_isdst=0)
# asctime 获取系统当前时间,把struct_time换成固定的字符串表达式
print(time.asctime())
#输出 Sat Mar 1 17:20:58 2025
# ctime 获取系统当前时间,把时间戳转换为固定的字符串表达式
print(time.ctime())
#输出 Sat Mar 1 17:21:18 2025
# strftime 将struct_time转换成时间字符串
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))
#输出 2025-03-01 17:22:20
# strptime 将时间字符串转换成了struct_time
print(time.strptime('2025-03-01','%Y-%m-%d'))
#输出 time.struct_time(tm_year=2025, tm_mon=3, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=60, tm_isdst=-1)
logging模块
# 用于记录日志信息
# basicConfig 第一个参数filename:文件名称,第二个参数filemode:文件模式,第三个参数level:级别 CRITICAL>ERROR>WARNING>INFO>DEBUG>NOTSET 默认WARNING,第四个参数format:信息展示格式化
import logging
logging.basicConfig(filename='log.log',filemode='w',level=logging.NOTSET,format='%(levelname)s:%(asctime)s\t%(message)s')
logging.debug('jwq')
logging.info('jwqinfo')
logging.warning('jwqwarning')
logging.error('jwqerror')
logging.critical('jwqcritical')
# 会出现一个log.log的日志文件,里面内容如下
# DEBUG:2025-03-02 15:51:38,223 jwq
# INFO:2025-03-02 15:51:38,223 jwqinfo
# WARNING:2025-03-02 15:51:38,223 jwqwarning
# ERROR:2025-03-02 15:51:38,223 jwqerror
# CRITICAL:2025-03-02 15:51:38,223 jwqcritical
random模块
# 作用:用于实现各种分布的伪随机数生成器,可以根据不同的实数分布来随机生成值
import random
# random() 产生大于0小于1的随机小数
print(random.random())
#输出 0.1846671454251234
# uniform(a,b) 产生大于a小于b的随机小数
print(random.uniform(1,3))
#输出 1.0359668200972125
# randint(a,b) 产生大于a小于b的随机整数,包含开头也包含结尾
print(random.randint(1,5))
#输出 4
# randrange(start,stop,[step]) 产生start到stop的随机整数,包含开头但不包含结尾
print(random.randrange(1,5,2))
#输出 3
NumPy模块
# 安装
pip install numpy
# NumPy是一个运行速度非常快的数学库,主要用于数组计算
# 查看版本
import numpy as np
print(np.__version__)
#输出 2.2.3
# zeros 创建一个长度为10的空向量
import numpy as np
print(np.zeros(10))
#输出 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
# 找到一个数组的内存大小
import numpy as np
data=np.zeros((10,10))
print(f'内存大小:{data.size*data.itemsize}bytes')
#输出 内存大小:800bytes
# 查看add函数的说明文档
import numpy as np
np.info(np.add)
# 创建一个长度为10,并且第五个向量为1的数组
import numpy as np
data=np.zeros(10)
data[4]=1
print(data)
#输出 [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
# 创建一个值域范围从10到20的向量
import numpy as np
data = np.arange(10,20)
print(data)
#输出 [10 11 12 13 14 15 16 17 18 19]
# 向量反转
import numpy as np
data = np.arange(10)
data=data[::-1]
print(data)
#输出 [9 8 7 6 5 4 3 2 1 0]
# 创建一个3*3并且值从0-8的矩阵
import numpy as np
data = np.arange(0,9).reshape(3,3)
print(data)
#输出 [[0 1 2]
#输出 [3 4 5]
#输出 [6 7 8]]
# 找到数组[1,2,0,0,4]中非0位置的索引
import numpy as np
data = np.nonzero([1,2,0,0,4])
print(data)
#输出 (array([0, 1, 4]),)
# 创建一个3*3的单位矩阵
import numpy as np
data = np.eye(3,3)
print(data)
#输出 [[1. 0. 0.]
#输出 [0. 1. 0.]
#输出 [0. 0. 1.]]
# 创建3*3*3的随机数组
import numpy as np
data = np.random.random((3,3,3))
print(data)
# 创建一个10*10的随机数组,并找到最大值和最小值
import numpy as np
data = np.random.random((10,10))
print(data)
print(data.min(),data.max())
# ndmin 指定生成数组的最小维度
import numpy as np
a = np.array([1,2,3],ndmin = 2)
print (a)
#输出 [[1 2 3]]
# dtype 参数 数组元素的数据类型
import numpy as np
a = np.array([1, 2, 3], dtype = str)
print (a)
#输出 ['1' '2' '3']
# 数据类型
# dtype
import numpy as np
# int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替
dt = np.dtype('i4')
print(dt)
# min max 最大和最小 生成一个 10x10 的随机二维数组
import numpy as np
data = np.random.random((10,10))
print(data)
print(data.min(),data.max())
matplotlib模块
# 下载matplotlib模块,下载前看看自己有没有下载numpy setuptools,
# 没有的话先下载pip install numpy setuptools
# pip install matplotlib
from matplotlib import pyplot as plt
# figsize中参数表示宽高,宽12,高8 dpi 每英寸上点的个数,dpi越大越清晰
fig=plt.figure(figsize=(12,8),dpi=80)
x=range(2,26,2)
y=[15,13,14.5,17,20,25,26,26,27,22,18,15]
# 绘图
plt.plot(x,y)
# 设置x的刻度
plt.xticks(x)
plt.yticks(range(min(y),max(y)+2))
# 保存图片
# plt.savefig('img/t.png')
# 展示图片
plt.show()
# 如果列表a表示10点到12点的每一分钟气温,温度在20,35之间,折线图表示
from matplotlib import pyplot as plt
import random
x=range(0,120)
y=[random.randint(20,35) for i in range(120)]
fig=plt.figure(figsize=(12,8),dpi=80)
plt.plot(x,y)
plt.show()