### 玩转自动化运维全流程
1、易混杂操作本节对一些 Python 易混杂的操作停止比照。
1.1 有放回随机采样和无放回随机采样
import randomrandom.choices(seq, k=1) # 长度为k的list,有放回采样random.sample(seq, k) # 长度为k的list,无放回采样复制代码
1.2 lambda 函数的参数
func = lambda y: x + y # x的值在函数运转时被绑定func = lambda y, x=x: x + y # x的值在函数定义时被绑定复制代码
1.3 copy 和 deepcopy
import copyy = copy.copy(x) # 只复制最顶层y = copy.deepcopy(x) # 复制一切嵌套局部复制代码
复制和变量别名分离在一同时,容易混杂:
a = [1, 2, [3, 4]]# Alias.b_alias = a assert b_alias == a and b_alias is a# Shallow copy.b_shallow_copy = a[:] assert b_shallow_copy == a and b_shallow_copy is not a and b_shallow_copy[2] is a[2]# Deep copy.import copyb_deep_copy = copy.deepcopy(a) assert b_deep_copy == a and b_deep_copy is not a and b_deep_copy[2] is not a[2]复制代码
对别名的修正会影响原变量,(浅)复制中的元素是原列表中元素的别名,而深层复制是递归的停止复制,对深层复制的修正不影响原变量。
1.4 == 和 is
x == y # 两援用对象能否有相同值x is y # 两援用能否指向同一对象复制代码
1.5 判别类型
type(a) == int # 疏忽面向对象设计中的多态特征isinstance(a, int) # 思索了面向对象设计中的多态特征复制代码
1.6 字符串搜索
str.find(sub, start=None, end=None); str.rfind(...) # 假如找不到返回-1str.index(sub, start=None, end=None); str.rindex(...) # 假如找不到抛出ValueError异常复制代码
1.7 List 后向索引
这个只是习气问题,前向索引时下标从0开端,假如反向索引也想从0开端能够运用~。
print(a[-1], a[-2], a[-3])print(a[~0], a[~1], a[~2])复制代码
2、C/C++ 用户运用指南不少 Python 的用户是从以前 C/C++ 迁移过来的,这两种言语在语法、代码作风等方面有些不同,本节扼要停止引见。
2.1 很大的数和很小的数
C/C++ 的习气是定义一个很大的数字,Python 中有 inf 和 -inf:
a = float('inf')b = float('-inf')复制代码
2.2 布尔值
C/C++ 的习气是运用 0 和非 0 值表示 True 和 False, Python 倡议直接运用 True 和 False 表示布尔值。
a = Trueb = False复制代码
2.3 判别为空
C/C++ 对空指针判别的习气是 if (a) 和 if (!a)。Python 关于 None 的判别是:
if x is None: pass复制代码
假如运用 if not x,则会将其他的对象(比方长度为 0 的字符串、列表、元组、字典等)都会被当做 False。
2.4 交流值
C/C++ 的习气是定义一个暂时变量,用来交流值。应用 Python 的 Tuple 操作,能够一步到位。
a, b = b, a复制代码
2.5 比拟
C/C++ 的习气是用两个条件。应用 Python 能够一步到位。
if 0 < a < 5: pass复制代码
2.6 类成员的 Set 和 Get
C/C++ 的习气是把类成员设为 private,经过一系列的 Set 和 Get 函数存取其中的值。在 Python 中固然也能够经过 @property、@setter、@deleter 设置对应的 Set 和 Get 函数,我们应防止不用要的笼统,这会比直接访问慢 4 - 5 倍。
2.7 函数的输入输出参数
C/C++ 的习气是把输入输出参数都列为函数的参数,经过指针改动输出参数的值,函数的返回值是执行状态,函数调用方对返回值停止检查,判别能否胜利执行。在 Python 中,不需求函数调用方停止返回值检查,函数中遇到特殊状况,直接抛出一个异常。
2.8 读文件
相比 C/C++,Python 读文件要简单很多,翻开后的文件是一个可迭代对象,每次返回一行内容。
with open(file_path, 'rt', encoding='utf-8') as f: for line in f: print(line) # 末尾的n会保存复制代码
2.9 文件途径拼接
C/C++ 的习气通常直接用 + 将途径拼接,这很容易出错,Python 中的 os.path.join 会自动依据操作系统不同补充途径之间的 / 或 分隔符:
import osos.path.join('usr', 'lib', 'local')复制代码
2.10 解析命令行选项
固然 Python 中也能够像 C/C++ 一样运用 sys.argv 直接解析命令行选择,但是运用 argparse 下的 ArgumentParser 工具愈加便当,功用愈加强大。
2.11 调用外部命令
固然 Python 中也能够像 C/C++ 一样运用 os.system 直接调用外部命令,但是运用 subprocess.check_output 能够自在选择能否执行 Shell,也能够取得外部命令执行结果。
import subprocess# 假如外部命令返回值非0,则抛出subprocess.CalledProcessError异常result = subprocess.check_output(['cmd', 'arg1', 'arg2']).decode('utf-8') # 同时搜集规范输出和规范错误result = subprocess.check_output(['cmd', 'arg1', 'arg2'], stderr=subprocess.STDOUT).decode('utf-8') # 执行shell命令(管道、重定向等),能够运用shlex.quote()将参数双引号惹起来result = subprocess.check_output('grep python | wc > out', shell=True).decode('utf-8')复制代码
2.12 不反复造轮子
不要反复造轮子,Python称为batteries included即是指Python提供了许多常见问题的处理计划。
3、常用工具3.1 读写 CSV 文件
import csv# 无header的读写with open(name, 'rt', encoding='utf-8', newline='') as f: # newline=''让Python不将换行统一处置 for row in csv.reader(f): print(row[0], row[1]) # CSV读到的数据都是str类型with open(name, mode='wt') as f: f_csv = csv.writer(f) f_csv.writerow(['symbol', 'change'])# 有header的读写with open(name, mode='rt', newline='') as f: for row in csv.DictReader(f): print(row['symbol'], row['change'])with open(name, mode='wt') as f: header = ['symbol', 'change'] f_csv = csv.DictWriter(f, header) f_csv.writeheader() f_csv.writerow({'symbol': xx, 'change': xx})复制代码
留意,当 CSV 文件过大时会报错:_csv.Error: field larger than field limit (131072),经过修正上限处理
import syscsv.field_size_limit(sys.maxsize)复制代码
csv 还能够读以 t 分割的数据
f = csv.reader(f, delimiter='t')复制代码
3.2 迭代器工具
itertools 中定义了很多迭代器工具,例如子序列工具:
import itertoolsitertools.islice(iterable, start=None, stop, step=None)# islice('ABCDEF', 2, None) -> C, D, E, Fitertools.filterfalse(predicate, iterable) # 过滤掉predicate为False的元素# filterfalse(lambda x: x < 5, [1, 4, 6, 4, 1]) -> 6itertools.takewhile(predicate, iterable) # 当predicate为False时中止迭代# takewhile(lambda x: x < 5, [1, 4, 6, 4, 1]) -> 1, 4itertools.dropwhile(predicate, iterable) # 当predicate为False时开端迭代# dropwhile(lambda x: x < 5, [1, 4, 6, 4, 1]) -> 6, 4, 1itertools.compress(iterable, selectors) # 依据selectors每个元素是True或False停止选择# compress('ABCDEF', [1, 0, 1, 0, 1, 1]) -> A, C, E, F复制代码
序列排序:
sorted(iterable, key=None, reverse=False)itertools.groupby(iterable, key=None) # 按值分组,iterable需求先被排序# groupby(sorted([1, 4, 6, 4, 1])) -> (1, iter1), (4, iter4), (6, iter6)itertools.permutations(iterable, r=None) # 排列,返回值是Tuple# permutations('ABCD', 2) -> AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DCitertools.combinations(iterable, r=None) # 组合,返回值是Tupleitertools.combinations_with_replacement(...)# combinations('ABCD', 2) -> AB, AC, AD, BC, BD, CD
download