首页 > Python基础教程 >
-
python基础总结(4)
__all__
使用,被引用的模块中编写__all__=['','',...]
列表中是可被导入的成员。但__all__
只对此种导入方法起作用,用于表示模块可以被外界使用的成员,元素是成员名组成的字符串,默认不写是可以导入全部成员。
系统导入模块的搜索路径,以import time
示例:先在内存中查看是否有以该模块名命名的命称空间,如果之前成功导入过某个模块,会直接使用已经存在的模块。若没有则再内置模块路径中(在python安装路径中lib和site-packages文件夹下)寻找。若仍没有,就会在sys.path
中寻找。
sys.path:查看sys.path内容,用cmd运行:import sys print(sys.path)
打印出的列表第一个元素是当前执行脚本的路径。列表动态可修改因此可将自定义模块文件夹所在的绝对路径添加到sys.path中以便导入:
import sys
sys.path.append('模块文件夹路径')
在不同的目录下相对导入自定义模块:
相对导入:针对某个项目中的不同模块之间进行导入,称为相对导入(模块间必须有一个同一个文件夹)。相对导入只有一个语法:from 相对路径 import xxx
相对路径:包含了点号的一个相对路径。
.:表示当前的路径。
..:表示的是父路径
...:表示的是父路径的父路径
..x.y:表示的是父路径下x文件夹下的y文件(夹)
举例:在python文件夹下有t1和t2两个文件夹,t1和t2文件夹下分别有pt1.py和pt2.py两个模块。python文件夹在WorkSpace文件夹下,WorkSpace下有一个main.py文件。
#相对导入(在pt1.py文件中编写):
#1.将pt1作为对外界的接入口:
from ..t2 import pt2 #..:从当前的路径(不包含当前文件,即/WorkSpace/python/t1)的父目录(/WorkSpace/python/)下找t2,在从t2中找pt2。
#测试相对导入(在main.py文件中编写):
import os,sys
sys.path.append(os.path.dirname(__file__)) #把项目所在的父路径加到sys.path中。
from python.t1 import pt1
#使用pt1.py模块文件导入的pt2.py模块中的成员:
pt1.pt2.成员名 #但不推荐这样写。容易向外界暴露pt2模块。
#更改方法(真正的相对导入):
#相对导入(在pt1.py文件中编写):
#1.将pt1作为对外界的接入口:
from ..t2.pt2 import * #直接导入pt2模块
#测试相对导入(在main.py文件中编写):
import os,sys
sys.path.append(os.path.dirname(__file__)) #把项目所在的父路径加到sys.path中。
from python.t1 import pt1
#使用pt1.py模块文件导入的pt2.py模块中的成员:
pt1.成员名 #成员名:可以是pt1和pt2模块的成员。
#不用相对导入(不推荐):
#1.在pt1模块下编写:
import os,sys
sys.path.append(as.path.dirname(os.path.dirname(__file__))+'/t2')
from pt2 import *
常用模块
使用导入的模块是否要在其后加():如果是一个类(class)或者是一个函数(function)就要加(),如果是一个属性就不要加括号。
random模块
pseudo-random,伪随机数;提供了随机数获取的方法
- random.random():获取[0.0,1.0)范围内的浮点数。
- random.randint(a,b):获取[a,b]范围内的一个整数。
- random.uniform(a,b):获取[a,b]范围内的一个浮点数数。
- random.shuffle(x):把参数指定的数据中的元素打乱,参数必须是一个可变的数据类型。没有返回值(因为是直接将x打乱,调用改函数后x会被改变,与append无返回值原因相同。)(不支持元祖,可用sample打乱)
- random.sample(x,k):从x中随机抽取k个数据,组成一个列表返回。
- random.randrange(start,stop,step):生成一个[start,stop)之间以step为步长的随机整数。默认步长为1。
- random.seek(a):设置初始化随机数种子。a,随机数种子,可以是整数或浮点数。使用random库产生随机数不一定要设置随机数种子,如果不设置,random库默认以系统时间产生当做随机数种子。设置随机数种子的好处是可以重复在现相同的随机数序列。
l1 = [1,2,3,4,5,6,] #列表是有序的
s1 = {1,2,3,4,5,6,}
s2 = 'wfwhgfwqnbvc阿尔天花板vc'
t1 = (1,2,3,4,5,6,)
import random
random.seed()
print(random.random())
print(random.uniform(1,8))
print(random.randint(2,8))
print(random.shuffle(l1)) #只能用于有下标类型,并且可以用x[i],x[j]=x[j],x[i]互换,dict、set、tuple不行。
print(l1)
random.shuffle(s2)
print(s2)
s3 = random.sample(t1,len(t1)) #取样,
print(t1)
time模块
封装了获取时间戳和时间戳与字符串形式的一些方法,时间戳:从时间元年(1970年,1月,1日,00:00:00)到现在经过的秒数(毫秒数,不同系统/编程语言不一样。)
import time
# 获取时间戳:
print(time.time())
# 默认使用当前时间戳,
# 获取格式化时间对象(方法:gmtime()、localtime()),格式化时间对象:struct_time:
print(time.gmtime()) #接受参数为时间戳,默认不写使用当前时间戳,获取格林威治(GMT)时间。
print(time.localtime()) #接受参数为时间戳,默认不写使用当前时间戳,获取当地时间,tm_hour与格林威治时间(时区差)不同。
# 格式化时间对象和时间字符串(str)之间的转换。time.strftime(format,str)
a = time.localtime()
print(time.strftime('%Y-%m-%d %H:%M:%S',a)) #接受两个参数,第一个是时间格式,第二个是格式化时间对象(默认不写用当前的时间戳的格式化时间对象)。
# 时间字符串转换为时间对象(time.strptime(str,format)):
print(time.strptime('2000 1 1','%Y %m %d')) #不指定时间用默认值(小时分钟等用0,月份天等用1)
# 格式化时间对象转换为时间戳:time.mktime()
print(time.mktime(time.localtime()))
# 暂停当前程序:time.sleep() 参数为秒
time.sleep(2) #暂停2秒
datetime模块
封装了一些日期和时间相关的类。主要用于数学计算
date类(年月日):
#date类
d = datetime.date(2010,10,10)
print(d) #2010-10-10
print(d.year) #2010
print(d.month) #10
print(d.day) #10
time类(时分秒):
#time类
t = datetime.time(10,11,12)
print(t)
print(t.hour)
print(t.minute)
print(t.second)
datetime类
dt = datetime.datetime(2010,10,10,11,11,11)
print(dt)
print(dt.year)
timedelta类: 参与数学运算,创建时间对象(只能和date,datetime,timedelta进行运算),会产生进位,和时间段进行运算的结果类型和另一个被操作的类型相同。
td = datetime.timedelta(seconds=3)
d = datetime.datetime(2000,10,10,10,10,59)
res = d+td
print(res)
练习:随便给出一年,计算2月份有多少天。
import datetime
#1.首先创建出指定年份的3月1号,然后让它往前走一天。
year = int(input("输入年份:"))
#2. 创建指定年份的date对象。
d = datetime.date(year,3,1)
dt = datetime.timedelta(days=1)
res = d-dt #和时间段进行运算的结果类型和前方被减类型相同。
print(res.day)
os模块
和操作系统相关的操作被封装在这个模块中。
和文件相关的:重命名、删除、
import os
#删除文件
os.remove() #参数为文件的路径
#重命名文件
os.rename() #两个参数,第一个为文件路径,第二个为文件新名
#删除目录,必须是空目录,在程序中删除不会放在回收站中。
os.removedirs() #一个参数,目录的路径
#使用shutil模块可以删除带内容的目录。
import shutile
shutile.rmtree() #一个参数,文件夹目录
os.getcwd() #可查看当前的目录
os.chdir(‘指定目录’) #可切换目录
和路径相关的操作,被封装到另一个子模块中:os.path
绝对路径:从盘符开始定位的路径;相对路径:从当前文件定位的路径
exists(path) 判断路径是否存在 若文件不存在则为False
isdir(s) 判断是否为一个目录 若文件不存在则为False
isfile() 判断是否是一个文件 若文件不存在则为False
以下方法不会判读文件是否存在
dirname(path) 取一个路径前的目录(父目录),不会判断目录是否存在,
basename(path) 取一个路径中最后的部分
split(path) 分割路径,返回一个二元祖,第一个元素为路径前的(父目录),第二个为路径中最后的部分。
join(path,paths) 合并路径。
abspath(path) 将路径变为绝对路径
isabs() 判断一个路径是否为绝对路径
import os
res = os.path.dirname(r'd:/aaa/bbb/ccc/text.py')
print(res) #d:/aaa/bbb/ccc
res = os.path.basename(r'd:/aaa/bbb/ccc/text.py')
print(res) #text.py
res = os.path.join('d:\\','aaa','bbb','cc') #有一个转义字符
print(res) #d:\aaa\bbb\cc
res = os.path.abspath(r'd:\aaa\bbb\cc')
print(res) #D:\aaa\bbb\cc
res = os.path.abspath(r'\aaa\bbb\cc') #如果是\开头的路径,默认是在当前盘符下。
print(res) #D:\aaa\bbb\cc
res = os.path.abspath(r'aaa\bbb\cc') #如果不是\开头,则是当前脚本的路径。
print(res) #D:\WorkSpace\Python\text1\aaa\bbb\cc
使用os模块获取一个文件路径的父路径:import os os.path.dirname(__file__)
,__file__
:获取模块的路径。import os os.__file__
sys模块
提供了解释器使用和维护的变量和函数;没有提供源码,用c语言编写直接集成在解释器上;默认会导入os模块,但若要使用os模块仍需import os
。
sys.argv
:以当前脚本方式执行程序时,从命令行获取参数。
argv[0]
表示的是当前正在执行的脚本名,argv[1]
表示第一个参数,以此类推。
import sys
print("脚本名:",sys.argv[0])
print("第一个参数:",sys.argv[1])
#在命令行运行,传入两个参数,会将两个参数打印出来
sys.path
系统寻找模块的路径,可以通过PYTHONPATH来进行优化。由于是程序执行的时候进行初始化的,所以路径的第一项path[0]始终是调用解释器的脚本所在的路径,如果是动态调用的脚本,或者是从标准输入读取到的脚本命令,则path[0]是一个空字符串,程序中可以随时对这个路径进行修改,已达到动态添加模块路径的目的。
sys.modules
:以字典形式返回系统已经加载的模块。常作为是否重新重新加载模块的判断。
json模块
将数据结构直接转换为字符串用str()
可以,但再将字符串数据转换为原先的数据结构就会出现问题。
l1 = ['ab','cd']
s1 = str(l1)
print(s1) #['ab', 'cd']
print(list(s1)) #['[', "'", 'a', 'b', "'", ',', ' ', "'", 'c', 'd', "'", ']']
JavaScript Object Notation:Java脚本兑现标记语言。已经成为一种简单的数据交换格式。将数据转换成特殊字符串,不同语言都遵循的一种数据转化格式,用于储存dump()和load()或dumps()和loads()
或网络传输dumps()和loads()
。
json序列化:
import json
s = json.dumps([1,2,3,4,]) #将指定的对象转换成json格式的字符串,仍然放在内存中
print(s,type(s)) #[1, 2, 3, 4] <class 'str'>
#元祖序列化后变成列表
import json
s = json.dumps((1,2,3,4,))
print(s,type(s)) #[1, 2, 3, 4] <class 'str'>
#集合不可一被json序列化
#将结果直接写到文件中:json.dump(obj,fb)
with open('a.txt',mode='at',encoding='utf-8') as f:
json.dump(['1,2,3,'],f)
json反序列化:
import json
res = json.dumps([1,2,3,])
lst = json.loads(res)
#从文件中反序列化:json.loads(fb)
with open('a.txt',encoding='utf-8') as f:
res = json.load(f)
dump()和load()
只能一次性写,一次性读。把需要序列化的对象,通过dumps()和loads()
的方式,可实现多次读或写,写入时要换行,才能读出再转化。
with open('a.txt',mode='wt',encoding='utf-8') as f:
for i in range(10):
f.write(json.dumps()+'\n')
with open('a.txt',encoding='utf-8') as f:
for i in f:
json.loads(i.strip()) # 或json.loads(i),默认去除换行
pickle模块
可将python中所有的数据类型转换成字节串
元祖在pickle中转换不会改变类型。
pickle也可以转换set类型
pickle中dump()和load()
可以多次读写一个文件。dump(s,f)
可以写入python中的任何对象(变量、函数、类等)
import pickle
bys = pickle.dumps((1,2,3)) #转化为字节
res = pickle.loads(bys)
print(type(res),res) #<class 'tuple'> (1, 2, 3)
#把pickle序列化内容写入文件中:
with open('b.txt',mode='wb') as f:
pickle.dump([1,2,3],f)
#从文件中反序列化pickle数据:
with open('b.txt',mode='rb') as f:
pickle.load(f)
pickle与json的比较
json:
- 不是所有的数据类型都可以序列化
- 不能多次对同一个文件序列化
- json数据可以跨语言。
- json序列化只支持部分python数据结构:dict、tuple、int、float、True、False、None
pickle:
- 所有的python类型都能序列化,结果为字节串。
- 可以多次对同一个文件序列化
- 不能跨语言,只能在python中使用。
hashlib模块
封装一些用于加密的类。加密的目的:用于判断和验证,而非解密。给一个数据进行加密,用另个加密的结果和第一次加密的结果进行对比,如果加密结果想同,说明原文相同。
特点:
- 把一个大的数据切分成不同的块,分别对不同的块进行加密,再汇总的结果和直接对整体数据加密的结果是一致的。
- 单向加密,不可逆。
- 原始数据的一点小的变化,将导致加密结果非常大的差异。
md5加密算法:
import hashlib
#获取一个加密对象
m = hashlib.md5()
#使用加密对象的update进行加密
m.update(b'abc') #将abc变为字节,若有中文则为'abc'.encode('utf-8')
#通过hexdigest()获取加密。
res = m.hexdigest()
print(res) #900150983cd24fb0d6963f7d28e17f72
给一个数据加密的步骤:
-
获取一个加密对象,不只是有md5,还有sha系列
sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512'
等,随着sha系列数字越高,加密越复杂,。在创建加密对象时,可以指定参数,使加密程度更高。import hashlib m = hashlib.md5('abc'.encode('utf-8')) m.update('qaz'.encode('utf-8')) print(m.hexdigest())
-
使用加密对象的
update()
方法进行加密。加密对象可以调用多次(即为把一个大数据切分成小数据,再把小数据进行累次加密,不是对同一个数据多次加密)。都是对字节进加密。相同的加密对象将字节转化成固定长度的字符串。 -
通常通过
hexdigest()
获取加密字符串,也可以通过digest()
获取加密字节串。不同加密算法的加密结果长度不同,随着加密结果的变长,加密时间也会变长。
#注册和登录程序 import hashlib def register(): username = input('输入用户名:') passwd = input("输入密码:") get_passwd = get_md5(passwd) #加密 with open('login',mode='at',encoding='utf-8') as f: #写入文件 f.write(f'{username}|{get_passwd}\n') def login(): username = input('输入用户名:') passwd = input('输入密码:') get_passwd = get_md5(passwd) res = f'{username}|{get_passwd}\n' with open('login',mode='rt',encoding='utf-8') as f: for line in f: if res == line: return True else:return False def get_md5(passwd): m = hashlib.md5('12') #再次加密 m.update(passwd.encode('utf-8')) return m.hexdigest() while True: op = input('1.注册 2.登录 3.退出') if op == '1': register() elif op == '2': res = login() if res: print('登录成功') else: print('登录失败,请重新登录') elif op == '3': break else:print("您输入的有误,请重新输入")
文件的校验:
Linux中一切皆文件:文本文件,非文本文件,音频,视频,图片……。无论下载的视频还是国外的软件往往都会有一个md5值。
collections模块
封装了一些常用的容器类。
namedtuple()
:命名元祖,可以使用属性的方式引用元祖中的数据。
import collections as co:
#namedtuple()的返回值是一个类
Rectangle = co.namedtuple('Rectangle_class',['length','width']) #第一个参数是对类名的说明信息,不能有空格。namedtuple()的返回值是赋值给了自定的类名。
r = Rectangle(10,5)
#通过属性访问元祖的元素
print(r.length)
print(r.width)
#通过引所的方式访问元素
print(r[0])
defaultdict()
:默认值字典
#defaultdict():(自定义)函数(不能有参数)充当第一个参数
d = co.defaultdict(lambda :'hello',name='aa',age='10')
print(d['na']) #hello 若无要查询的键,不会报错,会根据函数返回一定的值,且会自动将此键值增加至字典中
print(d)
#defaultdict(<function <lambda> at 0x000001F90D30D378>, {'name': 'aa', 'age': '10', 'na': 'hello'})
Counter()
:计数器,返回值是字典,必须使用可哈希的数据。
c = co.Counter('asasasasaszszxaxzsxazsx')
print(c) #Counter({'s': 8, 'a': 7, 'z': 4, 'x': 4})
print(c.most_common(3)) #[('s', 8), ('a', 7), ('z', 4)]
re模块
findall()
:返回所有符合匹配结果的列表,只有一个元祖元素,每个分组是元祖中的每个元素。如果正则进行分组,则只显示分组里的内容。若不想让每个分组返回;取消分组优先,在分组括号中增加?:
search()
:返回一个对象(变量),需和group()配合。如果进行分组,则只显示第一个分组里的内容,但可以通过group(n)
获取第n个分组的内容(n>0),默认为0,返回所有的分组结果。
设置参数flags=re.S
可让.
匹配任意内容,包括换行符。
import re
ret = re.search('(d+)\w','123123adas1213as')
if ret: #若ret为None直接打印ret.group()就会报错。
print(ret.group())
split()
:可以根据正则表达式切割字符串,返回分组,若给正则加上分组,则会将分组中匹配的内容保留至列表中。
sub()
:替换。re.sub('\d','a','123qwe21',1)
将数字替换成a,只替换1次。
subn()
:替换,返回二元祖。第一个为替换结果,第二个为替换次数。
match()
:只匹配开头,通过group()
取值,相当于使用search()
方法在正则表达前使用^
。用来规定字符串必须是什么。
时间:完成一个程序所需要的代码行数;在执行代码的过程中,底层程序是如何工作的。
空间:占用的内存条资源,程序的执行效率。
compile()
:假如同一个正则表达式要被多次使用,可用re.compile('正则表达式')
可节省了多次解析同一个正则表达式的时间。从时间上提高了效率。如果不重复使用正则,则不会节省时间。
finditer()
:将正则表达式的匹配所有的结果变成一个迭代器,用.group()
每个获取结果。节省了空间。
import re
ret = re.compile('\d')
res = ret.finditer('qaq112qsx123sxa')
for i in res:
print(r.group())
分组命名:在分组中取名?P<分组名>
将名字放在<>
之间。可以用group('分组名')
获取。分组匹配的内容可以被引用。
import re
exp = '<h1>123qdwdcasd</h1>'
ret = re.search('<(?P<tag>\w+)>.*?</(?P=tag)>',exp) #第二个分组引用的是第一个分组匹配的内容。
print(ret)
分组间也可以用\n
引用:n为要引用的第几个分组。
import re
exp = '<h1>123qdwdcasd</h1>'
ret = re.search(r'<(?P<tag>\w+)>.*?</\1>',exp) #在python中`\1、\2、\3等是有特殊意义的,因此要表示在正则中的意义需要转义,即加r或\
ret = re.search('<(?P<tag>\w+)>.*?</\\1>',exp)
shutil模块
import shutil
# 拷贝文件,shutil.copy2('原文件', '现文件')
shutil.copy2('file', 'temp')
# 拷贝目录,shutil.copytree("原目录", "新目录",ignore=shutil.ignore_patterns(*args))
#ignore,忽略要copy的文件
shutil.copytree("/Users/jingliyang/PycharmProjects", "logging模块2", ignore=shutil.ignore_patterns('*.py')) #*.py:所有的以.py结尾的。
# 删除目录,shutil.rmtree("temp", ignore_errors=True) ignore_errors:是否忽略一些错误。
shutil.rmtree("logging模块2", ignore_errors=True)
# 移动文件/目录,并可以重命名。
shutil.move("logging模块", "logging2", copy_function=shutil.copy2)
# 获取磁盘使用空间
total, used, free = shutil.disk_usage(".") .:查看当前磁盘的空间,也可以用:'c:\\'
print("当前磁盘共: %iGB, 已使用: %iGB, 剩余: %iGB"%(total / 1073741824, used / 1073741824, free / 1073741824))
# 压缩文件,shutil.make_archive('压缩文件夹的名字', 'zip','待压缩的文件夹路径')
shutil.make_archive('logging2', 'zip','/Users/jingliyang/PycharmProjects/面试题/常用模块/随机数')
# 解压文件,shutil.unpack_archive('zip文件的路径.zip','解压到目的文件夹路径')
shutil.unpack_archive('/Users/jingliyang/PycharmProjects/面试题/常用模块/shutil模块/logging2.zip','/Users/jingliyang/PycharmProjects/面试题/常用模块/shutil模块/tmp')
logging模块
log:用来记录用户的行为,以便数据分析,操作审计;用来排查代码中的错误。
基本配置: