常用模块
random
random() 方法返回随机生成的一个实数
import random
print(random.random()) #默认(0,1)----float 大于0且小于1之间的小数#结果:0.7386919875081359
print(random.randint(1,3)) #[1,3] 大于等于1且小于等于3之间的整数
print(random.randrange(1,3)) #[1,3) 大于等于1且小于3之间的整数
print(random.choice([1,'23',[4,5]])) #1或者23或者[4,5]
print(random.sample([1,'23',[4,5]],2)) #列表、元素任意2个组合
print(random.uniform(1,3))#大于1小于3的小数,如1.927109612082716
item=[1,3,5,7,9]random.shuffle(item) #打乱item的顺序,相当于"洗牌"print(item)[3, 1, 7, 5, 9]
生成随机验证码
def make_code(n): res='' for i in range(n): s1=chr(random.randint(65,90)) #65,90是ASCII中的大写 s2=str(random.randint(0,9)) s3=chr(random.randint(97,122)) #97,122是ASCII中的小写 res+=random.choice([s1,s2,s3]) return resprint(make_code(7))
os模块
import os
#获取文件目录
os.path.dirname(r'D:\pycharm_20期\day6\练习.py')
#获取文件名
os.path.basename(r'D:\pycharm_20期\day6\练习.py')
#拼接
os.path.join
#获取当前目录的父目录字符串名:('..')
os.pardir
#规范化路径,如..和/
os.path.normpath
#举例
a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..'print(os.path.normpath(a))/Users/jieli/test1
获取当前执行文件的最上层文件夹
#D:\pycharm_20期\day6\练习.py
BASE_DIR=os.path.normpath(os.path.join( os.path.abspath(__file__), os.path.pardir, os.path.pardir,))
#这种写法的通用性好
sys 模块
import sys
sys.argv
#获取一个List,第一个元素是程序本身绝对路径
#举例,可以这样用:
#当py文件按照脚本方式执行时,可以在py文件后面加上值,此时可以利用sys.argv获取这些值
python3 test.py sfile dfile #脚本方式执行,执行文件后面跟了两个参数#使用解压方法可以一次将两个参数分别赋予变量_,sfile,dfile=sys.argv即:sfile=sfile #第一个参数dfile=dfile #第二个参数
sys.exit(n) 退出程序,正常退出时exit(0)
print(sys.path) 初始化时使用PYTHONPATH环境变量的值
使用举例:
把当前目录加入到环境变量BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))sys.path.append(BASE_DIR)
知识点:进度条
先打印出进度条的样子
print('[%-50s]' %('#'*1)) #-代表左对齐,50代表宽度print('[%-50s]' %('#'*2))print('[%-50s]' %('#'*3))结果:[# ][## ][### ]
我们要把它变成一个连续的过程
知识点:
%% 两个百分号连到一起代表取消%的特殊意义,第一个百分号就是一个单纯的符号
print('[%%-%ds]' %50)结果:(是个字符串)[%-50s]print(('[%%-%ds]' %50) %('#'*10)) 等于'[%-50s]' %('#'*10)结果:[########## ]
实现进度条代码,这里使用time.sleep(0.1)模拟网络延迟
import timedef progress(percent,width=50): #percent是百分比,width是宽度 if percent >= 1: percent=1 show_srt=('[%%-%ds]' %width) %('#'* int(width*percent)) #宽度乘百分比利用int取整 print('\r%s %d%%' %(show_srt,int(100*percent)),end='') #\r代表光标移动到行首,end=''代表print不换行,%d%%是最后面的百分比recv_size=0 #已经接收的大小total_size=102312 #文件总大小while recv_size < total_size: time.sleep(0.1) recv_size+=1024 progress(recv_size/total_size)
这里有个问题,如果文件大小是10241的话,那意味着在循环10次后recv_size已经是10240了,但此时recv_size仍然小于total_size
这时就会再次进入循环,结果在10240即基础上又加上了1024,此时recv_size已经大于total_size,在做除法运算时结果会大于1
这就会导致最后一次计算出的#打印个数大于宽度,需要在上面的进度条显示逻辑做判断,大于1直接按1算
shutil模块
高级的 文件、文件夹、压缩包 处理模块
import shutil
#将文件内容拷贝到另一个文件中shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
shutil.copyfile(src, dst)
#拷贝文件shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在
shutil.copy(src, dst)
#拷贝文件和权限shutil.copy('f1.log', 'f2.log')
shutil.copytree(src, dst, symlinks=False, ignore=None)
#递归的去拷贝文件夹shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
#目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
shutil.rmtree(path[, ignore_errors[, onerror]])
#递归的去删除文件shutil.rmtree('folder1')
shutil.move(src, dst)
#递归的去移动文件,它类似mv命令,其实就是重命名。shutil.move('folder1', 'folder3')
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如 data_bak =>保存至当前路径
如:/tmp/data_bak =>保存至/tmp/
format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的
#将/data下的文件打包放置当前程序目录
import shutilret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
#将/data下的文件打包放置 /tmp/目录
import shutilret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
#解压
import tarfilet=tarfile.open('/tmp/egon.tar','r')t.extractall('/egon')t.close()
josn模块
josn 是一种通用的标准格式
import json
#序列化
#使用dumps进行序列化
a={'name':'dzm','age':18,'sex':'male'}with open('user.json','w',encoding='utf-8') as f: user=json.dumps(a) f.write(user)
#使用dump可以直接将序列化后的内容写入文件json.dump(a,open('user.json','w',encoding='utf-8'))
#反序列化
#使用loads进行反序列化
with open('user.json','r',encoding='utf-8') as f: user=json.loads(f.read()) #与json.dumps对应 print(user['name'])
#无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads
#使用load进行反序列化 load只能读文件
user=json.load(open('user.json','r',encoding='utf-8'))print(user['name'])
pickle 模块
#可以识别python所有的数据类型,但不能跨平台
#等号右边任何值都可以被pickle序列化,python中一切皆对象
#pickle序列化后的数据是bytes类型,因此写入读取文件时要以b模式打开
import pickle
#使用格式与josn相同
#序列化
a={'name':'dzm','age':18,'sex':'male'}res=pickle.dumps(a)print(res)
#直接写入文件pickle.dump(a,open('user.pkl','wb'))
#反序列化pickle.loads(res)
#从文件读
res=pickle.load(open('user.pkl','rb'))print(res)
shelve模块
#shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
import shelve
#写
f=shelve.open('db.shl')f['stu1']={'name':'dzm','age':18}f['stu2']={'name':'egon','age':28}f.close()
#读
f=shelve.open('db.shl')print(f['stu1']['name'])f.close()
xml模块
from xml.etree import ElementTree
tree=ElementTree.parse('a.xml') #得到根
#拿到一个元素Element
root=tree.getroot()
元素
#每一个元素都有三个需要掌握的点
root.tag #标签的名字root.attrib #标签的属性,就是名字后面的内容,如果有属性会把属性变成字典返回root.text #文本,一个标签内部,在子标签之外的独立文本才算
三种查找方式
#从当前节点下面的子节点中找元素Element
root.find() #只找第一个,有多个相同名称的标签也只找一个root.findall() #全部相同名称的找出来#从整个树形结构中查找root.iter()
#遍历文档数
for country in root: #找根下面的子节点(元素) for item in country: #再找子节点下面的子节点(元素) print(item.tag,item.attrib,item.text)
#修改内容
#把year找到并修改,添加树形,修改文本
for year in root.iter('year'): year.set('updated','yes') #往文件里写必须是字符串 year.text=str(int(year.text)+1) #在原有年份上加1,取出来的年份是字符串,没法做数学运算,转换+1后要再转换会字符串写入文件tree.write('a.xml')
#添加内容
#添加到名为rank的标签下面
for rank in root.iter('rank'): if int(rank.text) == 5: #取出来的rank.text是字符串,所以转换成int再比较 obj=ElementTree.Element('dzm') obj.attrib={'name':'dzm','age':'18'} #直接使用attrib添加要全部拼好 obj.text='dzm is good' rank.append(obj)tree.write('a.xml')
configparser模块
import configparserconfig=configparser.ConfigParser() #得到一个对象config.read('my.ini') #读取文件,这里使用mysql配置文件模拟
查找
print(config.sections()) #查看有哪些标签['mysqld', 'client', 'egon']
print(config.options('mysqld')) #查看标签下面的内容,返回的是k['charater-server-set', 'default-engine', 'skip-grant-table', 'port', 'data_dir']
print(config.get('mysqld','charater-server-set')) #查看标签下面配置项的值utf8
#注意,文件中有一行配置项的值是True,但通过get取出来的True只是一个字符串
print(type(config.get('mysqld','skip-grant-table')))<class 'str'>
#使用getboolean可以直接转换成布尔值print(config.getboolean('mysqld','skip-grant-table'))
#同理,使用getint可以直接获取int类型的值print(config.getint('mysqld','port'))
#使用getfloat可以直接拿到浮点型config.getfloat('mysqld','port')
#查看一个标签那面有没有这个配置项
print(config.has_option('mysqld','aaa'))False
添加内容
config.add_section('dzm')config.set('dzm','name','18') #标签、配置项、值config.write(open('my.ini','w',encoding='utf-8'))
修改内容
config.set('client','password','870911')config.write(open('my.ini','w',encoding='utf-8'))
hashlib模块
#hash:一种算法 ,3.x里代替了md5模块和sha模块
import hashlib
m=hashlib.md5()m.update('hello'.encode('utf-8')) #添加校验文本内容m.update('world'.encode('utf-8')) #两行内容会自动变为一行print(m.hexdigest()) #得出哈希值
#sha512 算法更复杂
m=hashlib.sha512()m.update('hello'.encode('utf-8'))print(m.hexdigest())
hmac模块
#用法与hashlib相同,但强制密码加严
import hmacm=hmac.new('密码加严'.encode('utf-8'))m.update('hello'.encode('utf-8'))print(m.hexdigest())
subprocess 模块
创建附加进程
import subprocess
import time
subprocess.Popen('tasklist',shell=True) #创建一个子进程执行,会直接执行下面的代码,不会管这条命令是否执行成功time.sleep(1) #上面的命令默认将结果打印到终端,但需要一定时间,如果这里不暂停1秒结束程序的话就看不到返回结果
obj=subprocess.Popen('tasklist',shell=True, stdout=subprocess.PIPE, #创建一个管道,把正确的结果传进这个管道 stderr=subprocess.PIPE, #再创建一个管道,把执行错误的结果传进 )
print(obj.stdout.read().decode('gbk')) #把stdout管道中的东西打出来print(obj.stderr.read().decode('gbk')) #把stderr管道中的内容打印出来
#注意,管道里是bytes类型,需要解码,在windows平台默认是按照gbk编码的,所以要以gbk解码
数据流交互
obj1=subprocess.Popen('tasklist',shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, )obj2=subprocess.Popen('findstr python',shell=True, stdin=obj1.stdout, #数据来源是上一个数据流 stdout=subprocess.PIPE, stderr=subprocess.PIPE, )print(obj2.stdout.read().decode('gbk'))
结果:一个数据流可以和另外一个数据流交互,可以通过爬虫得到结果然后交给greppython.exe 12336 Console 8 11,084 K
类的定义与使用
类的定义
对象是特征与技能的结合体,类就是一系列对象相似的特征与技能的结合体在现实世界中:一定是先有的一个个具体存在的对象,后总结出的类在程序中:一定保证先定义类,后产生对象
站在老男孩学校的角度
现实中的对象: 对象1: 特征 学校=老男孩 名字=李三炮 性别=男 年龄=18 技能 学习 选课 对象2: 特征 学校=老男孩 名字=张铁蛋 性别=女 年龄=38 技能 学习 选课 对象3: 特征 学校=老男孩 名字=武大郎 性别=男 年龄=28 技能 学习 选课 对象4: 特征 学校=老男孩 名字=egon 性别=男 年龄=18 技能 教学
现实中的老男孩学生类: 老男孩学生类 相似的特征 学校=老男孩 相似的技能 学习 选课
类的使用
类体代码在类的定义阶段就会立刻执行,
class Student: school='oldboy' def learn(self): print('is learning') def choose_course(self): print('choose course')
#查看
print(Student.school) #类的数据属性print(Student.learn) #类的函数属性
#增加
Student.name='dzm'print(Student.name)
#修改
Student.school='Oldboy'print(Student.school)
#删除
del Student.nameprint(Student.name)
print(Student.learn) #就是一个函数Student.learn('xxxxx') #加括号打印,但要遵循类的规则,必须有传参
对象的定义与使用
class Student: school='oldboy' def __init__(self,name,age,sex): #在调用类时会自动触发执行 self.Name=name self.Age=age self.Sex=sex def learn(self): print('is learning') def choose_course(self): print('choose course')
调用类的过程又称之为实例化,先定义类,在定义对象
1、得到一个返回值,即对象,该对象是一个空对象
2、Student.init(stu1,'dzm',18,'male)
对象定义过程中其本身会作为第一个值传给函数init,就是那个self
stu1=Student('dzm',18,'male')stu2=Student('egon',28,'male')stu3=Student('alex',38,'male')
print(stu1.__dict__) #看看stu1的名称空间里都有什么{'Name': 'dzm', 'Age': 18, 'Sex': 'male'}
#修改
stu1.Age=19print(stu1.Age)
#对象的增删改查方式与类的增删改查相同
对象的属性查找
class Student: school='oldboy' # Name='xxx' def __init__(self,name,sex,age): #在调用类时会自动触发执行 self.Name = name self.Sex = sex self.Age = age #stu1.Name='李三炮' #stu1.Sex='男' #stu1.Age=18 def learn(self,x,y): print('%s is learning' %self.Name) print(x,y) def choose_course(self): print('choose course') def commit_hw(): #类内定义的函数默认要有一个参数,约定俗成地写出self print('commit homework')
#1、查找一个对象的属性顺序是:先找对象自己的dict,再找类的dict
stu1=Student('dzm','男',18)print(stu1.school)oldboystu1=Student('李三炮','男',18)stu2=Student('张铁蛋','女',38)stu3=Student('武大郎','男',28)
#2、类的数据属性是所有对象共享,所有对象都指向同一个内存地址
Student.school='Oldgirl' #修改要从类入手print(Student.school,id(Student.school))print(stu1.school,id(stu1.school))print(stu2.school,id(stu2.school))print(stu3.school,id(stu3.school))
对象的绑定方法
#类是一系列对象相似的特征与技能的结合体
#抽象的理解上面掌握了特征,下面要掌握技能
#类中定义的函数是绑定给对象使用:
#1:不同对象就是不同绑定方法
#2:绑定给谁,就应该由谁来调用,谁来调用就会把谁当做第一个参数传给对应的函数
print(Student.learn) #返回结果就是个函数print(stu1.learn()) #绑定方法,会将对象自动传值给第一个位置参数
stu1.learn()stu2.learn()stu3.learn()调用结果:李三炮 is learning张铁蛋 is learning武大郎 is learning
stu1.learn(1,2) #Student.learn(stu1,1,2)
#可以多传几个参数
stu1.commit_hw()
#这里调用就会出错,因为绑定到对象的方法有自动传值的特征,而上面类中相应函数没有定义位置参数,所以执行调用会报错
共同学习,写下你的评论
评论加载中...
作者其他优质文章