Python DAY6进阶语法:文件/标准常用库/字符编码和解码

马上期末考试了,进度暂缓一下,今天就只弄些进阶语法

Python 文件模块

电脑文件的操作是任何一门编程语言都会涉及的知识,本篇博客主要围绕 Windows 电脑上的文件操作进行说明,毕竟看到本博客内容的同学大多数都是使用的 Windows 电脑。

文件夹和文件路径

文件和文件夹就不用说了吧,你想要学习编程肯定离不开电脑,对电脑文件和文件夹已经比较熟悉了,但是文件路径可能就不太清楚了,本文开篇先介绍一下文件路径相关问题。

打开你的电脑上任一文件夹,在上图所示位置发现的一个地址就是文件路径,对于电脑上任一文件都可以用文件路径+文件名访问到。

C:\Users\Administrator\Desktop\书籍封面\abc.png

除了最后的是文件名以外,前面的就是文件路径。
例如对于 abc.png 文件,它的文件路径是 C:\Users\Administrator\Desktop\书籍封面。文件路径可称作文件目录或者文件所在文件夹

绝对路径和相对路径

标题的这两个概念很有意思,在第一次学习的时候很容易就弄迷糊了。
先记住绝对路径吧,绝对就是绝对不变的意思。

例如上述文件 abc.png 它的绝对路径就是硬盘上的一个不会变的地址,即 C:\Users\Administrator\Desktop\书籍封面 就是它的绝对路径。

一般情况下理解为绝对路径是从根目录开始描述的路径。

相对路径,关键词是相对,相对就是相对与当前目录,这个需要结合案例进行学习,稍后补充。

还有两个知识点需要补充一下。. 没错,就是一个点,表示的是当前文件夹;.. 两个点表示的是上一层文件夹。

怎么用

os 模块与 os.path 模块

在 Python 中操作文件路径,使用 os 模块,os.path 模块是 os 模块内部的一个子模块,首先导入该模块。

import os

获取当前 Python 文件的目录

getcwd 方法可以获取当前 Python 文件所在的工作目录,就是当前文件在那个文件夹中,获取到的是绝对地址,例如下述代码。

import os
print(os.getcwd())

获取绝对路径 os.path.abspath

os.path 模块中的 abspath 方法可以返回绝对路径,可以先通过 help 函数,查看该方法使用方式。

import os

help(os.path.abspath)

注意学习返回结果,学编程对英语要求不高,但是常见的单词还是要认识一些的。

Help on function abspath in module ntpath:

abspath(path)
    Return the absolute version of a path.

abspath 方法需要一个参数 path,即一个路径,基于该路径在返回绝对路径。

例如通过该代码返回 demo4.py 文件的绝对路径

import os

ret = os.path.abspath("demo4.py")
print(ret)

绝对路径返回的是一个从根目录开始的路径值,但是相对路径不一样,该方法既然叫做相对,那需要有一个相对对象,所以该方法的语法格式如下:

os.path.relpath(path,start)
  • path 就是要获取绝对路径的地址值,描述起来比较绕,一会看代码;
  • start 相对的对象值。
import os

ret = os.path.relpath("D:\\")
print(ret)

获取 D:\\ 该目录的相对地址,相对于谁的地址,没写 start 参数就相对于当前工作目录,即 Python 文件所在的目录,你已经知道当前 Python 文件所在的目录是 D:/gun/2

先认为的推断一下 D:\\ 相对于 D:/gun/2 怎么获取,应该是父级目录的父级目录,那用代码怎么表示,已经学习了父级(上一层文件夹)目录表示方式 ..,所以写作 ..\.. ,整理完逻辑之后,发现跟代码得到的效果一致。

..\..

将 path 参数修改为跟 Python 文件目录一致的值,看一下是不是得到相对路径是一个 .,表示当前目录。

import os

ret = os.path.relpath("d:\\gun\\2")
# 或者写成下面这个样子
# ret = os.path.relpath("d:/gun/2")
print(ret)

结果输出为 . ,没错是期望值。

学起来如果吃力,不要急,接着往下看,慢慢你就悟了。

路径检查方法

检查路径主要是为了检查文件或者文件夹是否存在,或者判断一个路径对应的是一个文件夹还是一个文件。

  • exists(path) 如果 path 文件或文件夹存在返回 True,否则返回 False;
  • isabs(path) path 是绝对路径返回 True,否则返回 False;
  • isdir(path) path 是文件夹返回 True,否则你懂;
  • isfile(path) path 是文件返回 True。

以上四个方法都在 os.path 模块下,具体代码比较简单,自己尝试一下即可。

目录操作

以下几个方法在 os 模块中,执行如下操作建议先通过 os.path.exists 判断目录是否存在。

  • mkdir(path) 创建目录;
  • rmdir(path) 删除目录;
  • chdir(path) 切换当前工作目录到 path;
  • remove(path) 删除文件,注意如果 path 是一个目录,删除会报错,权限不足,删除目录请使用 rmdir

