第一部分 Python基础语法
步骤一:Python基础知识
Python概述
Python是完全面向对象的语言,属于解释性语言。
Python对大小写非常敏感
Python由两种注释方式:1、#符号进行单行注释。2、’’’ ‘’’ 进行多行注释
Python变量与字符串
函数就是python程序提前准备好的功能。每个函数都有对应的功能。函数的使用方式:函数名(参数)。
print函数是python中用于向控制台输出字符串的函数,例如:print(“锄禾日当午”)、print(3),可以用转移字符\n在括号内对文本换行。
编程语言中数据使用变量的形式进行保存,程序的作用就是用来处理数据
例如:name=“毛主席”(文本,string类型),salary=1938.3(数字,float类型) is_weekend=True(布尔值,bool类型)
变量名只能包含字母、下划线和数字(数字不能开头),必须要做到见名知意
用type函数得到变量的数据类型,语法:变量=type(变量名)
//是基本运算符代表除法取整(9//2=4),/是浮点数除法(10/2=5.0),是幂(N次方)(24=16)
input函数将用户输入的字符串保存到变量,语法:变量=input(“提示信息”)
字符串与数字之间的相互转换:字符串-》数字:int(字符串)、float(字符串)。数字-》字符串:str(数字)
字符串可以使用单引号,也可以使用双引号
字符串拼接使用+号处理:例如“您的航班”+“MF8777”+“次准备起飞”
字符串大小写转化函数:lower()转为小写,upper()转为大写,capitalize()字符串首字母大写,title()每个单词首字母大写,swapcase()大小写互相转化
函数format()是字符串提供了一种格式化函数,实例1:“{}{}you”.format(“I”,“love”)将产生I love you。实例2:“{2}.{1}.{0}".format(“com”,“imooc”,“www”)将产生www.imooc.com
format函数还支持数字格式化,例如format(1234.567,‘0.2f’)会保留两位小数,format(1234.567,’,’)会产生千分位分隔符
制表符是指增加字符的缩进,是\t
strip函数用于删除字符串中的空白,lstrip()删除左侧,rstrip删除右侧,strip删除两侧
find函数用于获取子字符串出现的位置,例如:“Nice to meet you”.find(“ee”)返回9,找不到则返回-1,语法为mystr.find(str,strat(开始位置),end(结束位置)),rfind从右边开始查找返回第一个字符的索引
index函数用法与find函数用法一样,不过如果找不到会报错,也有rindex函数
count函数返回str在start与end中出现的次数,语法为mystr.find(str,strat(开始位置),end(结束位置))
replace函数用于字符串中的替换,语法:str.replace(原始串,目标串,[替换次数]),例如“aaabbbccc”.replace(“b”,“d”,2)输出aaaddbccc
splitlines函数按照行进行分割,返回一个包含各个元素的列表
Python流程控制语句
Python流程控制语句分为两大部分:分支语句以及循环语句。
分支语句的基本书写形式
判断条件必须可以判断结果是True或是False,执行语句块必须进行缩进
多分支语句就是在原有基础上增加elif,进行多重判断
pow函数,pow(4,2)=16,计算的是4的2次方
分支语句嵌套是指在分支语句中再次使用if进行二次判断
使用tab的时候代表输入四个空格。
逻辑运算符
and(与),or(或),not(非),not>and>or
循环是满足条件下周而复始的运行的情况
循环通常有明确的执行次数,计数器便是保存循环次数的变量,比如设置一个i=0使得它在每次循环都+1。计数器常用字母i(index)来命名
continue与break:continue用于跳过当前循环的剩余语句,break关键字用来终止循环语句。continue语句相当于过滤
常用运算符的使用
运算符分类:算术运算符,比较运算符,逻辑运算符,赋值运算符,成员运算符,身份运算符和位运算符
算术运算符
比较运算符
逻辑运算符
赋值运算符
成员运算符与身份运算符
位运算符
运算符优先级
列表与字典(python中可变类型的数据集合)
数据结构分为四种(数据结构就是指从计算机存储、组织数据的结构):列表(List)、元组(Tuple)、字典(Dictionary)、集合(Set)
列表
1.列表中的数据按顺序排列
2.列表有正序和倒序两种索引
3.列表可以存储任意类型数据且允许重复
例如:
for…in…语句专门用于遍历列表、元组等数据结构
for 迭代变量 in 可迭代对象:
循环体(必须缩进)
列表的操作(增删改查)
应该是新列表=list[起始索引:结束索引]
多维数组(嵌套列表)
split函数,可以用split函数将字符串根据某个元素分割成一个列表。例如:str=“小一,小二,小三”,p1 = str.split(","),则p1为【小一,小二,小三】的列表
列表在表达结构化数据时语义不明确。结构化数据是指有明确属性,明确表示规则的数据
字典
字典是Python中的内置数据结构,字典非常适合表达结构化数据。
字典采用键(key):值(value)形式来表达数据,其中key不允许重复,value可以重复。
字典是可以修改的,运行时动态调整存储空间
创建字典
1.使用**{}**来创建字典,例如dict2={‘name’:‘汪峰’,‘sex’:‘男’,‘hiredate’:‘1999-01-07’}
2.使用dict函数创建字典,例如dict3=dict(name=‘汪峰’,sex=‘男’,hiredate=‘1999-01-07’)
PS:利用对应的序列创造对应的key,利用dict中的fromkeys方法,例如dict4=dict.fromkeys([‘name’,‘sex’,‘hiredate’,‘grade’],‘N/A’),其中N/A是给不同key附加的默认值。
字典的取值操作
setdefault函数为字典设置默认值,如果某个key已经存在则忽略,如果不存在则设置
获取字典的视图:
1.keys代表获取所有的键,例如ks=emp.keys(),ks返回一个“dict_keys([‘key1’,‘key2’])”
2.values代表获取所有的值,例如vs=emp.values(),ks返回一个“dict_keys([‘value1’,‘value2’])”
3.items代表获取所有的键值对,例如its=emp.items(),ks返回一个“dict_keys([(‘key1’,‘value1’),(‘key2’,‘value2’)])”
利用字典格式化字符串
字典也称为“哈希(Hash)”,对应“散列值”,散列值是从任何一种数据中创建数字“指纹”。是一次运行中对某一元素的唯一标识。
Python中提供了hash()函数生成散列值,例如h1=hash(“abc”),print(h1) ,h1则返回-810469…
对于整数来说散列值就是它们本身
在每一次运行过程中除了整数元素产生的散列值都不同
字典存储原理
元组与集合
元组
元组(Tuple)是“不可变”的列表(List)
元组使用小括号,列表使用方括号,例如tup=(‘physics’,‘chemistry’,1997,2000)
元组的读取方式与列表相同,但创建后元素不允许修改
元组允许使用“元组运算符”来创建新元组
序列
序列(Sequence)是指“有序”的队列
序列中的元素顺序按添加顺序排列
序列中的数据通过“索引”进行获取
序列包含的常用数据结构有:字符串(Str),列表(List),元组(Tuple),数字序列(Range)
数字序列
range用于表示数字序列,内容不可变
数字序列使用range()函数创建,例如r=range(0,100)产生0-99的数字序列,r=(0,100,2)则产生100以内的双数序列
序列类型的相互转换
list() 转换成列表
tuple() 转换成元组
join()、str() 转换成字符串
集合
集合(Set)是Python中的内置数据结构
集合可以被看作是“没有Value的字典”
集合的创建
1.使用{}符号创建集合
2.使用set()函数创建集合
集合的数学运算有交集、并集、差集
交集运算使用intersection()函数来进行交集运算
可以使用intersection_update更新原有集合
union函数进行并集运算
difference函数进行单项差集运算
symmetric_difference函数进行双向差集运算,即既包含A在B中不存在的部分也包含B在A中不存在的部分
上述函数都可以增加_update进行原有集合的更新
issubset函数
issuperset函数
isdisjoint函数判断是否存在重复元素
内置生成式
列表生成式、字典生成式、集合生成式
字典生成式
集合生成式
步骤二 Python函数与模块
简单函数举例
函数的特点
1.隐藏实现功能的细节
2.重用代码
3.提高可读性,便于调试
函数的定义
参数就是函数的输入数据,在程序运行过程中根据参数不同执行不同代码
形式参数代表调用函数时应该输入的参数,实参指实实在在传入函数的参数
有返回值的函数
参数是函数的输入数据,而返回值则是函数的输出结果
return不是必须的,但是return语句执行后,函数将中断执行
可以给参数设置默认值,只需要在形参后面加上“ = 具体值”即可
还可以用形参形式传参(关键字传参)
即在“形参名=实参”的形式调用函数
*代表之后的所有参数传参时必须使用关键字传参
序列传参
print(calc(l))
字典传参
在字典前加两个是为了将字典展开
python在参数名之前使用两个星号来支持任意多的关键字传参
多个返回值
用一个大字典来包含字典的序列
调用多个返回值单个数据的方法如下
以生活小助手为例介绍函数的使用技巧
主函数如下图所示
双色球函数如下图所示
随机数生成方式如下图所示·
import random
r=random.randint(1,16) #可生成1,16的随机数
号码百事通函数如下
phone_number="警察[110],消防[120],医护[119]"
def find_phone(keyword):
phone_list = phone_number.split(",") #将字符串按照,划分成序列
for p in phone_list:
if p.find(keyword) != -1: #查找序列中单个元素存不存在关键字,如果有则输出
print(p)
查询天气函数如下
weather_1="北京,2020年,多云,8°!重庆,2020年,晴天,20°"
def get_weather(city):
city_list = weather_1.split("!") #按照!划分成序列
weather_data = {}
for i in range(0, len(city_list)): #先将所有元素以字典形式存储,如{“南京”:{南京,8°....},....}
w = city_list[i].split(",") #再将序列中的元素以“,”再次划分成一个序列
weather = {"name": w[0], "data": w[1], "weather": w[2], "wendu": w[3]}#将单个元素生成字典
weather_data[weather["name"]] = weather #此处是第i个元素的name城市名称, #左边是key 右边value weather在weather_data中做name的value
if city in weather_data:
return weather_data.get(city)
else:
return {}
模块与包
包包含着模块
模块介绍
模块就是程序,模块的名称就是不含.py后缀的文件名
python模块的好处
1.可维护性更强
2.方便代码重用
模块的导入及定位
导入:import os
定位:当前包——>内置函数——>sys.path(环境变量)
内置函数跟环境变量可以理解为一个内容
使用自定义的模块需要添加入环境变量中(一次性)才能使用,例如
模块属性
dir——列出对象的所有属性及方法,import导入包之后就可以通过dir(对象)查看
help——查看类,方法的帮助信息
name——模块的名称,像这样以两个下划线开头和结尾的方法被成为模法方法,是python内置的方法
file——文件全路径
包的简介
1.可以用来组织模块(可以包含其他模块的模块)
2.目录必须包含文件__init__.py
3.模块重名问题解决
包的引用
四种引用方式
1.引入整个包: import module
2.只是引入所需要的属性和方法:form module.xx.xx import xx
3.指定别名:form module.xx.xx import xx as renename (用于防止名称冲突)
4.引入所有: from module.xxx import * (不建议)
用什么引用什么
如果想要直接调用包中的包,需要在包的__init__.py中from . import package_name(你想要调用的包的名称),其中 ‘ . '代表当前目录
因为想调用的包不在大包的同级目录下,环境变量上也没有
包包含着模块,可以把包也看做一个模块只不过它可以包含其他模块的模块
dir()和help()方法可以很容易帮助掌握陌生模块
import导入模块的执行过程
导入不同包中的同名模块
标准模块和第三方模块
标准模块——os模块
以下是os模块的部分方法
可以进入终端界面使用python对这些方法进行操作
操作实例如下
os模块之os.path
可以通过dir(os.path)查看目录
标准模块——datetime模块
图中的import也可以换成from datetime import datetime,当然now_time的定义要改变
import time
time.time()可以得到一个毫秒数,从python出现的时候开始计算并一直增长
time.sleep(2)休息两毫秒
自定义时间
时间,日期与字符串之间的相互转换
1.字符串转换成datetime对象
2.datetime对象转换成字符串
当然可以单独输出月份或者日期之类
3.datetime之间的加减操作
加法操作
减法操作
结果是28
当然小的减去大的会得到负数,结果是-28
python第三方模块
Django——一个自带电池的web开发框架
Flask——简单易用。快速上手的web开发框架
mysqlclient——使用python操作mysql数据的工具库
可以通过pypi.org来下载学习python的各种库
第一种安装方式通过pip install XX直接进行安装
第二种安装方式找到它的源码,在gethub种下载它的包,然后解压之后cd到它的包,它的包内有一个setup.py的程序,通过python setuo.py install进行安装
可以通过uninstall的方式进行卸载
如果安装不成功,可以找到它源码版本中的whl下载解压进行第二种方式安装
自定义包的实现
python虚拟环境之virtualenv
虚拟环境virtualenv——你可能手上同时在做三件事情但他们依赖的包不一样,我们可以通过pip install安装需要的所有包,但我希望能像三台电脑一样工作,一个电脑开发flask,一台开发django…但我们只有一台电脑,这时候我们就需要虚拟环境virtualev
pip install virtualenv安装virtualenv
上图案例通过virtualenv创建django1.1的虚拟环境
django1.1下的scripts目录
可以通过activate激活然后安装想要的虚拟环境
进入/退出虚拟环境 activate/deactivate.bat
进入和退出虚拟环境都要在Scripts中进行
pip install virtualenvwrapper-win(-win主要是标识是作用于windows系统)
需要在用户变量中添加上图环境变量,添加之后可以通过workon vname来实现虚拟环境自由切换
每个虚拟环境都是纯净的不包含其他虚拟环境
编译器中可通过上图方式添加虚拟环境,通过apply后使用
可以点击上图的Existing environment添加已经存在的虚拟环境
python虚拟环境之pipenv
假设当你手上有python2的项目在做但项目比较庞大迁移成本太高,而且手上还有python3.6的项目正在做,我们需要安装两个python环境,虚拟环境pipenv就是来解决这个问题的
pipenv也是依赖于virtualenv的但是它会把需要的python环境移过来
创建并进入python2.7的虚拟环境
运行print “hello python2”(python3已经不支持这种写法)
可以通过pipenv --help查找相关指令
python graoh可以查看依赖的库
实战——实现自己的工具包
以下自定义包是在虚拟环境中实现的
实现trans工具包
tools代码如下
import random
from datetime import datetime
def get_trans_id(date=None):
'''
根据所传入时间得到一个唯一的交易流水Id
:param date: 日期
:return: 交易流水ID字符
'''
#如果没有传入时间则使用当前系统时间
if date is None:
date = datetime.now()
#如何确认ID是唯一的
#日期+时间+毫秒+随机数(6位)
#'{0}{1}'.format(date.strftime('%y%m%d%H%M%S%f'),random.randint(100000,999999))
return date.strftime('%y%m%d%H%M%S%f')+str(random.randint(100000,999999))#strftime返回以可读字符串表示的当地时间。
#也可以使用{0}{1}.format()的方法传出数据
test_module代码如下
from datetime import datetime
from trans.tools import get_trans_id
def test_trans_tool():
'''测试trans包下的tools方法'''
id1=get_trans_id()
print(id1)
date=datetime(2015,10,2,12,30,45)
id2=get_trans_id(date)
print(id2)
if __name__=='__main__':
test_trans_tool()
实现work工具包
work中tools代码
import os.path
import constants
def get_file_type(file_name):
'''
根据文件名称来判断文件的类型
:param file_name: str文件名称
:return: int 文件类型
-1:未知文件类型
0:代表图片
1:word文档
2:excel
3:ppt文档
'''
#默认文件是未知类型的
result=constants.FILE_TYPE_UNK
# if not os.path.isfile(file_name):#传进来的必须是一个文件的名称,文件必须是存在的,假的会直接返回false
# return result
path_name,ext=os.path.splitext(file_name)#os.path.splitext(path)分割路径中的文件名与拓展名
#将后缀文件名统一成小写
ext=ext.lower()
if ext in('.png','.jpg','.bmp'):
result=constants.FILE_TYPE_IMG
elif ext in('.txt','.doc','.docx'):
result=constants.FILE_TYPE_DOC
elif ext in('.ppt','.pptx'):
result=constants.FILE_TYPE_PPT
elif ext in('.xls','xlsx'):
result=constants.FILE_TYPE_EXC
return result
测试代码
from datetime import datetime
from trans import tools as trans_tools
from work import tools as work_tools
#work是一个目录trans是一个包
# 如果直接import work的时候会出错,这时候我们需要加上_init_
# 如果直接导入包的话是不能使用包内的方法的,需要在_init_中加上类似于from . import tools的代码导入文件
def test_trans_tool():
'''测试trans包下的tools方法'''
id1=trans_tools.get_trans_id()
print(id1)
date=datetime(2015,10,2,12,30,45)
id2=trans_tools.get_trans_id(date)
print(id2)
def test_work_tool():
'''测试work模块'''
filename='c:\\users\\59917\\desktop\\test.txt'
rest=work_tools.get_file_type(filename)
print(rest)
if __name__=='__main__':
test_trans_tool()
test_work_tool()
constants中的数据
FILE_TYPE_IMG=10 #图片类型
FILE_TYPE_DOC=11 #DOC
FILE_TYPE_EXC=12 #EXCEL
FILE_TYPE_PPT=13 #PPT
FILE_TYPE_UNK=14 #未知文件
如上图所示,work是一个目录trans是一个包,因此直接在测试函数中import work的时候调用work中的tools会出错,这时候我们需要加上_init_.py,并且在_init_,py中加上类似于from . import tools的代码导入文件,这时候才能直接在测试函数中import work并使用tools的方法
from . import xxx ,是从同级导入xxx
.代表当前目录,…代表上一层目录,…代表上上层目录。
python中的常用高阶函数
lambda函数
lambda是一种简单的表达式,创建内嵌的简单匿名函数
示例lambda n,m:n+m,其中n,m:n+m是两个未知数以及对他们进行的操作
filter(过滤器)
返回一个列表,其中包含对其指向函数时结果为真的所有元素
filter(func,seq),其中func是过滤的条件,seq是需要过滤的列表(list/tuple)
def f(n):
#判断给定的数字是不是奇数
return n%2!=0
def use_filer(l):
'''
获取指定列表(元组)中的奇数
:param l:list/tuple要过滤的数据
:return:过滤好的奇数列表
列表是可以修改的数据结构,而元组是固定长度,不能被修改元素值的数据结构。
元组是使用圆括号()表示,而列表是使用方括号[]。请注意两者的区别。
'''
rest=filter(lambda n:n%2!=0,l)
#rest=filter(f,l)
return rest
if __name__=='__main__':
l=[1,2,3,4,5,6,7,8,9,10,11]
rest=use_filer(l)
print(list(rest))
map(对序列每个元素进行相同操作(生成一个列表))
*** 创建一个列表,其中包含对指定序列包含的项执行指定函数返回的值***
map(function,sequence,…)其中function是一个函数,sequence是一个序列
def pow_number(l):
'''
根据给定的列表数据计算每一项的立方
:param l: int类型的列表或者元组
:return: 原列表每一项立法
'''
rest_list=[]
for x in l:
rest_list.append(x*x*x)
return rest_list
def f(n):
return n*n*n
def pow_use_map(l):
#return map(f,l)
return map(lambda n:n*n*n,l)
if __name__=='__main__':
l=[1,2,3,4,5,6,7]
rest=pow_number(l)
print(rest)
re1=pow_use_map(l)
print(rest)
reduce(依次对序列每一个元素进行操作(生成一个数))
***使用指定的函数将序列的前两个元素合二为一,再将结果与第三个元素合二为一,以此类推,直到处理完整个序列并得到一个结果 ***
reduce(func,seq【,initial】)
等价于func(func(func(seq[0],seq[1]),seq[2]),…)
迭代反复调用
from functools import reduce
def get_sum(l):
'''
根据给定的列表,求里面各位数字的总和
:param l: 整数列表
:return: 列表所有和
'''
rest=0
for i in l:
rest+=i
return rest
def get_sum_use_py(l):
return sum(l)
def get_sum_use_reduce(l):
return reduce(lambda n,m:m+n,l)
if __name__=='__main__':
l=[1,2,3,4,5,6,7,8]
rest=get_sum(l)
print(rest)
r1=get_sum_use_py(l)
print(r1)
r2=get_sum_use_reduce(l)
print(r2)
filter类似于按条件进行查询的过程
map类似于给定一串数据,按照某个规则对这串数据进行处理并返回一串新的数据
reduce类似于给一串数据,对着串数据进行处理(累乘,累加…)并给出一个总的结果
文件读写模式
a是添加内容到以前的文件最后面
r是只读无法写
w是重新写,把之前的内容全部覆盖的.
文件的打开与关闭
使用open命令打开文件
一般我们使用open函数打开文件的时候会忘记close,这时候我们可以使用with语法进行文件的打开
with语法
with open(“somefile.txt”)as f:
do_something(f)
到达语句末尾时,将自动关闭文件,即便出现异常也是如此
文件的读取
read():读取文件,可以指定参数,表示读几个字符(字节)
读取的文件内容
关于香妃的传说众说纷纭,历史上真正的香妃是怎么样的呢?她是否真的遍体生香,能引来胡蝶?
而且历史上的香妃原型是谁,
为何备受的宠爱?历史上的香妃真的有电视剧里那么神奇吗?
2- 关于香妃的传说众说纷纭,历史上真正的香妃是怎么样的呢?她是否真的遍体生香,能引来胡蝶?
而且历史上的香妃原型是谁,
为何备受的宠爱?历史上的香妃真的有电视剧里那么神奇吗?
test_file_read函数测试read方法
def read_file():
'''读取文件'''
file_name='test.txt'
# file_path='D:\\python-project\\chapter04\\test.txt'
#考虑到可移植性,建议使用path2,也可以使用os.path.join的方式拼接3,在Linux和Mac里面没有磁盘的区别
file_path2='D:/python-project/chapter04/test.txt'
with open(file_path2,encoding="utf-8")as f:
# with open(file_name,encoding="utf-8") as f:
#f=open(file_name,encoding='utf-8')
#read从头读到尾 readline读取一行 readlines读取所有行并返回列表
#rest=f.read()
#读取指定内容
#T = True
# while T:
#读取指定内容
# rest=f.read(8)
# if not rest:
# break
# print(rest)
# print(f.read(8))
#跳过10个字符进行读取
# f.seek(10)
# print(f.read(5))
#读取一行,持续输出是接着上次读取的内容继续读取
# rest=f.readline(8)
# print(rest)
# print(f.readline(8))
#读取所有行
rest=f.readlines()
print(len(rest))
for i in rest:
print(i)
# T=False
#f.close()
if __name__=='__main__':
read_file()
os.path.join的使用
import os
print os.path.join('111','222','333') #111/222/333
print os.path.join('/111','222','333') #/111/222/333
print os.path.join('/111','/222','333') #/222/333
print os.path.join('/111','/222','/333') #/333
print os.path.join('111','222','/333') #/333
print os.path.join('111','/222','/333') #/333
print os.path.join('/111','/222','/333') #/333
print os.path.join('111/','222','333') #111/222/333
print os.path.join('111/','222/','333') #111/222/333
print os.path.join('111/','222/','333/') #111/222/333/
print os.path.join('111','222','333/') #111/222/333/
print os.path.join('111','222/','333/') #111/222/333/
print os.path.join('111/','222/','333/') #111/222/333/
print os.path.join('111','222','./333') #111/222/./333
文件的写入
使用write函数进行文件内容的写入
test_write_file的代码
import random
import datetime
#‘w'写入文件并覆盖之前文件 'a'追加写入
def write_file():
'''写入文件'''
file_name='write_test.txt'
#w是重新写,把之前的内容全部覆盖的.
f=open(file_name,'w')
f.write('hello')
#换行符 \n,\r,\r\n,通常都是\n
f.write('\n')
f.write('world')
f.close()
def write_mult_line():
file_name='write_mult.txt'
with open(file_name,'w',encoding='utf-8') as f:
l=['第一行','\n','第二行','\n','第三行']
f.writelines(l)
def write_user_log():
'''记录日志'''
rest='用户:{0}-访问时间:{1}'.format(random.randint(1000,9999),datetime.datetime.now())
print(rest)
file_name='write_user_log.txt'
with open(file_name,'a',encoding='utf-8') as f:
f.write(rest)
f.write('\n')
def read_and_write():
'''先读再写'''
file_name='read_and_write.txt'
with open(file_name,'r+',encoding='utf-8')as f:
read_rest=f.read()
if '1' in read_rest:
f.write('bbb')
else:
f.write('aaa')
f.write('\n')
if __name__=='__main__':
write_file()
write_mult_line()
write_user_log()
read_and_write()
以下是代码执行四次后的内容
read_and_write.txt
aaa
aaa
aaa
aaa
aaa
write_user_log.txt
用户:9018-访问时间:2021-03-28 15:32:42.281063
用户:5735-访问时间:2021-03-28 15:33:43.950296
用户:5348-访问时间:2021-03-28 15:34:40.497661
用户:3400-访问时间:2021-03-28 15:38:54.745128
write_test.txt
hello
world
write_mult.txt
第一行
第二行
第三行
实战:文件备份
import os
import os.path
class FileBackup(object):
'''文本文件备份'''
def __init__(self,src,dist):
'''
这里self就是指类本身,self.name就是类的属性变量,
是类所有。而src和dist是外部传来的参数,不是类所自带的。
构造方法
:param src: 目录,需要备份的目录
:param dist: 目录,备份后的目录
'''
self.src=src
self.dist=dist
def read_files(self):
'''读取指定(src)目录所有文件'''
ls=os.listdir(self.src)
print(ls)
for l in ls:
self.backup_file(l)
def backup_file(self,file_name):
'''
处理备份
:param file_name:文件/文件夹的名字
:return:
'''
#1.判断备份用的目录是否存在,如果不存在要创造这个目录
if not os.path.exists(self.dist):
os.makedirs(self.dist)
print("文件不存在,创建完成")
#拼接文件
full_src_path=os.path.join(self.src,file_name)
full_dist_path=os.path.join(self.dist,file_name)
#2.判断文件是否为我们需要备份的文件,可以借助文件后缀名判断
#首先要判断是否为文件夹,取后缀名返回的是一个元组
if os.path.isfile(full_src_path) and os.path.splitext(full_src_path)[-1].lower()=='.txt':
print(full_src_path)
with open(full_dist_path,'w',encoding='utf-8')as f_dist:
print('开始备份【{0}】'.format(file_name))
with open(full_src_path,'r',encoding='utf-8') as f_src:
while True:
rest=f_src.read(100)
if not rest:
break
#如果读不出数据则取消
f_dist.write(rest)
f_dist.flush()#flush相当于将残余数据全部加载入备份文件夹里,(冲马桶)
print('【{0}】备份完成'.format(file_name))
else:
print("文件类型不符合备份要求,跳过")
#3.读取文件内容
#4.写入
def backup_file2(self,file_name):
'''
处理备份--优化版
:param file_name:文件夹的名字
:return:
'''
#1.判断目录是否存在,如果不存在要创造这个目录
if not os.path.exists(self.dist):
os.makedirs(self.dist)
print("备份文件目录不存在,创建完成")
#拼接文件
full_src_path=os.path.join(self.src,file_name)
full_dist_path=os.path.join(self.dist,file_name)
#2.判断文件是否为我们需要备份的文件,可以借助文件后缀名判断
#首先要判断是否为文件夹
if os.path.isfile(full_src_path) and os.path.splitext(full_src_path)[-1].lower()=='.txt':
print(full_src_path)
#\表示这一行的语句没有结束
with open(full_dist_path,'w',encoding='utf-8')as f_dist, \
open(full_src_path, 'r', encoding='utf-8') as f_src:
print('开始备份【{0}】'.format(file_name))
while True:
rest=f_src.read(100)
if not rest:
break
f_dist.write(rest)
f_dist.flush()
else:
print("文件类型不符合备份要求,跳过")
#3.读取文件内容
#4.写入新的文件夹
if __name__=='__main__':
# src_path='D:\\python-project\\chapter04\\src'
# #要备份的文件↑地址
# dist_path='D:\\python-project\\chapter04\\dist'
#dirname功能:去掉文件名,返回目录
#abspath+__file__此方法代表得到当前文件的绝对路径:D:\\python-project\\chapter04\\test_backup.py
base_path=os.path.dirname(os.path.abspath(__file__))
src_path=os.path.join(base_path,'src')
dist_path=os.path.join(base_path,'dist')
bak=FileBackup(src_path,dist_path)#此为对象
bak.read_files()