一、标准库 datetime
1.1 datetime
模块
- 对日期、时间、时间戳的处理
1.2 datetime
类
- 类方法
a.today()
返回本地时区当前时间的datetime
对象
b.now(tz=None)
返回当前时间的datetime
对象,精确至微秒,若tz
为None
,返回同today()
c.utcnow()
没有时区的当前时间
d.fromtimestamp(timestamp, tz=None)
从一个时间戳返回一个datetime
对象
1.3 datetime
对象
-
timestamp()
返回一个到微秒的时间戳
a. 时间戳:格林威治时间 1970 年 1 月 1 日 0 点到现在的秒数 -
构造方法
datetime.datetime(2020, 12, 6, 16, 29, 43, 79043)
-
year
、month
、day
、hour
、minute
、second
、microsecond
,取datetime
对象的年月日时分秒及微秒 -
weekday()
返回周几,周一为0
,周日为6
-
isoweekday()
返回周几,周一为1
,周日为7
-
date()
返回日期date
对象 -
time()
返回时间time
对象 -
replace()
修改并返回新的时间 -
isocalendar(0
返回一个三元组(年,周数,周几)
1.4 日期格式化
-
类方法
strptime(date_string, format)
,返回datetime
对象 -
对象方法
strftime(format)
,返回字符串 -
字符串
format
函数格式化
import datetime
dt = datetime.datetime.strptime("08/12/20 16:30", "%d/%m/%y %H:%M")
print(dt.strftime("%Y-%m-%d %H:%M:%S"))
print("{0:%Y}/{0:%m}/{0:%d} {0:%H}::{0:%H}::{0:%S}".format(dt))
print('{:%Y-%m-%d %H:%M:%S}'.format(dt))
示例.png
1.5 timedelta
对象
datetime2 = datetime1 + timedelta
datetime2 = datetime1 - timedelta
timedelta = datetime1 - datetime2
- 构造方法
a.datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
b.year = datetime.timedelta(days=365)
-
total_seconds()
返回时间差的总秒数
二、标准库 time
2.1 time
-
time.sleep(secs)
将调用线程挂起指定的秒数
三、列表解析
3.1 举例
- 生成一个列表,元素 0 ~ 9,对每一个元素自增 1 后求平方返回新列表
lst = list(range(10))
newlst = list()
for i in lst:
newlst.append((i+1) ** 2)
print(newlst)
lst = list(range(10))
newlst = [ (i + 1) ** 2 for i in lst]
print(newlst)
示例.png
3.2 语法
[ 返回值 for 元素 in 可迭代对象 if 条件]
- 使用中括号
[]
,内部是for
循环,if
条件语句可选 - 返回一个新列表
3.3 列表解析式是一种语法糖
- 编译器会优化,不会因为简写而影响效率,反而因优化提高了效率
- 减少程序员工作量,减少出错
- 简化了代码,但可读性增强
3.4 举例
- 获取 10 以内的偶数,比较执行效率
even = []
for i in range(10):
if i % 2 == 0:
even.append(i)
even = [ i for i in range(10) if i % 2 == 0]
示例.png
- 思考
-
有这样的赋值语句
示例.pngnewlist = [print(i) for i in range(10)]
,请问打印出什么?newlist
打印出来是什么?
-
获取 20 以内的偶数,若同时 3 的倍数也打印
示例.png[i for i in range(20) if i % 2 == 0 elif i % 3 ==0]
行么?
-
四、列表解析进阶
4.1 [expr for item in iterable if cond1 if cond2]
- 等价于
ret = []
for item in iterable:
if cond1:
if cond2:
ret.appent(expr)
- 举例
- 20 以内,既能被 2 整除又能被 3 整除的数
[i for i in range(20) if i %2 == 0 and i % 3 == 0] [i for i in range(20) if i 5 2 == 0 if i % 3 == 0]
4.2 [expr for i in iteranle1 for j in iterable2]
- 等价于
ret = []
for i in iterable1:
for j in iterable2:
ret.append(expr)
- 举例
[(x, y) for x in 'abcde' for y in range(3)] [[x, y] for x in 'abcde' for y in range(3)] [{x, y} for x in 'abced' for y in range(3)] # 集合是整个生成列表中的元素,不会去重 [{x: y} for x in 'abced' for y in range(3)] # 字典与集合相同,不会去重
4.4 请问下面 3 中输出各是什么?为什么
[(i,j) for i in range(7) if i>4 for j in range(20,25) if j>23]
[(i,j) for i in range(7) for j in range(20,25) if i>4 if j>23]
[(i,j) for i in range(7) for j in range(20,25) if i>4 and j>23]
示例.png
五、列表解析练习
5.1 练习(要求使用列表解析式完成)
- 返回 1 - 10 平方的列表
[i ** 2 for i in range(11) if i > 0 ]
示例.png
- 有一个列表
lst = [1, 4, 9, 16, 2, 5, 10, 15]
,生成一个新列表,要求新列表元素是lst
相邻 2 项的和
lst = [1, 4, 9, 16, 2, 5, 10, 15]
[lst[i] + lst[i+1] for i in range(len(lst)) if i < (len(lst)-1)]
示例.png
六、生成器表达式 Generator expression
6.1 语法
(返回值 for 元素 in 可迭代对象 if 条件)
- 列表解析式中的括号换成小括号即可
- 返回一个生成器
6.2 和列表解析式的区别
- 生成器表达式是 按需计算(或称 惰性求值、延迟计算),需要的时候才计算值
- 列表解析式是立即返回值
6.3 生成器
- 可迭代对象
- 迭代器
6.4 举例
g = ("{:04}".format(i) for i in range(1,11))
next(g)
for x in g:
print(x)
print('~~~~~~~~~~~~')
for x in g:
print(x)
- 列表对比
g = ["{:04}".format(i) for i in range(1,11)]
for x in g:
print(x)
print('~~~~~~~~~~~~')
for x in g:
print(x)
6.5 总结
-
生成器
- 延迟计算
- 返回迭代器,可迭代
- 从前到后走完一遍,不能回头
-
列表
- 立即计算
- 返回的不是迭代器,返回可迭代对象列表
- 从前导后走完一遍,可重新回头迭代
6.6 习题
it = (print("{}".format(i+1)) for i in range(2))
first = next(it)
second = next(it)
val = first + second
-
val
的值是什么
print() 函数是立即返回,所以不论是 first 还是 second 的值都是 None
所以 val 的运算结果会抛异常
示例
-
val = first + second
语句之后能否再次next(it)
不可以 next() 了,因为此前的计数器是 range(2),程序已经迭代两次,所以不可再次 next()
示例.png
it = (x for x in range(10) if x % 2)
first = next(it)
second = next(it)
val = first + second
-
val
的值是什么?
val 的值为 4
示例.png
-
val = first + second
语句后能否再次next(it)
因为此前计数器并未迭代完,所以可以继续 next() 调用
示例.png
6.7 和列表解析式的对比
- 计算方式
- 生成器表达式延迟计算,列表解析式立即计算
- 内存占用
- 单从返回值本身来说,生成器表达式
- 生成器没有数据,内存占用极少,它是使用时一个个返回数据,若将这些返回的数据合起来占用的内存和列表解析式差不多,但是,它不需要立即占用这么多内存
- 列表解析式构造新的列表需要立即占用内存,不管你是否立即使用这么多数据
- 计算速度
- 但看计算时间,生成器表达式耗时非常短,列表解析式耗时长
- 但生成器本身并没有返回任何值,只返回了一个生成器对象
- 列表解析式构造并返回了一个新的列表,所以开起来耗时了
七、集合解析式
7.1 语法
{ 返回值 for 元素 in 可迭代对象 if 条件 }
- 列表解析式的中括号换成大括号
{}
即可 - 立即返回一个集合
7.2 用法
-
{(x, x+1) for x in range(10)}
-
{[x] for x in range(10)}
八、字典解析式
8.1 语法
{ 返回值 for 元素 in 可迭代对象 if 条件 }
- 列表解析式中的括号换成大括号
{}
即可 - 使用
key:value
形式 - 立即返回一个字典
8.2 用法
{x:(x, x+1) for x in range(10)}
{x:[x, x+1] for x in range(10)}
{(x,):[x, x+1] for x in range(10)}
{[x]:[x, x+1] for x in range(10)}
{chr(0x41 +x):x**2 for x in range(10)}
{str(x):y for x in range(3) for y in range(4)}
- 等价于
ret = {}
for x in range(3):
for y in range(4):
ret[str(x)] = y
九、总结
- Python 2 引入列表解析式
- Python 2.4 引入生成器表达式
- Python 3 引入集合、字典解析式,并迁移至 Python 2.7
- 一般来说,应该多应用解析式,简短、高效
- 若一个解析式非常复杂,难以读懂,可考虑拆解成
for
循环 - 生成器和迭代器是不同的对象,但都是可迭代对象
- 可迭代对象范围更大,都可使用
for
循环遍历
网友评论