以上四个方法实际编码也非常简单,导入模块之后,用就完了,橡皮擦自己就先不浪费篇幅了。

获取文件大小

该内容只需要调用 getsize 方法即可。

import os
print(os.path.getsize("demo4.py"))

注意得到的是字节大小。

获取指定目录下面的所有内容

通过 os.listdir 方法可以获取指定目录下的所有内容,包括文件与文件夹。

import os
print(os.listdir("."))

输出的内容:

['demo1.py', 'demo2.py', 'demo3.py', 'demo4.py', 'demo5.py', 'dog_module.py', '__pycache__']

可以与文件进行一下比对。 

os.walk 方法

这个方法比较不好理解,第一次滚雪球阶段还是暂时略过,该方法可以遍历目录树,通过循环就可以获取到指定目录下面所有的文件与文件夹了,但是咱不学 (^_−)☆

Python 读取文件

Python 在读写文件的时候首先要做的是打开文件,然后可以一次性读取文件或者一行行的读取,打开文件使用 open 函数。

读取文件所有内容

使用 open 函数打开文件之后,可以通过 read 读取文件内容,该方法相当于将文件的内容一次性的读取到了程序的一个字符串中,非常强大。

test.txt 文件内容

梦想橡皮擦
是一个大佬
真的是一个大佬
我自己都信了

读取代码如下:

# 文件地址,注意提前在当前目录新建一个 test.txt 文件
file = "test.txt"
# 打开文件
f = open(file, encoding="utf-8")
# 读取文件全部内容
read_str = f.read()
# 关闭文件
f.close()
print(read_str)

第一点需要注意的是使用 open 打开文件时,必须在文件使用完毕之后通过 close 关闭文件。
第二点需要注意,上述代码中 file = "test.txt" 该文件名并不是一个完整的路径,这种情况下表示该文件和当前的 Python 文件在一个目录,如果在不同目录,需要用到前文讲到的路径相关知识了。

例如,在上一级目录 ../test.txt

上述代码如果运行出现编码 BUG,注意修改以下 open 函数部分代码,通过 encoding = “utf-8” 设置文件打开时的编码。

# 打开文件
f = open(file, encoding="utf-8")

逐行读取文件内容

通过循环调用文件对象,可以逐行输出文件内容。

# 文件名
file = "test.txt"
# 打开文件
f = open(file, encoding="utf-8")
# 循环逐行读取
for line in f:
	print(line)
# 关闭文件
f.close()

输出的内容如下图所示。 

在这里逐行读取多了一个换行,原因是在 txt 文件中,每行的末尾默认有一个换行,print 函数输出也会带一个换行,所以出现 2 个回车符,解决办法,可以使用 print 函数的第二个参数。

# 文件名
file = "test.txt"
# 打开文件
f = open(file, encoding="utf-8")
# 循环逐行读取
for line in f:
	print(line,end="")
# 关闭文件
f.close()

逐行读取方法 readlines

使用 readlines 方法可以将数据一次性读取到一个列表中,例如下述代码。

# 文件名
file = "test.txt"
# 打开文件
f = open(file, encoding="utf-8")
# 逐行读取
data = f.readlines()
# 关闭文件
f.close()

print(data)

输出内容中,可以看到每行读取到的字符串都带一个 \n 换行符。

['梦想橡皮擦\n', '是一个大佬\n', '真的是一个大佬\n', '我自己都信了']

with 上下文

在 Python 中为了防止忘记打开文件之后,在进行关闭,提供了一个 with 关键词解决该问题,语法格式如下:

with open(待打开文件) as 文件对象:
	文件操作代码块

有了该语法之后,前文的代码可以修改为:

file = "test.txt"
# 打开文件
with open(file,encoding="utf-8") as f:
    # 读取文件全部内容
    read_str = f.read()
    print(read_str)

读取文件还包含其它的几个方法,可以自行尝试。

写入文件

写入文件,泛指写入到本地硬盘上。

在学习写入文件之前,需要先扩展一下 open 函数,该函数目前已经掌握 2 个参数,第一个是操作的文件,第二个是文件的编码 encoding,在补充一个文件打开模式 mode 参数,open 函数中该参数的默认值是 r ,代码写作 open("text.txt",mode="r",encoding="utf-8") 表示以只读的方式打开文件,如果想要向文件中写入内容,需要将 mode 参数设置为 w。关于 mode 参数还有其它值,不要着急,后续会学习到,先记住 2 个即可。

文件写内容的语法格式为:

文件对象.write(待写入内容)

具体案例代码:

# 文件地址,注意提前在当前目录新建一个 test.txt 文件
file = "test.txt"
# 打开文件
with open(file, mode="w", encoding="utf-8") as f:
    # 写入文件内容
    f.write("我是即将被写入的内容")

