1. Exception类
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
2. 内置函数
- reversed()
- filter()
- yield
- enumerate()
- memoryview()
- locals()
- isinstance() / issubclass()
- property()
- ord() / hex()
- setattr()
- slice()
- coerce()
- intern()
- apply()
- vars()
- unichr()
- type()
- globals()
2.1. sorted()
sorted(iterable[, key[, reverse]])
参数:
-
cmp为函数,指定排序时进行比较的函数(Python3.x已取消)
>>> L=[('b',2),('a',1),('c',3),('d',4)] >>> sorted(L, cmp=lambda x,y: cmp(x[1],y[1])) # 利用cmp函数
key和reverse比一个等价的cmp函数处理速度要快。这是因为对于每个列表元素,cmp都会被调用多次,而key和reverse只被调用一次。
def numeric_compare(x, y): return x - y sorted([5, 2, 4, 1, 3], cmp=numeric_compare) # [1, 2, 3, 4, 5]
在Python3中,如需自定义排序规则:
from functools import cmp_to_key x = [(5,"z"), (2,"k"), (4,"c"), (3,"a"), (3,"z"), (1,"d"), (5,"a")] def cmp_(x, y): if x[0] == y[0]: return ord(y[1]) - ord(x[1]) else: return x[0] - y[0] x_ = sorted(x, key=cmp_to_key(cmp_))
不过,这个方式也可以通过Python3的形式表达:
x_ = sorted(x, key=lambda x: (x[0], -ord(x[1])))
-
key为函数,指定取待排序元素的哪一项进行排序
students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)] sorted(students, key=lambda item: item[2])
键函数不需要直接依赖于被排序的对象。键函数还可以访问外部资源。例如,如果学生成绩存储在字典中,则可以使用它们对单独的学生姓名列表进行排序:
students = ['dave', 'john', 'jane']
newgrades = {'john': 'F', 'jane':'A', 'dave': 'C'}
sorted(students, key=newgrades.__getitem__) # ['jane', 'dave', 'john']
在两个对象之间进行比较时,保证排序例程使用 lt() 。 因此,通过定义 lt() 方法,可以很容易地为类添加标准排序顺序:
>>> Student.__lt__ = lambda self, other: self.age < other.age
>>> sorted(student_objects) # [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
2.1.1. from operator import itemgetter
operator模块提供的 itemgetter
函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号)。注意, operator.itemgetter
函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。
a = [1,2,3]
>>> b=operator.itemgetter(1) # 定义函数b,获取对象的第1个域的值
>>> b(a)
2
>>> b=operator.itemgetter(1,0) # 定义函数b,获取对象的第1个域和第0个的值
>>> b(a)
(2, 1)
itemgetter() 函数也支持多个keys排序
>>> rows_by_lfname = sorted(rows, key=itemgetter('lname','fname'))
>>> print(rows_by_lfname)
[{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'},
{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'}]
实际上,在排序时,也可以使用lambda表达式,与itemgetter()效果相同。但是,使用itemgetter()方式会运行的稍微快点。因此,如果你对性能要求比较高的话就使用itemgetter()方式。
rows_by_fname = sorted(rows, key=lambda r: r['fname'])
rows_by_lfname = sorted(rows, key=lambda r: (r['lname'],r['fname']))
最后,不要忘了这节中展示的技术也同样适用于 min()
和 max()
等函数。比如:
>>> min(rows, key=itemgetter('uid'))
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}
>>> max(rows, key=itemgetter('uid'))
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
2.1.2. from operator import attrgetter
想排序类型相同的对象,但是他们不支持原生的比较操作。
class user():
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
'''定义该对象需要输出时的字符串格式'''
return self.name + ":" + str(self.age)
users = [
user("Mike", 28),
user("Lily", 25),
user("Tom", 27),
user("Ben", 23)
]
list_by_name = sorted(users, key=attrgetter("name", "age"))
# 等价于: sorted(users, key=lambda user: (user.name, user.age))
2.1.3. 字典排序
test = defaultdict(list)
test = {"key1":[1,2,3,4], "key2:"[3,4,5,6]}
items = sorted(test.items(), key=lambda x:x[1][3], reverse=True)
# test.items() 返回时一个列表 ("key1",[1,2,3,4])
x[1] 则是[1,2,3,4]
x[1][3] 的话就是4了
3. platform
platform模块给我们提供了很多方法去获取操作系统的信息。
-
platform.platform() # 获取操作系统名称及版本号,'Linux-3.13.0-46-generic-i686-with-Deepin-2014.2-trusty'
-
platform.version() # 获取操作系统版本号,'# 76-Ubuntu SMP Thu Feb 26 * 18:52:49 UTC 2015'
-
platform.architecture() # 获取操作系统的位数,('32bit', 'ELF')
is_64bits = sys.maxsize > 2**32
-
platform.machine() # 计算机类型,'i686'
-
platform.node() # 计算机的网络名称,'XF654'
-
platform.processor() # 计算机处理器信息,'i686'
-
platform.uname() # 包含上面所有的信息汇总
还可以获得计算机中python的一些信息。
- platform.python_build()
- platform.python_compiler()
- platform.python_branch()
- platform.python_implementation()
- platform.python_revision()
- platform.python_version()
- platform.python_version_tuple()
4. shutil
-
shutil.copy(src, dst, *, follow_symlinks=True)
-
shutil.copy2(src, dst, *, follow_symlinks=True) # also attempts to preserve file metadata
-
shutil.copytree()
-
shutil.rmtree('xxx')
-
shutil.move()
-
shutil.remove()
-
cols, lines = shutil.get_terminal_size()
-
shutil.chown(path)
-
shutil.which("python")
-
shutil.ignore_patterns(*patterns)
from shutil import copytree, ignore_patterns copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
5. os
-
os.environ # list of str
-
os.environ['PATH']
-
os.getenv(key, default=None)
On Unix, keys and values are decoded with sys.getfilesystemencoding() and 'surrogateescape' error handler. Use os.getenvb() if you would like to use a different encoding.
-
os.chdir(path)
-
os.getcwd()
-
os.getlogin()
-
os.getuid()
-
os.getpid()
-
os.getcwd()
-
os.chdir('subdir')
-
os.scandir(path='.') # 返回os.DirEntry对象
with os.scandir(path) as it: for entry in it: if not entry.name.startswith('.') and entry.is_file(): print(entry.name)
-
os.DirEntry
- name
- path
- inode()
- is_dir()
- is_file()
- is_symlink()
- stat()
-
os.listdir(path='.')
depressed, use os.scandir() after 3.5
-
os.stat('fileA.txt')
-
os.mkdir(path, mode=0o777)
-
os.makedirs(name='xxxx/yyyy', mode=0o777, exist_ok=False)
-
os.rmdir("xxx/")
-
os.removedirs("xxx/yyy") # 注意,当目录非空时,触发异常
-
os.system("rm -rf xxx/yyy")
-
os.chmod(path, mode)
-
os.chown(path, uid, gid)
-
os.mkfifo(path, mode=0o666)
5.1. 关于一些近似函数的比较
创建文件夹
- os.mkdir(path): 只能在现有的文件夹下,创建一级目录
- os.makedirs("xx/yy/zzz"): 类似
mkdir -p
选项,可以创建多级目录
删除文件
- os.remove(path): 如果path为目录,raise
IsADirectoryError()
- os.rmdir(dir): 如果dir不存在或非空,raise
FileNotFoundError
- os.removedirs('foo/bar/baz'): 先删除baz,之后若bar/为空,则删除bar,以此类推,至删除foo/
- shutil.rmtree(path, ignore_errors=False): 无视dir非空,只管删除
5.2. 遍历文件 - glob
-
glob
glob.glob('*.txt') -> ["path_1", "path_2", ...] glob.glob('*.??')
-
os.listdir(path)
-
os.scandir(path)
-
os.walk
import os for root, dirs, files in os.walk(top, topdown=False): # top参数可以是相对路径,它决定了迭代中root的绝对-相对状态 # root: 代表当前迭代时的路径位置,如:"./loop/curr_dir" # dirs: list,当前root路径下的所有子文件夹,如["subdir", "subdir2"] # files: list,当前root路径下的文件,如["file.txt", "file2.txt"] for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name))
6. os.path
import os.path as osp
- osp.curdir # 常量: "."
- osp.exists(path)
- osp.getmtime(path)
- osp.getctime(path)
- osp.getsize(path)
- osp.isfile(path)
- osp.isdir(path)
- osp.join(path, *paths)
- osp.samefile(path1, path2)
- osp.sameopenfile(fp1, fp2)
- osp.split(path)
- osp.splitext(path)
- osp.basename(path) # 返回文件名: test.txt
- osp.dirname(path)
- osp.abspath(path)
- osp.realpath(path) # 区别于abspath: 如文件为链接,返回实际文件路径
- osp.relpath(path)
7. pathlib
from pathlib import Path
data_folder = Path("source_data/text_files/")
file_to_open = data_folder / "raw_data.txt" # 斜杠 / 操作符
f = open(file_to_open)
print(f.read())
类实例属性和实例方法名 | 功能描述 |
---|---|
PurePath.parts | 返回路径字符串中所包含的各部分: ('/', 'usr', 'bin', 'python3') |
PurePath.drive | 返回路径字符串中的驱动器盘符 |
PurePath.root | 返回路径字符串中的根路径 |
PurePath.anchor | 返回路径字符串中的盘符和根路径 |
PurePath.parents | 返回当前路径的全部父路径 |
PurPath.parent | 返回当前路径的上一级路径,相当于 parents[0] 的返回值 |
PurePath.name | 返回当前路径中的文件名: "raw_data.txt" |
PurePath.suffixes | 返回当前路径中的文件所有后缀名 |
PurePath.suffix | 返回当前路径中的文件后缀名。相当于 suffixes 属性返回的列表的最后一个元素: "txt" |
PurePath.stem | 返回当前路径中的主文件名: "raw_data" |
PurePath.as_posix() | 将当前路径转换成 UNIX 风格的路径 |
PurePath.as_uri() | 将当前路径转换成 URL。只有绝对路径才能转换,否则将会引发 ValueError |
PurePath.is_absolute() | 判断当前路径是否为绝对路径 |
PurePath.joinpath(*other) | 将多个路径连接在一起,作用类似于前面介绍的斜杠(/)连接符 |
PurePath.match(pattern) | 判断当前路径是否匹配指定通配符 |
PurePath.relative_to(*other) | 获取当前路径中去除基准路径之后的结果 |
PurePath.with_name(name) | 将当前路径中的文件名替换成新文件名。如果当前路径中没有文件名,则会引发 ValueError |
PurePath.with_suffix(suffix) | 将当前路径中的文件后缀名替换成新的后缀名。如果当前路径中没有后缀名,则会添加新的后缀名 |
-
Path.exists()
-
Path.is_dir()
-
Path.is_file()
-
Path.is_symlink()
-
Path.expanduser() 替换~为$HOME路径
-
Path.mkdir(mode=0o777, parents=False, exist_ok=False)
-
Path.chmod()
-
Path.rename(target)
-
Path.glob(pattern) 解析相对于此路径的通配符 pattern,产生所有匹配的文件
>>> sorted(Path('.').glob('*.py')) [PosixPath('pathlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')] >>> sorted(Path('.').glob('*/*.py')) [PosixPath('docs/conf.py')]
"**" 模式表示 “此目录以及所有子目录,递归”。换句话说,它启用递归通配
>>> sorted(Path('.').glob('**/*.py')) [PosixPath('build/lib/pathlib.py'), PosixPath('docs/conf.py'), PosixPath('pathlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')]
-
Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)
>>> p = Path('setup.py') >>> with p.open() as f: ... f.readline() ... '#!/usr/bin/env python3 '
-
Path.read_bytes()
-
Path.write_text(data, encoding=None, errors=None)
-
Path.read_text(encoding=None, errors=None)
>>> p = Path('my_text_file') >>> p.write_text('Text file contents') 18 >>> p.read_text() 'Text file contents'
7.1. 对应的 os 模块的工具
os 和 os.path | pathlib |
---|---|
os.path.abspath() | Path.resolve() |
os.chmod() | Path.chmod() |
os.mkdir() | Path.mkdir() |
os.rename() | Path.rename() |
os.replace() | Path.replace() |
os.rmdir() | Path.rmdir() |
os.remove(), os.unlink() | Path.unlink() |
os.getcwd() | Path.cwd() |
os.path.exists() | Path.exists() |
os.path.expanduser() | Path.expanduser() 和 Path.home() |
os.path.isdir() | Path.is_dir() |
os.path.isfile() | Path.is_file() |
os.path.islink() | Path.is_symlink() |
os.stat() | Path.stat(), Path.owner(), Path.group() |
os.path.isabs() | PurePath.is_absolute() |
os.path.join() | PurePath.joinpath() |
os.path.basename() | PurePath.name |
os.path.dirname() | PurePath.parent |
os.path.samefile() | Path.samefile() |
os.path.splitext() | PurePath.suffix |
8. subprocess
- subprocess.run("exit 1", shell=True, check=True)
- subprocess.call("mv abc", shell=True) # depressed
run/call()
函数均为主进程阻塞执行子进程,直到子进程调用完成返回;
如需非阻塞,需要使用 Popen ——
注意: shell=True
选项会开启Windows控制台执行命令,这会引发一个问题——Windows中的控制台命令是后台执行的!所以当python调用 Popen.terminate()
时,只是关闭了控制台,控制台命令却仍在后台执行(直至结束)。所以,如需关闭时同时关闭命令,请不要使用 Popen(str_cmd, shell=True)
,用 Popen(str_cmd.split(' ')
代替。
import subprocess
>>> ls = sub.Popen(['ls'], stdout=sub.PIPE)
>>> for f in ls.stdout: print(f)
...
b'fileA.txt
'
b'fileB.txt
'
b'ls.txt
'
>>> ex = sub.Popen(['ex', 'test.txt'], stdin=sub.PIPE)
>>> ex.stdin.write(b'i
this is a test
.
')
19
>>> ex.std.write(b'wq
')
3
9. time
time.strftime('%Y-%m-%d', time.localtime())
# '2017-12-04'
10. datetime
10.1. 获取当前时间
>>> from datetime import datetime
>>> now = datetime.now()
>>> print(now)
2015-05-18 16:28:07.198690
>>> print(type(now))
<class 'datetime.datetime'>
10.2. 获取指定日期和时间
>>> from datetime import datetime
>>> dt = datetime(2015, 4, 19, 12, 20) # 用指定日期时间创建datetime
>>> print(dt)
2015-04-19 12:20:00
两个datetime对象还可以进行比较。比如使用上面的t和t_next:
print(t > t_next)
对日期和时间进行加减实际上就是把datetime往后或往前计算,得到新的datetime。加减可以直接用+和-运算符,不过需要导入timedelta这个类:
>>> from datetime import datetime, timedelta
>>> now = datetime.now()
>>> now
datetime.datetime(2015, 5, 18, 16, 57, 3, 540997)
>>> now + timedelta(hours=10)
datetime.datetime(2015, 5, 19, 2, 57, 3, 540997)
>>> now - timedelta(days=1)
datetime.datetime(2015, 5, 17, 16, 57, 3, 540997)
>>> now + timedelta(days=2, hours=12)
datetime.datetime(2015, 5, 21, 4, 57, 3, 540997)
10.3. datetime对象与字符串转换
>>> from datetime import datetime
>>> date_info = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
>>> print(date_info)
2015-06-01 18:19:59
我们通过format来告知Python我们的str字符串中包含的日期的格式。在format中,%Y表示年所出现的位置, %m表示月份所出现的位置。
反过来,我们也可以调用datetime对象的strftime()方法,来将datetime对象转换为特定格式的字符串。比如上面所定义的t_next:
>>> from datetime import datetime
>>> now = datetime.now()
>>> print(now.strftime('%a, %b %d %H:%M'))
Mon, May 05 16:28
10.4. 本地时间转换为UTC时间
本地时间是指系统设定时区的时间,例如北京时间是UTC+8:00时区的时间,而UTC时间指UTC+0:00时区的时间。
一个datetime类型有一个时区属性tzinfo,但是默认为None,所以无法区分这个datetime到底是哪个时区,除非强行给datetime设置一个时区:
>>> from datetime import datetime, timedelta, timezone
>>> tz_utc_8 = timezone(timedelta(hours=8)) # 创建时区UTC+8:00
>>> now = datetime.now()
>>> now
datetime.datetime(2015, 5, 18, 17, 2, 10, 871012)
>>> dt = now.replace(tzinfo=tz_utc_8) # 强制设置为UTC+8:00
>>> dt
datetime.datetime(2015, 5, 18, 17, 2, 10, 871012, tzinfo=datetime.timezone(datetime.timedelta(0, 28800)))
如果系统时区恰好是UTC+8:00,那么上述代码就是正确的,否则,不能强制设置为UTC+8:00时区。
10.5. 时区转换
我们可以先通过utcnow()拿到当前的UTC时间,再转换为任意时区的时间:
# 拿到UTC时间,并强制设置时区为UTC+0:00:
>>> utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
>>> print(utc_dt)
2015-05-18 09:05:12.377316+00:00
# astimezone()将转换时区为北京时间:
>>> bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
>>> print(bj_dt)
2015-05-18 17:05:12.377316+08:00
# astimezone()将转换时区为东京时间:
>>> tokyo_dt = utc_dt.astimezone(timezone(timedelta(hours=9)))
>>> print(tokyo_dt)
2015-05-18 18:05:12.377316+09:00
# astimezone()将bj_dt转换时区为东京时间:
>>> tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9)))
>>> print(tokyo_dt2)
2015-05-18 18:05:12.377316+09:00
时区转换的关键在于,拿到一个datetime时,要获知其正确的时区,然后强制设置时区,作为基准时间。
利用带时区的datetime,通过astimezone()方法,可以转换到任意时区。
注:不是必须从UTC+0:00时区转换到其他时区,任何带时区的datetime都可以正确转换,例如上述bj_dt到tokyo_dt的转换。
11. random
-
random.random(): 随机浮点数, 0 <= n < 1.0
-
random.uniform(a,b): 随机符点数, a <= n <= b
-
random.randint(a, b): a <= n <= b
-
random.randrange([start], stop[, step])
从指定范围内,按指定基数递增的集合中获取一个随机数。
random.randrange(10, 30, 2),结果相当于从[10, 12, 14, 16, ... 26, 28]序列中获取一个随机数。
random.randrange(10, 30, 2)在结果上与
random.choice(range(10, 30, 2)
等效。 -
random.choice(sequence)
-
random.shuffle(x[, random])
用于将一个列表中的元素打乱,即将列表内的元素随机排列。
items = list("ABCDE") random.shuffle(items) # 无返回 print(items)
-
random.sample(sequence, k)
从指定序列中随机获取指定长度的片断并随机排列。
注意:sample函数不会修改原有序列。
random.sample(range(10), 5)
12. glob
类似 os.listdir
或 os.scandir
函数,但支持通配符(例如,能够选择特定的后缀名)。
import glob
glob.glob(r'.*.py') -> list_files
13. functools
13.1. partial
functools.partial(func, /, *args, **keywords)
14. itertools
可以实现诸如 A(4,2), C(5,3)
此类的运算。这里列举几个常用功能。
Iterator | Arguments | Results |
---|---|---|
product() | p, q, … [repeat=1] | cartesian product, equivalent to a nested for-loop |
permutations() | p[, r] | r-length tuples, all possible orderings, no repeated elements |
combinations() | p, r | r-length tuples, in sorted order, no repeated elements |
combinations_with_replacement() | p, r | r-length tuples, in sorted order, with repeated elements |
Examples | Results |
---|---|
product('ABCD', repeat=2) | AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD |
permutations('ABCD', 2) | AB AC AD BA BC BD CA CB CD DA DB DC |
combinations('ABCD', 2) | AB AC AD BC BD CD |
combinations_with_replacement('ABCD', 2) | AA AB AC AD BB BC BD CC CD DD |
15. operator
- operator.lt(a, b)
- operator.le(a, b)
- operator.eq(a, b)
- operator.ne(a, b)
- operator.ge(a, b)
- operator.gt(a, b)
Operation | Syntax | Function |
---|---|---|
Addition | a + b | add(a, b) |
Concatenation | seq1 + seq2 | concat(seq1, seq2) |
Containment Test | obj in seq | contains(seq, obj) |
Division | a / b | truediv(a, b) |
Division | a // b | floordiv(a, b) |
Bitwise And | a & b | and_(a, b) |
Bitwise Exclusive Or | a ^ b | xor(a, b) |
Bitwise Inversion | ~ a | invert(a) |
Bitwise Or | a | b |
Exponentiation | a ** b | pow(a, b) |
Identity | a is b | is_(a, b) |
Identity | a is not b | is_not(a, b) |
Indexed Assignment | obj[k] = v | setitem(obj, k, v) |
Indexed Deletion | del obj[k] | delitem(obj, k) |
Indexing | obj[k] | getitem(obj, k) |
Left Shift | a << b | lshift(a, b) |
Modulo | a % b | mod(a, b) |
Multiplication | a * b | mul(a, b) |
Matrix Multiplication | a @ b | matmul(a, b) |
Negation (Arithmetic) | - a | neg(a) |
Negation (Logical) | not a | not_(a) |
Positive | + a | pos(a) |
Right Shift | a >> b | rshift(a, b) |
Slice Assignment | seq[i:j] = values | setitem(seq, slice(i, j), values) |
Slice Deletion | del seq[i:j] | delitem(seq, slice(i, j)) |
Slicing | seq[i:j] | getitem(seq, slice(i, j)) |
String Formatting | s % obj | mod(s, obj) |
Subtraction | a - b | sub(a, b) |
Truth Test | obj | truth(obj) |
Ordering | a < b | lt(a, b) |
Ordering | a <= b | le(a, b) |
Equality | a == b | eq(a, b) |
Difference | a != b | ne(a, b) |
Ordering | a >= b | ge(a, b) |
Ordering | a > b | gt(a, b) |
16. base64
Base64是一种通过查表的编码方法,不能用于加密,即使使用自定义的编码表也不行。Base64适用于小段内容的编码,比如数字证书签名、Cookie的内容等。
Python内置的base64可以直接进行base64的编解码:
>>> import base64
>>> base64.b64encode(b'binaryx00string')
b'YmluYXJ5AHN0cmluZw=='
>>> base64.b64decode(b'YmluYXJ5AHN0cmluZw==')
b'binaryx00string'
由于标准的Base64编码后可能出现字符+和/,在URL中就不能直接作为参数,所以又有一种"url safe"的base64编码,其实就是把字符+和/分别变成-和_:
>>> base64.b64encode(b'ixb7x1dxfbxefxff')
b'abcd++//'
>>> base64.urlsafe_b64encode(b'ixb7x1dxfbxefxff')
b'abcd--__'
>>> base64.urlsafe_b64decode('abcd--__')
b'ixb7x1dxfbxefxff'
还可以自己定义64个字符的排列顺序,这样就可以自定义Base64编码,不过,通常情况下完全没有必要。
由于=字符也可能出现在Base64编码中,但=用在URL、Cookie里面会造成歧义,所以,很多Base64编码后会把=去掉:
# 标准Base64:
'abcd' -> 'YWJjZA=='
# 自动去掉=:
'abcd' -> 'YWJjZA'
去掉=后怎么解码呢?因为Base64是把3个字节变为4个字节,所以,Base64编码的长度永远是4的倍数,因此,需要加上=把Base64字符串的长度变为4的倍数,就可以正常解码了。
17. contextlib: with语句的实现
contextlib 模块包含用于处理上下文管理器和 with 语句的实用程序。
18. json
- json.dumps(data): 对数据进行编码
- json.loads(str_data): 对数据进行解码
相应的文件操作为
- json.dump(obj, fp, ...)
- json.load(fp, ...)
# 读取数据
with open('data.json', 'r') as fp:
data = json.load(fp)
# 写入 JSON 数据
with open('data2.json', 'w') as fp:
json.dump(data,
fp,
ensure_ascii=False, # 输出中文
indent=2) # 用于自动换行(缩进2空格)