贴子主要关于自己的读书摘要,涉及到侵权请联系删除
第一章:数据结构和算法
# 任何的序列(或者是可迭代对象)可以通过一个简单的赋值语句解压并赋值给多
# 个变量。唯一的前提就是变量的数量必须跟序列元素的数量是一样的。
p= (4,5)
x,y = p
print(x,y,end='\n')
# 1.2 解压可迭代对象赋值给多个变量
record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')
name, email, *phone_numbers = record
print(name)
4 5
Dave
星号表达式在迭代元素为可变长元组的序列时是很有用的
records = [
('foo', 1, 2),
('bar', 'hello'),
('foo', 3, 4),
]
def do_foo(x, y):
print('foo', x, y)
def do_bar(s):
print('bar', s)
for tag, *args in records:
if tag == 'foo':
do_foo(*args)
elif tag == 'bar':
do_bar(*args)
foo 1 2
bar hello
foo 3 4
星号解压语法在字符串操作的时候也会很有用,比如字符串的分割
line = 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false'
uname, *fields, homedir, sh = line.split(':')
uname
'nobody'
用这种分割语法去巧妙的实现递归算法
items = [1, 10, 7, 4, 5, 9]
def sum(items):
head, *tail = items
return head + sum(tail) if tail else head
sum(items)
36
1.3 保留最后 N 个元素
1.4 查找最大或最小的 N 个元素
# heapq 模块有两个函数:nlargest() 和 nsmallest() 可以完美解决这个问题。
import heapq
nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
print(heapq.nlargest(3, nums)) # Prints [42, 37, 23]
print(heapq.nsmallest(3, nums)) # Prints [-4, 1, 2]
[42, 37, 23]
[-4, 1, 2]
portfolio = [
{'name': 'IBM', 'shares': 100, 'price': 91.1},
{'name': 'AAPL', 'shares': 50, 'price': 543.22},
{'name': 'FB', 'shares': 200, 'price': 21.09},
{'name': 'HPQ', 'shares': 35, 'price': 31.75},
{'name': 'YHOO', 'shares': 45, 'price': 16.35},
{'name': 'ACME', 'shares': 75, 'price': 115.65}
]
cheap = heapq.nsmallest(3, portfolio, key=lambda a: a['price'])
expensive = heapq.nlargest(3, portfolio, key=lambda a: a['price'])
print("cheap:","\t",cheap,"\n",
"expensive:","\t",expensive)
cheap: [{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
expensive: [{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]
1.6 字典中的键映射多个值
d = {
'a' : [1, 2, 3],
'b' : [4, 5]
}
e = {
'a' : {1, 2, 3},
'b' : {4, 5}
}
from collections import defaultdict
# defaultdict 的一个特征是它会自动初始化每个 key 刚开始对应的值,所以你只需要
# 关注添加元素操作了
a = defaultdict(list)
a['a'].append(1)
a['a'].append(2)
a['b'].append(4)
d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)
print(a,d,sep='\n')
defaultdict(<class 'list'>, {'a': [1, 2], 'b': [4]})
defaultdict(<class 'set'>, {'a': {1, 2}, 'b': {4}})
# 需要注意的是,defaultdict 会自动为将要访问的键(就算目前字典中并不存在
# 这样的键)创建映射实体。如果你并不需要这样的特性,你可以在一个普通的字典上使
# 用 setdefault() 方法来代替
d = {} # A regular dictionary
d.setdefault('a', []).append(1)
d.setdefault('a', []).append(2)
d.setdefault('b', []).append(4)
d
{'a': [1, 2], 'b': [4]}
d = {}
for key, value in pairs:
if key not in d:
d[key] = []
d[key].append(value)
## 可 替换为
d = defaultdict(list)
for key, value in pairs:
d[key].append(value)
1.7 字典排序
from collections import OrderedDict
d = OrderedDict()
在迭代操作的时候它会保持元素被插入时的顺序
1.8 字典的运算
# 方向: 使用zip()函数将健和值反转过来进行操作
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
min_price = min(zip(prices.values(), prices.keys()))
# min_price is (10.75, 'FB')
max_price = max(zip(prices.values(), prices.keys()))
# max_price is (612.78, 'AAPL')
prices_sorted = sorted(zip(prices.values(), prices.keys()))
# prices_sorted is [(10.75, 'FB'), (37.2, 'HPQ'),
# (45.23, 'ACME'), (205.55, 'IBM'),
# (612.78, 'AAPL')]
prices_and_names = zip(prices.values(), prices.keys())
print(min(prices_and_names)) # OK
print(max(prices_and_names)) # ValueError: max() arg is an empty sequence
(10.75, 'FB')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [24], in <module>
19 prices_and_names = zip(prices.values(), prices.keys())
20 print(min(prices_and_names)) # OK
---> 21 print(max(prices_and_names))
ValueError: max() arg is an empty sequence
1.9 查找两字典的相同点
1.10 删除序列相同元素并保持顺序
def dedupe(items):
seen = set()
for item in items:
if item not in seen:
yield item
seen.add(item)
a = [1, 5, 2, 1, 9, 1, 5, 10]
list(dedupe(a))
[1, 5, 2, 9, 10]
1.11 命名切片
record = '....................100 .......513.25 ..........'
cost = int(record[20:23]) * float(record[31:37])
cost
SHARES = slice(20, 23)
PRICE = slice(31, 37)
cost = int(record[SHARES]) * float(record[PRICE])
cost
51325.0
1.12 序列中出现次数最多的元素
words = [
'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
'my', 'eyes', "you're", 'under'
]
from collections import Counter
word_counts = Counter(words)
# 出现频率最高的 3 个单词
top_three = word_counts.most_common(3)
print(top_three)
# Outputs [('eyes', 8), ('the', 5), ('look', 4)]
morewords = ['why','are','you','not','looking','in','my','eyes']
word_counts.update(morewords)
[('eyes', 8), ('the', 5), ('look', 4)]
1.13 通过某个关键字排序一个字典列表
rows = [
{'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
from operator import itemgetter
rows_by_fname = sorted(rows, key=itemgetter('fname'))
rows_by_uid = sorted(rows, key=itemgetter('uid'))
print(rows_by_fname)
print(rows_by_uid)
[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]
[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]
# itemgetter() 函数也支持多个 keys,比如下面的代码
rows_by_lfname = sorted(rows, key=itemgetter('lname','fname'))
print(rows_by_lfname)
[{'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}]
## 与上述的处理一样
rows_by_fname = sorted(rows, key=lambda r: r['fname'])
rows_by_lfname = sorted(rows, key=lambda r: (r['lname'],r['fname']))
# >>> min(rows, key=itemgetter('uid'))
# {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}
# >>> max(rows, key=itemgetter('uid'))
# {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
1.15 通过某个字段将记录分组
# 想根据某个特定的字段比如 date 来分组迭
# 代访问。
rows = [
{'address': '5412 N CLARK', 'date': '07/01/2012'},
{'address': '5148 N CLARK', 'date': '07/04/2012'},
{'address': '5800 E 58TH', 'date': '07/02/2012'},
{'address': '2122 N CLARK', 'date': '07/03/2012'},
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
{'address': '1060 W ADDISON', 'date': '07/02/2012'},
{'address': '4801 N BROADWAY', 'date': '07/01/2012'},
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'},
]
from operator import itemgetter
from itertools import groupby
# Sort by the desired field first
rows.sort(key=itemgetter('date'))
# Iterate in groups
for date, items in groupby(rows, key=itemgetter('date')):
print(date)
for i in items:
print(' ', i)
07/01/2012
{'address': '5412 N CLARK', 'date': '07/01/2012'}
{'address': '4801 N BROADWAY', 'date': '07/01/2012'}
07/02/2012
{'address': '5800 E 58TH', 'date': '07/02/2012'}
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}
{'address': '1060 W ADDISON', 'date': '07/02/2012'}
07/03/2012
{'address': '2122 N CLARK', 'date': '07/03/2012'}
07/04/2012
{'address': '5148 N CLARK', 'date': '07/04/2012'}
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'}
1.16 过滤序列元素
## 最简单的过滤序列元素的方法就是使用列表推导
mylist = [1, 4, -5, 10, -7, 2, 3, -1]
[n for n in mylist if n > 0]
[1, 4, 10, 2, 3]
# 使用列表推导的一个潜在缺陷就是如果输入非常大的时候会产生一个非常大的结
# 果集,占用大量内存
clip_neg = [n if n > 0 else 0 for n in mylist]
print(clip_neg)
clip_pos = [n if n < 0 else 0 for n in mylist]
print(clip_pos)
[1, 4, 0, 10, 0, 2, 3, 0]
[0, 0, -5, 0, -7, 0, 0, -1]
1.17 从字典中提取子集
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}
# Make a dictionary of all prices over 200
p1 = {key: value for key, value in prices.items() if value > 200}
# Make a dictionary of tech stocks
tech_names = {'AAPL', 'IBM', 'HPQ', 'MSFT'}
p2 = {key: value for key, value in prices.items() if key in tech_names}
p3 = dict((key, value) for key, value in prices.items() if value > 200)
p3
{'AAPL': 612.78, 'IBM': 205.55}
1.18 映射名称到序列元素
from collections import namedtuple
Subscriber = namedtuple('Subscriber', ['addr', 'joined'])
sub = Subscriber('jonesy@example.com', '2012-10-19')
print(sub)
print(sub.addr)
print(sub.joined)
Subscriber(addr='jonesy@example.com', joined='2012-10-19')
jonesy@example.com
2012-10-19
print(len(sub))
addr, joined = sub
print(addr)
print(joined)
2
jonesy@example.com
2012-10-19
from collections import namedtuple
Stock = namedtuple('Stock', ['name', 'shares', 'price'])
def compute_cost(records):
total = 0.0
for rec in records:
s = Stock(*rec)
total += s.shares * s.price
return total
s = Stock('ACME', 100, 123.45)
print(s)
s=s._replace(shares=75)
print(s)
Stock(name='ACME', shares=100, price=123.45)
Stock(name='ACME', shares=75, price=123.45)
1.19 转换并同时计算数据
# 计算平方和
nums = [1, 2, 3, 4, 5]
s = sum(x * x for x in nums)
s
55
import os
files = os.listdir('./')
if any(name.endswith('.py') for name in files):
print('There be python!')
else:
print('Sorry, no python.')
Sorry, no python.
portfolio = [
{'name':'GOOG', 'shares': 50},
{'name':'YHOO', 'shares': 75},
{'name':'AOL', 'shares': 20},
{'name':'SCOX', 'shares': 65}
]
min_shares = min(s['shares'] for s in portfolio)
min_shares
20
# Original: Returns 20
min_shares = min(s['shares'] for s in portfolio)
print(min_shares)
print("...................")
# Alternative: Returns {'name': 'AOL', 'shares': 20}
min_shares = min(portfolio, key=lambda s: s['shares'])
print(min_shares)
# 重视lambda 的功能
20
...................
{'name': 'AOL', 'shares': 20}
1.20 合并多个字典或映射
第二章:字符串和文本
2.1 使用多个界定符分割字符串
# split() 方法只适应于非常简单的字符串分割情形,它并不允许有
# 多个分隔符或者是分隔符周围不确定的空格
line = 'asdf fjdk; afed, fjek,asdf, foo'
import re
re.split(r'[;,\s]\s*', line)
['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
# 当你使用 re.split() 函数时候,需要特别注意的是正则表达式中是否包含一个括
# 号捕获分组。如果使用了捕获分组,那么被匹配的文本也将出现在结果列表中。
fields = re.split(r'(;|,|\s)\s*', line)
fields
['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo']
如果你不想保留分割字符串到结果列表中去,但仍然需要使用到括号来分组正则
表达式的话,确保你的分组是非捕获分组,形如 (?:…)
re.split(r'(?:,|;|\s)\s*', line)
['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
2.2 字符串开头或结尾匹配
str.startswith() 或者是 str.
endswith()
import os
filenames = os.listdir('.')
filenames
['.ipynb_checkpoints',
'Notes of Python Cookbook (Chr1-Chr3).ipynb',
'Untitled.ipynb']
[name for name in filenames if name.endswith(('.c', '.h')) ]
[]
any(name.endswith('.py') for name in filenames)
False
2.3 用 Shell 通配符匹配字符串
from fnmatch import fnmatch, fnmatchcase
print(fnmatch('foo.txt', '*.txt'))
print(fnmatch('foo.txt', '?oo.txt')
)
print(fnmatch('Dat45.csv', 'Dat[0-9]*')
)
True
True
True
names = ['Dat1.csv', 'Dat2.csv', 'config.ini', 'foo.py']
[name for name in names if fnmatch(name, 'Dat*.csv')]
['Dat1.csv', 'Dat2.csv']
# fnmatch() 函数使用底层操作系统的大小写敏感规则 (不同的系统是不一样的) 来
# 匹配模式。
print(fnmatch('foo.txt', '*.TXT'))
print(fnmatch('foo.txt', '*.TXT')
)
# 如果你的代码需要做文件名的匹配,最好使用 glob 模块。
False
False
2.4 字符串匹配和搜索
主要关于re正则表达匹配
text1 = '11/27/2012'
text2 = 'Nov 27, 2012'
# 先编译
datepat = re.compile(r'\d+/\d+/\d+')
# 再匹配
datepat.match(text1)
<re.Match object; span=(0, 10), match='11/27/2012'>
# match() 总是从字符串开始去匹配,如果你想查找字符串任意部分的模式出现位
# 置,使用 findall() 方法去代替
text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
datepat.findall(text)
['11/27/2012', '3/13/2013']
在定义正则式的时候,通常会利用括号去捕获分组
datepat = re.compile(r'(\d+)/(\d+)/(\d+)')
datepat.findall(text)
[('11', '27', '2012'), ('3', '13', '2013')]
m = datepat.match('11/27/2012')
print(m.group(1))
print(m.group(2))
month, day, year = m.groups()
print(month)
print('.......................')
for month, day, year in datepat.findall(text):
print('{}-{}-{}'.format(year,month,day))
print('*******************')
print(f'{year}-{month}-{day}')
11
27
11
.......................
2012-11-27
*******************
2012-11-27
2013-3-13
*******************
2013-3-13
findall() 方法会搜索文本并以列表形式返回所有的匹配。如果你想以迭代方式返
回匹配,可以使用 finditer() 方法来代替
for m in datepat.finditer(text):
print(m.groups())
('11', '27', '2012')
('3', '13', '2013')
这一节阐述了使用 re
模块进行匹配和搜索文本的最基本方法。核心步骤就是先使用 re.compile() 编译正则
表达式字符串,然后使用 match() , findall() 或者 finditer() 等方法。
如果你想精确匹配,确保你的正则表达式以 $ 结尾,就像这么这样:
datepat = re.compile(r'(\d+)/(\d+)/(\d+)$')
datepat.findall('11/27/2012abcdef')
print("................")
datepat.findall('11/27/2012')
# re.findall(r'(\d+)/(\d+)/(\d+)', text)
................
[('11', '27', '2012')]
2.5 字符串搜索和替换
对于简单的字面模式,直接使用 str.replace() 方法即可
text = 'yeah, but no, but yeah, but no, but yeah'
text.replace('yeah', 'yep')
'yep, but no, but yep, but no, but yep'
对于复杂的模式,请使用 re 模块中的 sub() 函数。
text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
import re
re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text)
'Today is 2012-11-27. PyCon starts 2013-3-13.'
sub() 函数中的第一个参数是被匹配的模式,第二个参数是替换模式。反斜杠数字
比如 \3 指向前面模式的捕获组号
# 先编译
import re
datepat = re.compile(r'(\d+)/(\d+)/(\d+)')
datepat.sub(r'\3-\1-\2', text)
'Today is 2012-11-27. PyCon starts 2013-3-13.'
对于更加复杂的替换,可以传递一个替换回调函数来代替,比如:
print(text)
print(datepat)
from calendar import month_abbr
def change_date(m):
mon_name = month_abbr[int(m.group(1))]
return '{} {} {}'.format(m.group(2), mon_name, m.group(3))
datepat.sub(change_date, text)
Today is 11/27/2012. PyCon starts 3/13/2013.
re.compile('(\\d+)/(\\d+)/(\\d+)')
'Today is 27 Nov 2012. PyCon starts 13 Mar 2013.'
一个替换回调函数的参数是一个 match 对象,也就是 match() 或者 find() 返回
的对象。使用 group() 方法来提取特定的匹配部分。回调函数最后返回替换字符串。
如果除了替换后的结果外,你还想知道有多少替换发生了,可以使用 re.subn()
来代替。
newtext, n = datepat.subn(r'\3-\1-\2', text)
print(newtext)
print(n)
Today is 2012-11-27. PyCon starts 2013-3-13.
2
2.6 字符串忽略大小写的搜索替换
text = 'UPPER PYTHON, lower python, Mixed Python'
re.findall('python', text, flags=re.IGNORECASE)
['PYTHON', 'python', 'Python']
最后的那个例子揭示了一个小缺陷,替换字符串并不会自动跟被匹配字符串的大
小写保持一致。为了修复这个,需要一个辅助函数
matchcase(‘snake’) 返回了一个回调函数 (参数必须是 match 对象),前
面一节提到过,sub() 函数除了接受替换字符串外,还能接受一个回调函数。
def matchcase(word):
def replace(m):
text = m.group()
if text.isupper():
return word.upper()
elif text.islower():
return word.lower()
elif text[0].isupper():
return word.capitalize()
else:
return word
return replace
re.sub('python', matchcase('snake'), text, flags=re.IGNORECASE)
'UPPER SNAKE, lower snake, Mixed Snake'
2.7 最短匹配模式
str_pat = re.compile(r'\"(.*)\"')
text1 = 'Computer says "no."'
print(str_pat.findall(text1))
text2 = 'Computer says "no." Phone says "yes."'
print(str_pat.findall(text2))
['no.']
['no." Phone says "yes.']
使得匹配变成非贪婪模式,从而得到最短的匹配
通过在 * 或者 + 这样的操作符后面添加一个 ? 可以强制匹配算法
改成寻找最短的可能匹配。
str_pat = re.compile(r'\"(.*?)\"')
str_pat.findall(text2)
['no.', 'yes.']
2.8 多行匹配模式
使用正则表达式去匹配一大块的文本,而你需要跨越多行去匹配
点 (.) 去匹配任意字符的时候,忘记了点 (.) 不能
匹配换行符的事实。
comment = re.compile(r'/\*(.*?)\*/')
text1 = '/* this is a comment */'
text2 = '''/* this is a
multiline comment */
'''
print(comment.findall(text1))
print(comment.findall(text2))
[' this is a comment ']
[]
修改模式字符串,增加对换行的支持
(?:.|\n) 代替 .
comment = re.compile(r'/\*((?:.|\n)*?)\*/')
comment.findall(text2)
# 在这个模式中,(?:.|\n) 指定了一个非捕获组 (也就是它定义了一个仅仅用来做
# 匹配,而不能通过单独捕获或者编号的组)
[' this is a\nmultiline comment ']
re.compile() 函数接受一个标志参数叫 re.DOTALL ,在这里非常有用。它可以让
正则表达式中的点 (.) 匹配包括换行符在内的任意字符。
comment = re.compile(r'/\*(.*?)\*/', re.DOTALL)
comment.findall(text2)
[' this is a\nmultiline comment ']
2.9 将 Unicode 文本标准化
2.10 在正则式中使用 Unicode
2.11 删除字符串中不需要的字符
2.12 审查清理文本字符串
2.13 字符串对齐
对于基本的字符串对齐操作,可以使用字符串的 ljust() , rjust() 和 center()
方法
text = 'Hello World'
print(text.rjust(20,'='))
print(text.center(20,'*'))
=========Hello World
****Hello World*****
函数 format() 同样可以用来很容易的对齐字符串。你要做的就是使用 <,> 或者 ^
字符后面紧跟一个指定的宽度。
print(format(text, '>20'))
print(format(text, '^20'))
# 指定一个非空格的填充字符,将它写到对齐字符的前面即可
print(format(text, '*^20s'))
Hello World
Hello World
****Hello World*****
'{:>10s} {:>10s}'.format('Hello', 'World')
' Hello World'
x = 1.2345
format(x, '^10.2f')
' 1.23 '
2.14 合并拼接字符串
parts = ['Is', 'Chicago', 'Not', 'Chicago?']
' '.join(parts)
'Is Chicago Not Chicago?'
2.15 字符串中插入变量
2.16 以指定列宽格式化字符串
使用 textwrap 模块来格式化字符串的输出。一些长字符串,想以指定的列宽将它们重新格式化。
s = "Look into my eyes, look into my eyes, the eyes, the eyes, \
the eyes, not around the eyes, don't look around the eyes, \
look into my eyes, you're under."
import textwrap
print(textwrap.fill(s, 70))
Look into my eyes, look into my eyes, the eyes, the eyes, the eyes,
not around the eyes, don't look around the eyes, look into my eyes,
you're under.
print(textwrap.fill(s, 40))
Look into my eyes, look into my eyes,
the eyes, the eyes, the eyes, not around
the eyes, don't look around the eyes,
look into my eyes, you're under.
print(textwrap.fill(s, 40, initial_indent=' '))
Look into my eyes, look into my eyes,
the eyes, the eyes, the eyes, not around
the eyes, don't look around the eyes,
look into my eyes, you're under.
print(textwrap.fill(s, 40, subsequent_indent=' '))
Look into my eyes, look into my eyes,
the eyes, the eyes, the eyes, not
around the eyes, don't look around the
eyes, look into my eyes, you're under.
textwrap 模块对于字符串打印是非常有用的,特别是当你希望输出自动匹配终端
大小的时候。你可以使用 os.get_terminal_size() 方法来获取终端的大小尺寸。
import os
os.get_terminal_size().columns
第三章:数字日期和时间
3.1 数字的四舍五入
对于简单的舍入运算,使用内置的 round(value, ndigits) 函数即可
round(1.25361,3)
1.254
当一个值刚好在两个边界的中间的时候,round 函数返回离它最近的偶数
print(round(1.5,0))
print(round(2.5,0))
2.0
2.0
a = 1627731
print(round(a, -1))
print(round(a, -2))
1627730
1627700
3.3 数字的格式化输出
格式化输出单个数字的时候,可以使用内置的 format() 函数
x = 1234.56789
print(format(x, '0.2f'))
print(format(x, '>10.1f'))
print(format(x, '^10.1f'))
print(format(x, ','))
1234.57
1234.6
1234.6
1,234.56789
3.12 基本的日期与时间转换
执行简单的时间转换,比如天到秒,小时到分钟等的转换。
from datetime import timedelta
a = timedelta(days=2, hours=6)
b = timedelta(hours=4.5)
c = a + b
print(c.days)
print(c.seconds)
print(c.seconds / 3600)
print(c.total_seconds() / 3600)
2
37800
10.5
58.5