注意,待写入的内容需为字符串类型,其它类型写入会报错。该种方式写入内容之后,原内容会被覆盖,如果想要在文件中追加数据,用到的是 mode = a

写入多行数据
通过 write 方法可以写入单行数据,如果想要写入多行数据,可以在 with 代码块中,写上多个 write 方法即可。注意 write 方法默认在行尾不添加换行符,如果希望加上换行符,需手动添加。 

例如下述代码:

file = "test.txt"
# 打开文件
with open(file, mode="w", encoding="utf-8") as f:
    # 写入文件内容
    f.write("我是即将被写入的内容\n")
    f.write("我是即将被写入的内容")
文件复制

使用该模块中 shutil 对象的 copy 方法可以对文件进行复制操作。

shutil.copy(旧文件,新文件)

书写成真实代码如下:

import shutil

shutil.copy("test.txt","aaa.txt")
shutil.copy("test.txt","../aaa.txt") # 不同目录拷贝
目录复制

copytree 方法语法格式与 copy 一致,只不过该方法是用来复制目录的,如果目录下面有子目录或文件一起复制。

import shutil
# 第一个参数是旧目录,第二个参数是新目录
shutil.copytree("../1","a4")

执行代码时,需要确定新目录不存在,如果存在会报错。

多用的 move 方法

使用 move 方法可以移动文件。

shutil.move(旧文件,新文件)

移动文件一定要确保旧文件存在,移动之后旧文件将移动到新文件位置。

使用 move 方法可以修改文件名,在移动文件的过程中,如果新旧文件名称不一致,可实现移动文件并重命名的效果。

使用 move 方法还可以移动目录,移动目录时会将该目录下的所有文件一起移动。当然如果新旧目录名称不一致,还可以实现移动目录并重命名的效果。

删除有数据的目录

使用 rmtree 可以删除有数据的目录,相当于直接清空该目录下的所有目录和文件,再顺便把该目录也删除了。具体内容自行测试即可。

文件模块扩展知识

zipFile 模块

通过该模块可以直接对文件进行压缩与解压操作。后续滚雪球中将补充该部分知识。

认识编码

在本篇博客中主要涉及编码的地方就是 open 函数中的 encoding 参数,我们将该参数的值设置为了 utf-8,在很多程序中设置为该值可以解决很多潜在的编码 BUG。

本部分内容展开讲解会占用很大篇幅,这里只说明以下几点知识。

  1. UTF-8 这几个字母的写法你要记住,大小写都可以;
  2. UTF-8 中有个 BOM 文件头,这里不细说,如果发现 UTF-8 解决不了编码问题,那就设置为 utf-8-sig 尝试解决。

Python 标准库是什么

Python 语言提供了非常庞大的组件,本文的呈现方式为罗列,为你描述和提供常用组件,以及其核心用途。

这些标准库很多都是用 C 语言进行编写,所以执行效率都非常高。

常用标准库清单如下

  1. sys
  2. os
  3. math
  4. random
  5. pikle
  6. subprocess
  7. queue
  8. StringIO
  9. logging
  10. json
  11. time
  12. datetime
  13. re
  14. csv
  15. threading
  16. asyncio

怎么用 

sys

sys 模块用于处理 Python 解析器相关的变量和方法,例如获取命令行参数,退出 Python 程序,获取输入输出相关内容。

os

os 模块,即系统模块,它提供了用于访问操作系统相关的功能,os 模块中的接口有些是特定平台使用的,所以要特殊记忆。

主要功能

  • 系统相关 API
  • 目录和文件操作
  • 执行命令
  • 管理进程
math

math 模块提供了对 C 标准定义的数学函数,但是这些函数不适用于复数,常用的有 ceil()floor()abs()sin() 等方法。

一些常量,例如 math.pi ,出场率极高。

random

random 模块用于生成伪随机数,伪随机数是由随机种子根据算法计算而来,处理一些简单的逻辑随机数,可以直接使用该模块。

pikle

该模块是 Python 中用于数据持久化的模块,可以持久化各种类型的数据,该模块持久化的数据无法直接读取,并且仅能在 Python 代码中进行读取。

subprocess

该模块主要用于进程操作,你可以使用它执行操作系统级别的命令,学习的时候优先掌握 run() 方法,使用其创建子进程,操作系统命令。

queue

队列模块,用于将数据存放在内存中,并进行数据交换。

StringIO

StringIO 模块,可以将字符串存储在内存中,然后像操作文件一样操作

logging

日志模块。

json

操作 JSON 格式数据的模块。

time 和 datetime

时间模块,time 模块目前只支持到 2038 年前,如果超过这个时间,使用 datetime 模块。

re

正则表达式处理模块。

csv

csv 文件操作模块。

threading

多线程模块,非常重要和高级的模块。

