继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Python Day6

慕少森
关注TA
已关注
手记 99
粉丝 42
获赞 216

常用模块

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'))

结果:一个数据流可以和另外一个数据流交互,可以通过爬虫得到结果然后交给grep
python.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()
#这里调用就会出错,因为绑定到对象的方法有自动传值的特征,而上面类中相应函数没有定义位置参数,所以执行调用会报错

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP