本篇文章主要是对python学习时的一些总结,作为学习笔记记录。
虽然python基础的开发环境已经包含很多的内置工具和功能,但大多都是一些比较基础性的功能,对于特定领域如可视化,数值计算,数据分析等来说,其使用就显得有些捉襟见肘了,因此我们就需要使用一些外部或者自定义的工具,这类工具就叫做模块。
在python中,我们可以将事先定义好的方法和变量定义都放置在文件中,从而为一些脚本或者解释器使用,而这类文件就叫做模块,后缀名为.py。通常情况下可以使用import关键字进行模块引入。
使用import关键字可以导入本地搜索路径下的模块。
import moduleName1[, moduleName2, ...]
但我们需要导入time模块时:
import time
print(time.ctime())
结果为:
Sat Dec 26 17:11:13 2020
这样我们就调用了time模块中的ctime方法,得到了当前的时间。
而对于解释器来说,当解释器遇到import关键字时,解释器会在当前的搜索路径中进行相关模块的搜索,如果搜索到相关模块就能够导入,从而可以进行访问。利用import进行模块导入的操作有点像C/C++中包含头文件,都是为了进行功能扩展,从而可以使用外部的接口,而对于python解释器来说,同样要想C/C++那样避免重复导入,也就是说不论我们使用import对同意模块进行多少次带入,都应该被导入一次。
之前我们提到了搜索路径,搜索路径有点类似于C/C++的头文件包含路径,python中的搜索路径包含了一系列的目录名,在利用import进行模块导入时,python解释器就会在这些目录中搜索相对应的模块。通常情况下,在本地安装完python之后,就会在本地自动添加python解释器的搜索路径,如果没有自动添加的话,也可以在环境变量中进行修改。python解释器的搜索路径可以通过sys模块中的path变量进行查看:
import sys
sys.path
结果为:
['',
'D:\\Anaconda3\\python36.zip',
'D:\\Anaconda3\\DLLs',
'D:\\Anaconda3\\lib',
'D:\\Anaconda3',
'C:\\......\\AppData\\Roaming\\Python\\Python36\\site-packages',
'D:\\Anaconda3\\lib\\site-packages',
'D:\\Anaconda3\\lib\\site-packages\\win32',
'D:\\Anaconda3\\lib\\site-packages\\win32\\lib',
'D:\\Anaconda3\\lib\\site-packages\\Pythonwin',
'D:\\Anaconda3\\lib\\site-packages\\IPython\\extensions',
'C:\\......\\.ipython']
sys.path的输出结果是一个列表,其中第一个元素为空,表示当前目录(该结果是在jupyer平台下进行打印输出的,如果利用IDE的脚本打印,则可能不为空,而是具体的本地目录)。
python中的from语句可以从某个模块中导入指定的部分:
from moduleName import name1[, name2, ...]
当我们想要从time模块中导入ctime函数时:
from time import ctime
print(ctime())
结果为:
Sat Dec 26 19:57:24 2020
用 * 来代替导入指定的模块部分会导入模块中的所有内容,虽然这样用起来很方便,但是却存在潜在的问题,如果导入的模块内部存在与自定义的内容重复的部分,可能会发生意想不到的错误,具体使用时应该避免这种情况。
from time import *
print(locals())
当使用上面导入模块的方法,再利用locals()函数查看局部变量就会发现出现了很多和time模块相关的方法,这对于编程来说很不友好。
对于模块来说,除了可以包含方法和变量定义外,还可以包含可执行代码,这些代码有些是为了初始化代码,有些则是为了进行测试,而对于用户来说,用户关心的可能只是模块中提供的方法,而不是其中的可执行代码,此时用户可以利用__name__属性来选择该段代码是否需要执行。
每个模块都存在一个__name__,只有当其值为__main__时,才表示该模块自身在运行,否则就是被导入的模块。这种使用方式有点类似与C/C++中的main函数一样,表明了该程序的入口。使用方式一般为:
if __name__ == '__main__':
pass
dir()函数可以返回模块内定义的所有名称的字符串列表。
import time
print(dir(time))
结果为:
['_STRUCT_TM_ITEMS', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'perf_counter', 'process_time', 'sleep', 'strftime', 'strptime', 'struct_time', 'time', 'timezone', 'tzname']
对于没有参数的dir()函数来说,会返回当前定义的所有名称:
print(dir())
结果为:
['In', 'Out', '_', '__', '___', '__builtin__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '_dh', '_i', '_i1', '_ih', '_ii', '_iii', '_oh', 'exit', 'get_ipython', 'quit']
python本身就带有一些标准的模块库,常见的标准模块有:
os模块主要可以对操作系统进行操作。常见的操作有:
os.remove() 删除文件
os.unlink() 删除文件
os.rename() 重命名文件
os.listdir() 列出指定目录下所有文件
os.chdir() 改变当前工作目录
os.getcwd() 获取当前文件路径
os.mkdir() 新建目录
os.rmdir() 删除空目录(删除非空目录, 使用shutil.rmtree())
os.makedirs() 创建多级目录
os.removedirs() 删除多级目录
os.stat(file) 获取文件属性
os.chmod(file) 修改文件权限
os.utime(file) 修改文件时间戳
os.name(file) 获取操作系统标识
os.system() 执行操作系统命令
os.execvp() 启动一个新进程
os.fork() 获取父进程ID,在子进程返回中返回0
os.execvp() 执行外部程序脚本(Uinx)
os.spawn() 执行外部程序脚本(Windows)
os.access(path, mode) 判断文件权限(详细参考cnblogs)
os.wait() 暂时未知
os.path模块主要是对文件路径的相关操作
os.path.split(filename) 将文件路径和文件名分割(会将最后一个目录作为文件名而分离)
os.path.splitext(filename) 将文件路径和文件扩展名分割成一个元组
os.path.dirname(filename) 返回文件路径的目录部分
os.path.basename(filename) 返回文件路径的文件名部分
os.path.join(dirname,basename) 将文件路径和文件名凑成完整文件路径
os.path.abspath(name) 获得绝对路径
os.path.splitunc(path) 把路径分割为挂载点和文件名
os.path.normpath(path) 规范path字符串形式
os.path.exists() 判断文件或目录是否存在
os.path.isabs() 如果path是绝对路径,返回True
os.path.realpath(path) 返回path的真实路径
os.path.relpath(path[, start]) 从start开始计算相对路径
os.path.normcase(path) 转换path的大小写和斜杠
os.path.isdir() 判断name是不是一个目录,name不是目录就返回false
os.path.isfile() 判断name是不是一个文件,不存在返回false
os.path.islink() 判断文件是否连接文件,返回boolean
os.path.ismount() 指定路径是否存在且为一个挂载点,返回boolean
os.path.samefile() 是否相同路径的文件,返回boolean
os.path.getatime() 返回最近访问时间 浮点型
os.path.getmtime() 返回上一次修改时间 浮点型
os.path.getctime() 返回文件创建时间 浮点型
os.path.getsize() 返回文件大小 字节单位
os.path.commonprefix(list) 返回list(多个路径)中,所有path共有的最长的路径
os.path.lexists 路径存在则返回True,路径损坏也返回True
os.path.expanduser(path) 把path中包含的”~”和”~user”转换成用户目录
os.path.expandvars(path) 根据环境变量的值替换path中包含的”$name”和”${name}”
os.path.sameopenfile(fp1, fp2) 判断fp1和fp2是否指向同一文件
os.path.samestat(stat1, stat2) 判断stat tuple stat1和stat2是否指向同一个文件
os.path.splitdrive(path) 一般用在windows下,返回驱动器名和路径组成的元组
os.path.walk(path, visit, arg) 遍历path,给每个path执行一个函数详细见手册
os.path.supports_unicode_filenames() 设置是否支持unicode路径名
stat模块描述返回的文件属性列表中各值的意义
fileStats = os.stat(path) 获取到的文件属性列表
fileStats[stat.ST_MODE] 获取文件的模式
fileStats[stat.ST_SIZE] 文件大小
fileStats[stat.ST_MTIME] 文件最后修改时间
fileStats[stat.ST_ATIME] 文件最后访问时间
fileStats[stat.ST_CTIME] 文件创建时间
stat.S_ISDIR(fileStats[stat.ST_MODE]) 是否目录
stat.S_ISREG(fileStats[stat.ST_MODE]) 是否一般文件
stat.S_ISLNK(fileStats[stat.ST_MODE]) 是否连接文件
stat.S_ISSOCK(fileStats[stat.ST_MODE]) 是否COCK文件
stat.S_ISFIFO(fileStats[stat.ST_MODE]) 是否命名管道
stat.S_ISBLK(fileStats[stat.ST_MODE]) 是否块设备
stat.S_ISCHR(fileStats[stat.ST_MODE]) 是否字符设置
sys模块表示系统特定的参数和功能,该模块提供对解释器使用或维护的一些变量的访问,以及与解释器强烈交互的函数
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.modules.keys() 返回所有已经导入的模块列表
sys.modules 返回系统导入的模块字段,key是模块名,value是模块
sys.exc_info() 获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息
sys.exit(n) 退出程序,正常退出时exit(0)
sys.hexversion 获取Python解释程序的版本值,16进制格式如:0x020403F0
sys.version 获取Python解释程序的版本信息
sys.platform 返回操作系统平台名称
sys.stdout 标准输出
sys.stdout.write(‘aaa‘) 标准输出内容
sys.stdout.writelines() 无换行输出
sys.stdin 标准输入
sys.stdin.read() 输入一行
sys.stderr 错误输出
sys.exc_clear() 用来清除当前线程所出现的当前的或最近的错误信息
sys.exec_prefix 返回平台独立的python文件安装的位置
sys.byteorder 本地字节规则的指示器,big-endian平台的值是‘big‘,little-endian平台的值是‘little‘
sys.copyright 记录python版权相关的东西
sys.api_version 解释器的C的API版本
sys.version_info ‘final‘表示最终,也有‘candidate‘表示候选,表示版本级别,是否有后继的发行
sys.getdefaultencoding() 返回当前你所用的默认的字符编码格式
sys.getfilesystemencoding() 返回将Unicode文件名转换成系统文件名的编码的名字
sys.builtin_module_names Python解释器导入的内建模块列表
sys.executable Python解释程序路径
sys.getwindowsversion() 获取Windows的版本
sys.stdin.readline() 从标准输入读一行,sys.stdout.write(“a”) 屏幕输出a
sys.setdefaultencoding(name) 用来设置当前默认的字符编码(详细使用参考文档)
sys.displayhook(value) 如果value非空,这个函数会把他输出到sys.stdout(详细使用参考文档)
datetime,date,time模块是与时间,日期相关的模块
datetime.date.today() 本地日期对象,(用str函数可得到它的字面表示(2014-03-24))
datetime.date.isoformat(obj) 当前[年-月-日]字符串表示(2014-03-24)
datetime.date.fromtimestamp() 返回一个日期对象,参数是时间戳,返回 [年-月-日]
datetime.date.weekday(obj) 返回一个日期对象的星期数,周一是0
datetime.date.isoweekday(obj) 返回一个日期对象的星期数,周一是1
datetime.date.isocalendar(obj) 把日期对象返回一个带有年月日的元组
datetime对象:
datetime.datetime.today() 返回一个包含本地时间(含微秒数)的datetime对象 2014-03-24 23:31:50.419000
datetime.datetime.now([tz]) 返回指定时区的datetime对象 2014-03-24 23:31:50.419000
datetime.datetime.utcnow() 返回一个零时区的datetime对象
datetime.fromtimestamp(timestamp[,tz]) 按时间戳返回一个datetime对象,可指定时区,可用于strftime转换为日期表示
datetime.utcfromtimestamp(timestamp) 按时间戳返回一个UTC-datetime对象
datetime.datetime.strptime(‘2014-03-16 12:21:21‘,”%Y-%m-%d %H:%M:%S”) 将字符串转为datetime对象
datetime.datetime.strftime(datetime.datetime.now(), ‘%Y%m%d %H%M%S‘) 将datetime对象转换为str表示形式
datetime.date.today().timetuple() 转换为时间戳datetime元组对象,可用于转换时间戳
datetime.datetime.now().timetuple()
time.mktime(timetupleobj) 将datetime元组对象转为时间戳
time.time() 当前时间戳
time.localtime
time.gmtime
random模块是和随机数相关的模块
random.random() 产生0-1的随机浮点数
random.uniform(a, b) 产生指定范围内的随机浮点数
random.randint(a, b) 产生指定范围内的随机整数
random.randrange([start], stop[, step]) 从一个指定步长的集合中产生随机数
random.choice(sequence) 从序列中产生一个随机数
random.shuffle(x[, random]) 将一个列表中的元素打乱
random.sample(sequence, k) 从序列中随机获取指定长度的片断
string模块则是和字符串操作有关的模块
str.capitalize() 把字符串的第一个字符大写
str.center(width) 返回一个原字符串居中,并使用空格填充到width长度的新字符串
str.ljust(width) 返回一个原字符串左对齐,用空格填充到指定长度的新字符串
str.rjust(width) 返回一个原字符串右对齐,用空格填充到指定长度的新字符串
str.zfill(width) 返回字符串右对齐,前面用0填充到指定长度的新字符串
str.count(str,[beg,len]) 返回子字符串在原字符串出现次数,beg,len是范围
str.decode(encodeing[,replace]) 解码string,出错引发ValueError异常
str.encode(encodeing[,replace]) 解码string
str.endswith(substr[,beg,end]) 字符串是否以substr结束,beg,end是范围
str.startswith(substr[,beg,end]) 字符串是否以substr开头,beg,end是范围
str.expandtabs(tabsize = 8) 把字符串的tab转为空格,默认为8个
str.find(str,[stat,end]) 查找子字符串在字符串第一次出现的位置,否则返回-1
str.index(str,[beg,end]) 查找子字符串在指定字符中的位置,不存在报异常
str.isalnum() 检查字符串是否以字母和数字组成,是返回true否则False
str.isalpha() 检查字符串是否以纯字母组成,是返回true,否则false
str.isdecimal() 检查字符串是否以纯十进制数字组成,返回布尔值
str.isdigit() 检查字符串是否以纯数字组成,返回布尔值
str.islower() 检查字符串是否全是小写,返回布尔值
str.isupper() 检查字符串是否全是大写,返回布尔值
str.isnumeric() 检查字符串是否只包含数字字符,返回布尔值
str.isspace() 如果str中只包含空格,则返回true,否则FALSE
str.title() 返回标题化的字符串(所有单词首字母大写,其余小写)
str.istitle() 如果字符串是标题化的(参见title())则返回true,否则false
str.join(seq) 以str作为连接符,将一个序列中的元素连接成字符串
str.split(str=‘‘,num) 以str作为分隔符,将一个字符串分隔成一个序列,num是被分隔的字符串
str.splitlines(num) 以行分隔,返回各行内容作为元素的列表
str.lower() 将大写转为小写
str.upper() 转换字符串的小写为大写
str.swapcase() 翻换字符串的大小写
str.lstrip() 去掉字符左边的空格和回车换行符
str.rstrip() 去掉字符右边的空格和回车换行符
str.strip() 去掉字符两边的空格和回车换行符
str.partition(substr) 从substr出现的第一个位置起,将str分割成一个3元组。
str.replace(str1,str2,num) 查找str1替换成str2,num是替换次数
str.rfind(str[,beg,end]) 从右边开始查询子字符串
str.rindex(str,[beg,end]) 从右边开始查找子字符串位置
str.rpartition(str) 类似partition函数,不过从右边开始查找
str.translate(str,del=‘‘) 按str给出的表转换string的字符,del是要过虑的字符
re模块是和正则表示式相关的模块
一.常用正则表达式符号和语法:
'.' 匹配所有字符串,除\n以外
‘-’ 表示范围[0-9]
'*' 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
'+' 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+
'^' 匹配字符串开头
‘$’ 匹配字符串结尾 re
'\' 转义字符, 使后一个字符改变原来的意思,如果字符串中有字符*需要匹配,可以\*或者字符集[*] re.findall(r'3\*','3*ds')结['3*']
'*' 匹配前面的字符0次或多次 re.findall("ab*","cabc3abcbbac")结果:['ab', 'ab', 'a']
‘?’ 匹配前一个字符串0次或1次 re.findall('ab?','abcabcabcadf')结果['ab', 'ab', 'ab', 'a']
'{m}' 匹配前一个字符m次 re.findall('cb{1}','bchbchcbfbcbb')结果['cb', 'cb']
'{n,m}' 匹配前一个字符n到m次 re.findall('cb{2,3}','bchbchcbfbcbb')结果['cbb']
'\d' 匹配数字,等于[0-9] re.findall('\d','电话:10086')结果['1', '0', '0', '8', '6']
'\D' 匹配非数字,等于[^0-9] re.findall('\D','电话:10086')结果['电', '话', ':']
'\w' 匹配字母和数字,等于[A-Za-z0-9] re.findall('\w','alex123,./;;;')结果['a', 'l', 'e', 'x', '1', '2', '3']
'\W' 匹配非英文字母和数字,等于[^A-Za-z0-9] re.findall('\W','alex123,./;;;')结果[',', '.', '/', ';', ';', ';']
'\s' 匹配空白字符 re.findall('\s','3*ds \t\n')结果[' ', '\t', '\n']
'\S' 匹配非空白字符 re.findall('\s','3*ds \t\n')结果['3', '*', 'd', 's']
'\A' 匹配字符串开头
'\Z' 匹配字符串结尾
'\b' 匹配单词的词首和词尾,单词被定义为一个字母数字序列,因此词尾是用空白符或非字母数字符来表示的
'\B' 与\b相反,只在当前位置不在单词边界时匹配
'(?P...)' 分组,除了原有编号外在指定一个额外的别名 re.search("(?P[0-9]{4})(?P[0-9]{2})(?P[0-9]{8})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '19930614'}
[] 是定义匹配的字符范围。比如 [a-zA-Z0-9] 表示相应位置的字符要匹配英文字符和数字。[\s*]表示空格或者*号。
二.常用的re函数:
方法/属性 作用
re.match(pattern, string, flags=0) 从字符串的起始位置匹配,如果起始位置匹配不成功的话,match()就返回none
re.search(pattern, string, flags=0) 扫描整个字符串并返回第一个成功的匹配
re.findall(pattern, string, flags=0) 找到RE匹配的所有字符串,并把他们作为一个列表返回
re.finditer(pattern, string, flags=0) 找到RE匹配的所有字符串,并把他们作为一个迭代器返回
re.sub(pattern, repl, string, count=0, flags=0) 替换匹配到的字符串
math模块则是和数学计算相关的模块
ceil:取大于等于x的最小的整数值,如果x是一个整数,则返回x
copysign:把y的正负号加到x前面,可以使用0
cos:求x的余弦,x必须是弧度
degrees:把x从弧度转换成角度
e:表示一个常量
exp:返回math.e,也就是2.71828的x次方
expm1:返回math.e的x(其值为2.71828)次方的值减1
fabs:返回x的绝对值
factorial:取x的阶乘的值
floor:取小于等于x的最大的整数值,如果x是一个整数,则返回自身
fmod:得到x/y的余数,其值是一个浮点数
frexp:返回一个元组(m,e),其计算方式为:x分别除0.5和1,得到一个值的范围
fsum:对迭代器里的每个元素进行求和操作
gcd:返回x和y的最大公约数
hypot:如果x是不是无穷大的数字,则返回True,否则返回False
isfinite:如果x是正无穷大或负无穷大,则返回True,否则返回False
isinf:如果x是正无穷大或负无穷大,则返回True,否则返回False
isnan:如果x不是数字True,否则返回False
ldexp:返回x*(2**i)的值
log:返回x的自然对数,默认以e为基数,base参数给定时,将x的对数返回给定的base,计算式为:log(x)/log(base)
log10:返回x的以10为底的对数
log1p:返回x+1的自然对数(基数为e)的值
log2:返回x的基2对数
modf:返回由x的小数部分和整数部分组成的元组
pi:数字常量,圆周率
pow:返回x的y次方,即x**y
radians:把角度x转换成弧度
sin:求x(x为弧度)的正弦值
sqrt:求x的平方根
tan:返回x(x为弧度)的正切值
trunc:返回x的整数部分
包是一种管理python模块命名空间的形式,对于一个模块名称 “A.B” 来说,A表示包,B表示包A中的模块B。采用这种管理形式,就可以区分开不同模块中的同名变量的相互影响,或者包中模块同名的问题。
对于包的说明,这里采用一种可能的包结构来说明:
A # 顶层包
__init__.py # 初始化包A
B # 包A.B
__init__.py # 初始化包A.B
module1.py # 模块A.B.module1
module2.py # 模块A.B.module2
......
C # 包A.C
__init__.py # 初始化包A.C
module1.py # 模块A.C.module1
module2.py # 模块A.C.module2
......
D # 包A.C.D
__init__.py # 初始化包A.C.D
module1.py # 模块A.C.D.module1
module2.py # 模块A.C.D.module2
......
需要注意的是:
import A.B.module1
此时会导入模块A.B.module1,同时模块中的变量和函数访问也必须采用这种全名的形式访问。使用这种形式,除了全名的最后一项,其它的名称都必须是包名,而最后一项的名称则可以是模块名或者包名,但不可以是类,变量或者函数。
from A.B.module1.py import func
使用这种方式可以直接导入变量或者函数。而当使用这种形式的时候,import后的名称既可以是包中的子模块,也可以是包中模块的变量或函数。
这里我们再次说明一下使用 * 进行导入的情况。
对于模块来说,* 会导入模块中定义的所有变量,类或者函数,而对于包来说,则会导入包中的所有子模块。这种情形是很可怕的,首先不说不同平台对于命名的支持,单是各个包中模块对于变量,函数的名称冲突都可能是一个大问题,因此这种方法并不提倡。
而为了避免这个问题,导入的时候尽量进行精确导入,以防止出现问题。
在包导入的时候,包所在的目录下会有一个__init__.py文件,在该文件中可能会存在一个名为__all__的列表变量,该变量限制了利用 * 进行导入的范围。
如在A.C中的__init__.py中的__all__变量为:
__all__ = ["module1"]
则在利用from A.C import *进行导入时,只会导入module1模块。
而如果__all__变量没有定义,在使用 * 进行导入的时候,就不会导入包A.C中的任何子模块。解释器只是把A.C和它里面定义的内容导入进来(可能运行__init__.py中定义的初始化代码,如果__init__.py文件为空,则可能什么都没有导入)。
这是一个目录列表,其中每一个包含的目录都含有为该包服务的__init__.py文件,该变量需要在__init__.py被执行之前进行定义。也可以修改该变量,以修改包含在该包中的模块和自包。