asyncio

异步 I/O 模块。

time、datetime 时间模块,calendar 日历模块 实战举例

接下来我们介绍一些典型的标准库,从日期时间库开始。

在 Python 中是没有原生数据类型支持时间的,日期与时间的操作需要借助三个模块,分别是 timedatetimecalendar

time 模块可以操作 C 语言库中的时间相关函数,时钟时间与处理器运行时间都可以获取。
datetime 模块提供了日期与时间的高级接口。
calendar 模块为通用日历相关函数,用于创建数周、数月、数年的周期性事件。

在学习之前,还有一些术语要补充一下,这些术语你当成惯例即可。这里在 Python 官方文档中也有相关说明,不过信息比较多,橡皮擦为你摘录必须知道的一部分。

epoch(纪元) 是时间开始的点,其值取决于平台。
对于 Unix, epoch(纪元) 是 1970年1月1日00:00:00(UTC)。要找出给定平台上的 epoch ,请使用 time.gmtime(0) 进行查看,例如橡皮擦电脑显示:

time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)

术语 纪元秒数 是指自 epoch (纪元)时间点以来经过的总秒数,通常不包括闰秒。 在所有符合 POSIX 标准的平台上,闰秒都不会记录在总秒数中。 

程序员中常把 纪元秒数 称为 时间戳。 

get_clock_info 函数

该函数获取时钟的基本信息,得到的值因不同系统存在差异,函数原型比较简单:

time.get_clock_info(name)

其中 name 可以取下述值:

  • monotonic:time.monotonic()
  • perf_counter: time.perf_counter()
  • process_time: time.process_time()
  • thread_time: time.thread_time()
  • time: time.time()

该函数的返回值具有以下属性:

  • adjustable : 返回 True 或者 False。如果时钟可以自动更改(例如通过 NTP 守护程序)或由系统管理员手动更改,则为 True ,否则为 False ;
  • implementation : 用于获取时钟值的基础 C 函数的名称,就是调用底层 C 的函数;
  • monotonic :如果时钟不能倒退,则为 True ,否则为 False;
  • resolution : 以秒为单位的时钟分辨率( float )。

import time available_clocks = [ ('clock', time.clock), ('monotonic', time.monotonic), ('perf_counter', time.perf_counter), ('process_time', time.process_time), ('time', time.time), ] for clock_name, func in available_clocks: print(''' {name}: adjustable : {info.adjustable} implementation: {info.implementation} monotonic : {info.monotonic} resolution : {info.resolution} current : {current} '''.format( name=clock_name, info=time.get_clock_info(clock_name), current=func())) 

运行结果如下图所示。

上图显示橡皮擦的计算机在 clock 与 perf_counter 中,调用底层 C 函数是一致的。 

获取时间戳

在 Python 中通过 time.time() 函数获取纪元秒数,它可以把从 epoch 开始之后的秒数以浮点数格式返回。

import time
print(time.time())
# 输出结果 1615257195.558105

时间戳大量用于计算时间相关程序,属于必须掌握内容。

获取可读时间

时间戳主要用于时间上的方便计算,对于人们阅读是比较难理解的,如果希望获取可读时间,使用 ctime() 函数获取。

import time
print(time.ctime())
# 输出内容:Tue Mar  9 10:35:51 2021

如何将时间戳转换为可读时间,使用 localtime 函数即可。

localtime = time.localtime(time.time())
print("本地时间为 :", localtime)

输出结果为 <class 'time.struct_time'> 类型数据,后文将对其进行格式化操作:

本地时间为 : time.struct_time(tm_year=2021, tm_mon=3, tm_mday=9, tm_hour=10, tm_min=37, tm_sec=27, tm_wday=1, tm_yday=68, tm_isdst=0)

上述代码中的时间戳最小值是 0,最大值由于 Python 环境和操作系统决定,我本地 64 位操作系统进行测试的时候,得到的数据如下:

import time

localtime = time.localtime(0)
print("时间为 :", localtime)
# 时间为 : time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)
localtime = time.localtime(32536799999)
print("时间为 :", localtime)
# 时间为 : time.struct_time(tm_year=3001, tm_mon=1, tm_mday=19, tm_hour=15, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=19, tm_isdst=0)
localtime = time.localtime(99999999999)
print("时间为 :", localtime)
# OSError: [Errno 22] Invalid argument
print(type(localtime))
单调时间 monotonic time

monotonic time 从系统启动开始计时,从 0 开始单调递增。

操作系统的时间可能不是从 0 开始,而且会因为时间出错而回调。

该函数原型如下,不需要任何参数,返回一个浮点数,表示小数秒内的单调时钟的值:

time.monotonic()

测试代码如下:

print("单调时间",time.monotonic())
# 输出:单调时间 12279.244
处理器时钟时间

