Python 核心编程(第二版)
Python cook book
流畅的编程(Fluent Python)
模块(module)
开发过程中,程序代码回越来越多,如果直接放在一个文件里,代码回越来越长。代码不易维护。
为了编写方便维护的代码,可以把不同功能的代码分组,保存在不同的文件里。这样,每个文件包含的代码量会比较少,更方便维护。
在Python中,一个.py文件就可以称为一个模块。
即:
- 包含相应功能的函数及变量,py则以".py"为后缀名;
- 模块可以为其他的程序引用,以使用该模块对应的函数或者变量
使用的模块的优点:
- 提高代码的可维护性
- 提高代码的复用性
- 可以导入很多功能的模块
- 标准库模块
- 第三方模块(pip安装的模块)
- 自定义模块(自己编写的)
- 避免变量名重复(作用域)
Python中导入模块的常用方式:
import 模块名称
import 模块名称 as 新名称
from 模块名称 import 函数名
区别:
- import 模块名称 和import 模块名称 as 新名称
- 会导入整个模块
- 如果我们需要使用某个函数,必须以“模块名称.函数名()”的形式来调用相应的函数。(这种方法可以更有利于代码的可读性(u偶先推荐的方法))
- import 模块名称 as 新名称,重新命名导入的模块,通常使模块名称简洁,方便使用。
- from 模块名称 import 函数名
- 只导入了某一函数,而不是某一模块
- 可以直接函数名称去调用函数,而无需在函数名称前加模块名称
- 如果程序语句很多,不建议采用此种方法(原因:调用很多模块,可能造成函数重名,引发错误)
from random import *
print(random())
print(randint(1,10))
注意
import语句的对应模块顺序(PEP)(程序的最上方)
- Python标准模块
- 第三方
- 自定义模块
自定义模块
OS模块
os模块是Python标准库中用于访问操作系统功能的模块。
使用OS模块提供的接口,能够实现跨平台访问。
最常见的操作:
- 目录的操作
- 判断
1.系统操作
- os.sep:用于查看系统路径的分隔符;
- Windows ——>’\’
- ubuntu ——>’/’
- os.name:显示我们正在使用的平台
- Windows ——>‘nt’
- Linux/Unix ——>‘posix’
- os.getenv() ——>读取环境变量 (environment)
- os.getcwd() ——>获取当前路径
2.目录操作——增删改查
- os.listdir():返回指定目录下的所有文件和目录名
>>> os.listdir() #未指定路径,当前路径下
['.idea', 'data', 'day1.py', 'day2.py', 'day3.py', 'day4.py', 'day5.py', 'venv']
>>>dirs = "D:\python.shixun>python" #指定路径下
>>> os.listdir(dirs)
['...']
-
目录的创建
- os.mkdir(path):创建目录,但仅创建一级目录
- os.makedirs(path):创建目录,创建多级目录
>>> os.mkdir('os_test') >>> os.makedirs('main_file/sub_file')
-
目录/文件删除
- os.rmdir(path) :删除空目录(一级)
- os.removedirs(path):删除空目录(多级)
- os.remove(path):
>>> os.mkdir('os_test') >>> os.makedirs('main_file/sub_file') >>> os.rmdir('os_test') >>> os.rmdir('data') Traceback (most recent call last): File "<stdin>", line 1, in <module> OSError: [WinError 145] 目录不是空的。: 'data' >>> os.removedirs('main_file/sub_file') >>> os.makedirs('main_file/sub_file') >>> os.removedirs('main_file/sub_file') >>> >>>os.remove('main_file/新建文档.txt')
-
更改路径
- os.chdir(path):change direction #将当前工作目录更改到指定的工作目录
- os.rename(旧,新)
>>> os.getcwd()
'D:\\python.shixun'
>>> os.chdir('..') #..表示上一级目录
>>> os.getcwd()
'D:\\'
>>>
>>>os.rename('data.txt','data.md')
-
判断文件
-
os.path.exists(path):判断文件或者目录是否存在,存在,True;否则,False
-
os.path.isfile(path):判断是否为文件,是,True;否,False
-
os.path.isdir(path):判断是否为目录,是,True;否,False
>>> os.path.exists('day1.py') #有后缀为文件 True >>> os.path.exists('data') #无后缀为目录 True
-
拓展:
- os.path.dirname(path):返回文件路径;
>>> os.path.dirname('D:\python.shixun\day1.py')
'D:\\python.shixun'
-
os.path.basename(path):返回文件名称
-
os.path.getsize(path):返回文件大小
-
os.path.abspath(name):返回文件的绝对路径
-
os.path.join(path,name):连接目录与环境
-
os.path.split(path):将path的目录和文件名分割开,并返回元组
-
查看文件的时间
- os.path.getmtime(path):返回文件或者目录的最后修改时间,结果为秒数——>modify
- os.path.getatime(path):返回文件或者目录的最后访问时间,结果为秒数
- os.path.getctime(path):返回文件或者目录的创建时间,结果为秒数
import datetime tm = os.path.getctime('day1.md') >>>1563785731.1246715 time.strftime('%Y-%m-%d %X',tX`ime.localtime(tm)) >>>'2019-07-22 16:55:31' im_g = os.path.getmtime('day1.md') time.strftime('%Y-%m-%d %X',time.localtime(im_g)) '2019-07-21 21:21:02'
-
查看文件和目录
- os.walk(path):
path = os.walk('..') for i in path: ... print(i)
包
module and package
包:包是通过使用’.模块名’来阻止Python模块名称空间的方式。
具体而言,包就是一个包含‘_init_.py’文件的文件夹。
目的:用文件夹将文件/模块组织起来。
注意:
py3,即使包中没有_init_.py 也可以使用;py2,如果没有_init_.py 会报错
创建包的目的不是为了运行,而是为了被导入使用。
包的本质依然还是模块。
- 使用时,import导入,导入带点的,点的最左边一定是包名。
- (.)表示当前目录 ( from . import a 不能直接a.function 运行)
- import导入文件时,产生名称空间的名字源于文件,import包,名称空间同样源于文件(包),_init_.py,导入包的本质导入它。
- (…)表示当前上一层目录
import school.db.models
school.db.models.register_models('Mysql')
import school
school.cmd.manage.main() #单独导入包时,不会导入包所包含的所有子模块
from school.cmd import manage
manage.main()
from school import cmd.manage #import后面不能带点
>>>报错
from school.cmd.manage import main
main()
```python
➜ school tree
.
├── api
│ ├── __init__.py
│ ├── students.py
│ └── versions.py
├── cmd
│ ├── __init__.py
│ └── manage.py
├── db
│ ├── __init__.py
│ └── models.py
└── __init__.py
```
在school/api/versions.py中导入school/cmd/manage.py
#在school/api/versions.py中
from school.cmd import manage
manage.main()
from school.api import versions
versions.manage.main()
字符编码
Python主要识别文件内容,而不是关心拓展名。——>解释器
字符——>(机器翻译)——>二进制
字符如何对应特定数字的标准,这个标准就是字符编码。
ASCII(英文字符)
GBK(中文字符)
Unicode
UTF-8 ( Unicode Transformation Format)
- 对于英文字符来说,1Bytes
- 对于中文字符,3Bytes
- 对于其他偏僻字符,更多的bytes存储
对于内存而言——>Unicode
utf-8————
time模块
import time
time.sleep([n]) #休眠n秒
time.time() #获取当前时间戳
在Python中,表示时间通常有三种方式:
-
时间戳(timetamp):表示的是从1970.01.01 00:00:00开始按秒计算的便宜量
import time print(time.time()) >>>1564103103.8556807
-
格式化的时间字符串(format string)
2019-07-26 08:48:21
print(time.strftime('%Y-%m-%d %x')) >>>2019-07-26 07/26/19
-
结构化的时间(struct_time)——>元组,9个元素(年月日时分秒,一年的第几周,一年的第几天,夏令时)
print(time.gmtime(time.time())) >>>time.struct_time(tm_year=2019, tm_mon=7, tm_mday=26, tm_hour=1, tm_min=18, tm_sec=31, tm_wday=4, tm_yday=207, tm_isdst=0)
python中时间日期格式化符号:
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身
time模块的常用方法
方法 | 描述 |
---|---|
time.localtime([set]) | 将一个时间戳转化为当前时区的struct_time(若未提供参数,为当前时间) |
time.gmtime([set]) | 和localtime()类似,不同的是,其是将一个时间戳转化为UTC时区(0时区)的struct_time |
time.time() | 返回当前的时间戳 |
time.mktime(t) | 将time.struct_time转化为时间戳 |
time.sleep(sec) | 线程推迟制定的时间运行,单位(s) |
time.asctime([t]) | 将表示时间的元组或struct_time表示为:“Fri Jul 26 09:08:34 2019”;如果未传参数,默认为time.localtime() |
time.ctime([t]) | 把一个时间戳转化为time.asctime的形式。如果未传参数,默认time.time() |
time.strftime(format[,t]) | 把一个代表时间的元组/struct_time/localtime()和gmime()转化为格式化的字符串,未传参数,默认为time.localtime() |
time.striptime() | 将结构化字符串转化为struct_time形式 |
- 时间戳:计算机识别
- 字符串时间:人类可以看
- 结构化时间:对时间操作
时间戳和结构化时间的转化
- time.gmtime(now)
- time.localtime(now)
now = time.time()
print(time.gmtime(now))
print(time.localtime(now))
>>>time.struct_time(tm_year=2019, tm_mon=7, tm_mday=26, tm_hour=1, tm_min=22, tm_sec=4, tm_wday=4, tm_yday=207, tm_isdst=0)
>>>time.struct_time(tm_year=2019, tm_mon=7, tm_mday=26, tm_hour=9, tm_min=22, tm_sec=4, tm_wday=4, tm_yday=207, tm_isdst=0)
结构化时间和时间戳的转化
- time.mktime(结构化时间)
tp = time.localtime()
print(time.mktime(tp))
>>>1564104254.0
结构化时间到字符串时间的转化
- time.strftime
tp = time.localtime()
print(time.strftime("%Y-%m-%d %X"))
>>>2019-07-26 09:27:15
字符串时间到结构化时间的转化
- time.strptime(时间字符串,字符串对应格式)
print(time.strptime('2019-07-26', "%Y-%m-%d" )) #效果相同
print(time.strptime('2019/07/26', "%Y/%m/%d" ))
>>>time.struct_time(tm_year=2019, tm_mon=7, tm_mday=26, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=207, tm_isdst=-1)
>>>time.struct_time(tm_year=2019, tm_mon=7, tm_mday=26, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=207, tm_isdst=-1)
结构化时间和字符串时间的转化(国际化时间字符串)
- time.asctime(结构化时间)
tp = time.localtime()
print(time.asctime(tp))
print(time.asctime())
>>>Fri Jul 26 09:50:15 2019
>>>Fri Jul 26 09:50:15 2019
时间戳和字符串的转化(国际化)
- time.ctime
print(time.ctime(time.time()))
>>>Fri Jul 26 09:53:15 2019
print(time.ctime)
>>>Fri Jul 26 09:53:15 2019
print(time.ctime(1111111111))
>>>Fri Mar 18 09:58:31 2005
datetime 模块
相比time来说,datetime模块接口更直观,更容易调用
方法(类) | 描述 |
---|---|
datetime.date | 表示日期(类),常用属性year,month,day |
datetime.time | 表示时间(类),常用属性hour,minute,second,microsecond |
datetime.datetime | 表示日期 |
datetime.timedelta | 表示时间间隔 |
datetime.tzinfo | 与时区有关的信息 |
import datetime
print(datetime.datetime.now().date())
print(datetime.datetime.now().time())
>>>2019-07-26
>>>10:05:11.056634
sys模块
sys模块是与Python解释器交互的一个接口。
Script:脚本
处理命令行参数
在解释器启动后,argv列表包含
序列化模块
序列化
概念:将一个对象从内存中转换为可存储(字符串类型)或者可传输(bytes)类型的过程。
Python中叫pickling。
为什么要使用序列化?
- 持久化数据类型
- 跨平台交互使用
- 使程序更易维护
json
json格式在各个语言中都可以通用序列化格式。在json中,所有的字符串必须为""。
json类型 | Python类型 |
---|---|
{} | dict |
[] | list |
“string” | str |
1234.56 | int/float |
true/false | True/False |
null | None |
json优缺点:
- 优点:所有的数据类型是各语言通用的
- 缺点:
- json只支持比较少的数据类型
- 对数据类型的约束十分严格
- 字典中的key必须是字符串
- json只支持列表,字典,数值,字符串以及布尔值
查看json的方法和属性
四个功能
- dumps
- dump
- loads
- load
序列化
import json
dic = {'name':'city', 'age': 20}
sr_dic = json.dumps(dic) #序列化,将字典转化为字符串
print(type(sr_dic))
>>><class 'str'>
print(sr_dic)
{"name": "city", "age": 20}
sr_dic
>>>'{"name": "city", "age": 20}'
序列化时,字典的key必须为string
字典中的value如果是元组,会被转化成列表
反序列化
dic_2 = json.loads(sr_dic)
print(dic_2)
>>>{'name': 'city', 'age': 20}
如果把数据类型直接序列化写入文件中,可以用dump和load方法。
dic = {'11':'a'}
with open('dump_json','w') as f:
json.dump(dic, f) #dump方法可以接受一个文件句柄。直接将字典转化为字符串,写入文件中
with open('dump_json')as f:
ret = json.load(f)
print((ret, type(ret)))
>>>({'11': 'a'}, <class 'dict'>)
多项写入读取
dic = {'11':'a'}
dic2 = {'c':'hangzhou'}
with open('dump_json1','w') as f:
str_dic1 = json.dumps(dic)
str_dic2 = json.dumps(dic2)
f.write(str_dic1+'\n')
f.write(str_dic2+'\n')#dump方法可以接受一个文件句柄。直接将字典转化为字符串,写入文件中
with open('dump_json1')as f:
for line in f:
ret = json.loads(line)
print(ret)
pickle
只用于Python
内存中结构化的数据 (格式pickle)(bytes类型)(保存在文件或基于网络传输
pickle优缺点
-
优点
-
支持python中的几乎所有数据类型
- pickle会把数据类型序列化为bytes类
-
-
缺点
只支持Python
模块提供四个功能
-
序列化
dumps
dump
-
反序列化
loads
load
import pickle
dic = {'name':'zxc', 'age': 22}
dic_b = pickle.dumps(dic)
print(type(dic_b))
>>><class 'bytes'>
dic_d = pickle.loads(dic_b)
print(type(dic_d))
>>><class 'dict'>
文件写入与读取
with open('pickle_dump', 'wb')as f:
pickle.dump(dic_b, f)
with open('pickle_dump', 'rb')as f:
print(pickle.load(f))
>>>b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00zxcq\x02X\x03\x00\x00\x00ageq\x03K\x16u.'