time() 函数返回的是纪元秒数(时间戳), clock() 函数返回的是处理器时钟时间。
该函数函数的返回值:

  • 在第一次调用的时候,返回的是程序运行的实际时间;
  • 在第二次之后的调用,返回的是自第一次调用后到这次调用的时间间隔。

需要注意的是 Python 3.8 已移除 clock() 函数,用 time.perf_counter() 或 time.process_time() 方法替代。

t0 = time.clock()
# 运行一段代码
print(time.clock() - t0, "程序运行时间")

我使用的 Python 版本较高,提示异常如下:

time.clock has been deprecated in Python 3.3 and will be removed from Python 3.8: use time.perf_counter or time.process_time instead t0 = time.clock()
性能计数器 time.perf_counter

perf_counter() 函数的 epoch (纪元)是未定义的。一般使用该函数都是为了比较和计算,不是为了用作绝对时间,该点需要注意下。

该函数用于测量较短持续时间的具有最高有效精度的时钟,包括睡眠状态消耗的时间,使用两次调用才会有效。

测试代码如下:

t0 = time.perf_counter()
# 运行一段代码
for i in range(100000):
    pass
print("程序运行时间", time.perf_counter() - t0)

与其类似的函数有 perf_counter_ns()process_time()process_time_ns(),具体可以查询手册进行学习,先掌握 perf_counter() 函数即可。

时间组件

上文已经涉及了时间组件相关的知识,通过 localtime 得到的 struct_time 类型的数据。

这里涉及到的函数有 gmtime() 返回 UTC 中的当前时间,localtime() 返回当前时区对应的时间,mktime() 接收 struce_time 类型数据并将其转换成浮点型数值,即时间戳。

print("*"*10)
print(time.gmtime())
print("*"*10)
print(time.localtime())

print("*"*10)
print(time.mktime(time.localtime()))

struct_time 类型包含的内容

上述代码返回的数据格式为:

time.struct_time(tm_year=2021, tm_mon=3, tm_mday=9, tm_hour=12, tm_min=50, tm_sec=35, tm_wday=1, tm_yday=68, tm_isdst=0)

其中各值可以根据英文含义进行理解 :tm_year 年份(range[1,12]),tm_mon 月份(range[1,12]),tm_mday 天数(range[1,31]),tm_hour 天数(range[0,23]),tm_min 分钟 (range[0,59]), tm_sec 秒数 (range[0,61]), tm_wday 星期 (range[0,6],0 是星期日), tm_yday 一年中的一天(range[1,366] ),tm_isdst 在夏令时生效时设置为 1,而在夏令时不生效时设置为 0,值-1 表示这是未知的。

解析和格式化时间

strptime() 和 strftime() 函数可以使时间值在 struct_time 表示和字符串表示之间相互转换。

对于 strftime 函数,其中的参数参考官方即可。

x = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(x)

这里的学习,没有什么难度大的点,孰能生巧的知识。

strptime 函数的应用

x = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(x)
# 方向操作,字符串格式化成 time.struct_time
struct_time = time.strptime(x, "%Y-%m-%d %H:%M:%S")
print(struct_time)

需要记忆的就是 strftime 与 strptime 函数只有中间的字符不同,一个是 f ,另一个是 p

datetime 模块

该模块比 time 模块高级了很多,并且对 time 模块进行了封装,提供的功能更加强大了。

在 datetime 模块中,Python 提供了 5 个主要的对象类,分别如下:

  • datetime:允许同时操作时间和日期;
  • date:只操作日期;
  • time:只操作时间;
  • timedelta:用于操作日期以及测量时间跨度;
  • tzinfo:处理时区。
date 类

优先展示部分该类的属性和方法,都是记忆层面的知识。

  • minmax:date 对象能表示的最大、最小日期;
  • resolution:date 对象表示日期的最小单位,返回天;
  • today():返回表示当前本地日期的 date 对象;
  • fromtimestamp(timestamp):根据时间戳,返回一个 date 对象。

测试代码如下:

from datetime import date
import time
print('date.min:', date.min)
print('date.max:', date.max)
print('date.resolution:', date.resolution)
print('date.today():', date.today())
print('date.fromtimestamp():', date.fromtimestamp(time.time()))

输出结果:

date.min: 0001-01-01
date.max: 9999-12-31
date.resolution: 1 day, 0:00:00
date.today(): 2021-03-09
date.fromtimestamp(): 2021-03-09

date 对象的属性和方法

通过下述代码创建一个 date 对象:

d = date(year=2021,month=3,day=9)
print(d)

该对象具备下述属性和方法:

  • d.year:返回年;
  • d.month:返回月;
  • d.day:返回日;
  • d.weekday():返回 weekday,如果是星期一,返回 0;如果是星期 2,返回 1,以此类推;
  • d.isoweekday():返回 weekday,如果是星期一,返回 1;如果是星期 2,返回 2,以此类推;
  • d.isocalendar():返回格式如(year, wk num, wk day);
  • d.isoformat():返回格式如’YYYY-MM-DD’的字符串;
  • d.strftime(fmt):自定义格式化字符串,与 time 模块中的 strftime 类似。
time 类

time 类定义的类属性:

  • minmax:time 类所能表示的最小、最大时间。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999)
  • resolution:时间的最小单位,这里是 1 微秒;

通过其构造函数可以创建一个 time 对象。

t = time(hour=20, minute=20, second=40)
print(t)

time 类提供的实例方法和属性:

  • t.hourt.minutet.secondt.microsecond:时、分、秒、微秒;
  • t.tzinfo:时区信息;
  • t.isoformat():返回型如”HH:MM:SS”格式的字符串时间表示;
  • t.strftime(fmt):返回自定义格式化字符串。
datetime 类

该类是 date 类与 time 类的结合体,很多属性和方法前文已经介绍,再补充一些比较常用的属性和方法。

获取当前的日期与时间:

from datetime import datetime
dt = datetime.now()
print(dt)

获取时间戳:

dt = datetime.now()
# 使用 datetime 的内置函数 timestamp()
stamp = datetime.timestamp(dt)
print(stamp)
timedelta 类

通过 timedelta 函数返回一个 timedelta 时间间隔对象,该函数没有必填参数,如果写入一个整数就是间隔多少天的的意思。

# 间隔 10 天
timedelta(10)
# 跨度为1 周
timedelta(weeks=1)

两个时间间隔对象可以彼此之间相加或相减,返回的仍是一个时间间隔对象。
一个 datetime 对象如果减去一个时间间隔对象,那么返回的对应减去之后的 datetime 对象,然后两个 datetime 对象如果相减,返回的是一个时间间隔对象。

更多关于 datetime 类使用的知识,可以参考 官方手册

calendar 模块(日历)

此模块的函数都是日历相关的,例如打印某月的字符月历。

calendar 模块定义了 Calendar 类,它封装了值的计算, 例如给定月份或年份中周的日期。通过 TextCalendar 和 HTMLCalendar 类可以生成预格式化的输出。

基本代码:

import calendar

c = calendar.TextCalendar(calendar.SUNDAY)
c.prmonth(2021, 3)

上述代码,默认是从周日开始的,输出结果:

     March 2021
Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6
 7  8  9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

random 随机函数模块

seed 与 random 函数

seed 函数初始化一个随机种子,默认是当前系统时间。
random 函数 生成一个 [0.0,1.0) 之间的随机小数 。

具体代码如下:

import random

random.seed(10)

x = random.random()
print(x)

其中需要说明的是 random.seed 函数, 通过 seed 函数 可以每次生成相同的随机数,例如下述代码:

import random

random.seed(10)
x = random.random()
print(x)

random.seed(10)
y = random.random()
print(y)

在不同的代码上获取到的值是不同的,但是 x 与 y 是相同的。

0.5714025946899135
0.5714025946899135
getstate() 和 setstate(state)

getstate 函数用来记录随机数生成器的状态,setstate 函数用来将生成器恢复到上次记录的状态。

# 记录生成器的状态
state_tuple = random.getstate()
for i in range(4):
    print(random.random())
print("*"*10)
# 传入参数后恢复之前状态
random.setstate(state_tuple)
for j in range(4):
    print(random.random())

输出的随机数两次一致。

0.10043296140791758
0.6183668665504062
0.6964328590693109
0.6702494141830372
**********
0.10043296140791758
0.6183668665504062
0.6964328590693109
0.6702494141830372
randint 和 randrange

randint 生成一个 [x,y] 区间之内的整数。
randrange 生成一个 [m,n) 区间之内以 k 为步长的随机整数。

测试代码如下:

x = random.randint(1,10)
print(x)

y = random.randrange(1,10,2)
print(y)

这两个函数比较简单,randint 函数原型如下:

random.randint(start,stop)

参数 start 表示最小值,参数 stop 表示最大值,两头都是闭区间,也就是 start 和 stop 都能被获取到。

randrange 函数原型如下:

random.randrange(start,stop,step)

如果函数调用时只有一个参数,默认是从 0 到该参数值,该函数与 randint 区别在于,函数是左闭右开,最后一个参数是步长。

查阅效果,可以复制下述代码运行:

for i in range(3): print("*"*20) print(random.randrange(10)) print(random.randrange(5,10)) print(random.randrange(5,100,5)) 

getrandbits(k) 和 choice(seq)

getrandbits 生成一个 k 比特长的随机整数,实际输出的是 k 位二进制数转换成的十进制数。
choice 从序列中随机选择一个元素。

x =  random.getrandbits(5)
print(x)
# 生成的长度是 00000-11111

getrandbits(k) 函数可以简单描述如下:输出一个 [ 0 , 2 k − 1 ] [0,2^k-1] [0,2k−1] 范围内一个随机整数,k 表示的是 2 进制的位数。

choice 就比较简单了,从列表中返回一个随机元素。

import random

my_list = ["a", "b", "c"]

print(random.choice(my_list))
shuffle(seq) 和 sample(pop,k)

shuffle 函数用于将序列中的元素随机排序,并且原序列被修改。
sample 函数用于从序列或者集合中随机选择 k 个选择,原序列不变。

my_list = [1,2,3,4,5,6,7,8,9]
random.shuffle(my_list)

print(my_list)

shuffle 函数只能用于可变序列,不可变序列(如元组)会出现错误。

my_list = ["梦想", "橡皮擦", 1, 2, [3, 4]]
print(my_list)
ls = random.sample(my_list, 4)
print(ls)
uniform(a,b) 、betavariate 和 triangular 函数

uniform 生成一个 [a,b] 之间的随机小数,采用等概率分布。
betavariate 生成一个 [0,1] 之间的随机小数,采用 beta 分布。
triangular 生成一个 [low,high] 之间的随机小数,采用三角分布。

在使用 uniform 时候需要注意,如果 a<b,那么生成一个 b-a 之间的小数。

for i in range(3):
    print(random.uniform(4, 1))
其它分布随机函数

以下都是生成随机数的方法,只是底层核心算法不同。
、、、、、、、。

  1. expovariate:生成一个 (0,∞) 之间的随机整数,指数分布;
  2. gammavariate:采用 gamma 分布;
  3. gauss:采用高斯(正太)分布;
  4. lognormvariate:对数正太分布;
  5. normalvariate:正太分布;
  6. vonmisesvariate:冯米赛斯分布;
  7. paretovariate:帕累托分布;
  8. weibullvariate:韦伯分布。

os 库

在 Python 中 os 库提供了基本的操作系统交互功能,该库下包含大量与文件系统、操作系统相关的函数,通过 dir 函数可以查看。

这些函数主要分为几类。

  1. 路径操作:os.path 子库,处理文件路径及信息;
  2. 进程管理:启动系统中其它程序;
  3. 环境参数:获得系统软硬件信息等环境参数。
os 库路径操作

os.path 在 os 库中用于提供操作和处理文件路径相关函数,常见的函数清单如下:

os.path.abspath(path)返回绝对路径
os.path.normpath(path)规范 path 字符串形式
os.path.realpath(path)返回 path 的真实路径
os.path.dirname(path)返回文件路径
os.path.basename(path)返回文件名
os.path.join(path1[, path2[, …]])把目录和文件名合成一个路径
os.path.exists(path)如果路径 path 存在,返回 True;如果路径 path 不存在,返回 False。
os.path.isfile(path)判断路径是否为文件
os.path.isdir(path)判断路径是否为目录
os.path.getatime(path)返回最近访问时间(浮点型秒数)
os.path.getmtime(path)返回最近文件修改时间
os.path.getsize(path)返回文件大小,如果文件不存在就返回错误

以上函数的使用过程比较容易理解,导入模块之后,调用即可。

模块导入使用下述方式:

import os.path
# import os.path as op
variate = os.path.abspath(__file__)
print(variate)

函数的参数都是 path,在传入的时候,特备要注意原生字符串的应用,还有要区分绝对路径和相对路径的问题。

由于 path 相关的库比较简单,每个内容都尝试一遍即可掌握,其它内容可以在 手册 进行学习。

os 库进程管理

该内容主要用于在 Python 中执行程序或命令 Command,函数原型为:

os.system(command)

例如,在 Python 中唤醒画板程序。

os.system("c:\windows/system32/mspaint.exe")

除了 system 函数以外,还有一个 os.exec 函数族相关知识。具体可以查看下述函数的用法:

os.execl(path, arg0, arg1, …)
os.execle(path, arg0, arg1, …, env)
os.execlp(file, arg0, arg1, …)
os.execlpe(file, arg0, arg1, …, env)
os.execv(path, args)
os.execve(path, args, env)
os.execvp(file, args)
os.execvpe(file, args, env)

这些函数都将执行一个新程序,以替换当前进程。

os 库运行环境相关参数

环境参数顾名思义就是改变系统环境信息,或者理解为 Python 运行环境相关信息。

通过下述属性,可以获取环境变量:

os.environ

如果希望获取操作系统类型,使用 os.name,目前只有 3 个值:分别是 posix , nt , java

函数部分,主要掌握的函数有:

  • os.chdir(path):修改当前程序操作的路径;
  • os.getcwd():返回程序运行的路径;
  • os.getlogin():获取当前登录用户名称;
  • os.cpu_count():获得当前系统的 CPU 数量;
  • os.urandom(n):返回一个有 n 个 byte 长的一个随机字符串,用于加密运算。

sys 库

该库主要维护一些与 Python 解释器相关的参数变量和方法。

常见属性如下

sys.argv
获取命令行参数列表,第一个元素是程序本身。

使用方式如下:

import sys
print(sys.argv)

接下来通过控制台运行 python 程序时,需要携带参数,下述代码 312.py 是 python 文件名,123 是后缀的参数。

python 312.py 1 2 3

执行程序之后,得到的结果为:

['312.py', '1', '2', '3']

第一个是文件名,后面依次是传递进来的参数。

sys.platform
获取 Python 运行平台的信息,结果比 os.name 要准确。

sys.path
获取 PYTHONPATH 环境变量的值,一般用作模块搜索路径。

import sys
print(sys.path)

sys.modules
以字典的形式获取所有当前 Python 环境中已经导入的模块。

sys.stdin,sys.stdout,sys.stderr
sys.stdin , sys.stdout ,sys.stderr 变量包含与标准 I/O 流对应的流对象。

import sys

# 标准输出, sys.stdout.write() 的形式就是 print() 不加'\n' 的形式。
sys.stdout.write("hello")
sys.stdout.write("world")

sys.stdin 标准输入,等价于 input

sys.ps1 和 sys.ps2
指定解释器的首要和次要提示符。仅当解释器处于交互模式时,它们才有定义。具体测试如下:

PS > python
Python 3.7.3 (v3.7.3:xxxxxx, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps1 = "***"
***print("hello")
hello
常见方法如下

**sys.exit(n) **
退出 Python 程序,exit(0)表示正常退出。
当参数非 0 时,会引发一个 SystemExit 异常,可以在程序中捕获该异常。参数也可以称为状态码。

sys.getdefaultencoding()、sys.setdefaultencoding() 、sys.getfilesystemencoding()

  • sys.getdefaultencoding():获取系统当前编码,有的博客中写默认为 ascii,但是我本地默认为 utf-8
  • sys.setdefaultencoding():设置系统的默认编码;
  • sys.getfilesystemencoding():获取文件系统使用编码方式,默认 utf-8

sys.getrecursionlimit() 、 sys.setrecursionlimit()
获取 Python 的最大递归数目和设置最大递归数目

sys.getswitchinterval()、sys.setswitchinterval(interval)
获取和设置解释器的线程切换间隔时间(单位为秒)

Python 字符编码与解码是什么

在 Python3 中字符默认编码是 Unicode 字符,而编码指的是将字符转换成字节流,解码是相反的操作。

在正式开始前,我们还需要梳理一些基本概念

Python 中的字符串

计算机中 8 比特(bit)等于一个字节(byte),8 比特就是 8 位,即一个字节能表示的最大整数是 255(1111 1111)。

如果希望扩大整数范围,需要用到更多的字节,例如 2 个字节就可以表示 65535,4 个字节就能表示 4294967295。

基于上述原理出现了各种编码格式,例如 ASCII 可以表示 256 个字符,但仅支持英文字母,数字和少部分符号,中文的范围要大很多,所以出现了 GB2312 编码(后来升级到了 GBK 编码),可以容纳 6763 个汉字,但放眼世界还不够,还需要更多的字符。

此时 Unicode 字符集就出现了,它将所有的语言都容纳在一起,后续为了在存储和传输数据时节省空间,出现了 UTF8 编码。

怎么用

Python 编码基本使用

通过 ord() 函数获取字符的整数表示,通过 chr() 将整数转换为字符,例如下述代码

print(ord('爬')) # 29228
print(chr(29228))

既然知道数字可以转换为数字,那十进制和十六进制的数字都可以。

例如 29228 = 722c,所以 \u722c

print(chr(int('722c', 16)))

Python 编码和解码函数

encode() 和 decode() 分别对应编码和解码函数,en 是编码,de 是解码。

my_b = '技能树'.encode('utf-8')
print('编码后',my_b) # 编码后 b'\xe6\x8a\x80\xe8\x83\xbd\xe6\xa0\x91'

解码操作如下所示:

my_b = '技能树'.encode('utf-8')
print('编码后', my_b)  # 编码后 b'\xe6\x8a\x80\xe8\x83\xbd\xe6\xa0\x91'

my_str = my_b.decode('utf-8')
print("解码后", my_str)

需要注意编码后输出的内容与字符串类似,就是前面有一个前缀 b。 

乱码

如果编码和解码方法不一致,就会出现乱码问题,例如下述代码

my_b = '技能树'.encode('gbk')
print('编码后', my_b)  # 编码后 b'\xbc\xbc\xc4\xdc\xca\xf7'

my_str = my_b.decode('utf-8')
print("解码后", my_str)

出错信息如下所示:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 0: invalid start byte

当出现上述类型的错误时,需要做的就是寻找到正确的原编码,然后进行处理。 

参考资料:文件-进阶语法-CSDNPython入门技能树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值