1 命令行及环境配置
1.1 PIP参数
- 波浪线tilde equals (~=),选择包的当前大版本的最高子版本 (Stackoverflow)
example:
mock-django~=0.6.10
It will select the latest version of the package, greater than or equal to 0.6.10, but still in the 0.6.* version, so it won’t download 0.7.0 for example.
1.2 检查安装的模块版本
- 代码
import sys
import pkg_resources
if __name__ == '__main__':
m_name = sys.argv[1]
try:
v = pkg_resources.get_distribution(m_name).version
print("{}'s version is: {}".format(m_name, v))
except:
print("No such a module installed.")
2 基本语法
2.1 Ellipsis (”…“)
- singleton Ellipsis object A placeholder for not-yet-written code,个人认为是比pass更好用的平替
2.2 Python中的Null类型 — None/NoneType
- Python中的Null类型为None,可以使用
if foo is None
来判断
2.3 ','
的拆包
2.3.1 拆包符号的使用
2.3.2 拆包符号的运算优先级
- 拆包中不能放入连续的运算,
','
前后的变量是同时完成运算(可以认为是并行),没有先后运算的时序关系,如输出结果为a, b = 1, 2 a, b = 2, a+1
a=2
,b=2
,进行b
的运算时并没有采用更新值,而是用之前初始化的值
2.4 判断列表是否存在,或是否为空
x=None | x=[] | x=[1,2,3] | |
---|---|---|---|
if x is None | True | False | False |
if not x | True | True | False |
if not (x is None) | False | True | True |
if x is not None | False | True | True |
None
,False
,空字符串""
,0
,空列表[]
,空字典{}
,空元组()
都相当于False
,因此if not x
不能对其进行区分if x is not []
不能用来判断空列表!
2.5 列表list及相关使用细节
多维列表根据某个位置的元素进行排序
- 使用
sort()
函数和lambda
reverse
:False
为升序排列,True
为降序排列
your_list = [[1,3],[32,5],[23,2],[48,1],[48,4],[32,0]]
your_list.sort(reverse=True, key=lambda x: x[-1])
2.5.1 两个list变量相互赋值,浅拷贝shallow copy与深拷贝deep copy
- 浅拷贝shallow copy对应C语言中按地址传递。深拷贝deep copy对应C语言中按值传递
- 如果声明了一个list类型变量
a
,再通过b=a
声明b
时,是浅拷贝,之后对a
的修改也会反应到变量中 - 类似情况如声明全零二维列表
- 如果在
a
的基础上,声明一个列表,则为深拷贝,之后对a
的修改,对于b
没有影响,如a = [1,2,3] b = a+[0] ## b = [1,2,3,0] a[1] = [10] ## a = [1,10,3] ## b = [1,2,3,0]
2.5.2 批量修改列表中元素(如一个列表中每个元素均为np.array)
- 使用
__setitem__()
方法a = [np.eye(4) for i in range(7)] [a[i].__setitem__((0, 3), 0.006) for i in range(3)]
2.5.3 声明全零二维列表
2.5.3.1 错误方法:
a = [[0]*m]*n
这个列表中每一行[0]*m
都指向同一实例,改变其中一个元素的值将同时改变每一行的值
这个方法相当于先声明了[0,0,0,...,0]
,再将其复制n
次
2.5.3.2 正确方法
a = [ [0]*m for _ in range(n)]
此二维列表中每个元素都是独立的
这个方法相当于每次都重新声明[0,0,0,...,0]
,共重复n
次
2.5.4 Range()
- 在一个区间进行计数
range(x1,x2)
的计数从x1
开始,到x2-1
结束,若生成列表,则为[x1, x1+1, x1+2, ..., x2-1]
- 倒序计数
range(n-1, -1, -1)
从n-1
反向计数至0
2.6 跳出多层循环
- 将多层循环包装为一个函数,使用
return
- 抛出异常
class GetOutOfLoop(Exception): pass try: for i in ...: for j in ...: if ...: pass else: raise GetOutOfLoop except GetOutOfLoop: pass
2.7 用Ctrl+c跳出程序的主循环
- 一般方法
try:
while True:
do_something()
except KeyboardInterrupt:
pass
- ROS
while not rospy.is_shutdown():
...
2.8 格式化输出
2.8.1 print/file.write的格式化输出
- 使用
print("your content here with {}".format(data))
- 指定整数或者小数的位数
print("data: {:3.4f}".format(your_float))
print("data: {:3.4}".format(your_float))
若没有f
,则为使用科学计数法表示
2.8.2 NumPy默认输出为科学计数法
2.9 构建数据类型(使用dataclass)
- 需要引用
dataclasses
的dataclass
和field
- 如果为多层嵌套,其内部所嵌套的每层声明应当用
field
进行初始化,否则会导致声明指向同一变量(Python stores default member variable values in class attributes.), 参考- 正确示例
输出为
1
和2
from dataclasses import dataclass, field ## inner most data @dataclass class Lv0: x: float=0 ## the structure in the middle @dataclass class Lv1: y0: Lv0 = field(default_factory=lambda: Lv0()) # not y0: Lv0 = Lv0() ## outer most data @dataclass class Lv2: z0: Lv1 = field(default_factory=lambda: Lv1()) if __name__ == '__main__': a = Lv2() b = Lv2() a.z0.y0.x = 1 b.z0.y0.x = 2 print(a.z0.y0.x) ## get 1 print(b.z0.y0.x) ## get 2
- 错误示例,
a
和b
的.z0.y0
指向了同一变量,输出为2
和2
from dataclasses import dataclass, field @dataclass class Lv0: x: float=0 @dataclass class Lv1: y0: Lv0 = Lv0() @dataclass class Lv2: z0: Lv1 = field(default_factory=lambda: Lv1()) if __name__ == '__main__': a = Lv2() b = Lv2() a.z0.y0.x = 1 b.z0.y0.x = 2 print(a.z0.y0.x) ## get 2 print(b.z0.y0.x) ## get 2
- 正确示例
输出为
3 如何导入在其他文件夹中的模块/同一子文件夹中的模块
- 假设当前脚本的结构为:
要在|->main.py |->utils/ |->vision/ |->rgb_process.py |->post_process.py |->control/ |->others/
post_pocess.py
中引用rgb_process
中的object_mask
类
sys.path.append('../../')
from utils.vision.rgb_process import object_mask
4 添加命令行参数
- 示例
import argparse
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-init', '--init', action = 'store_true', help = 'initializing') # add_argument()指定程序可以接受的命令行选项
args = parser.parse_args() # parse_args()从指定的选项中返回一些数据
print(args)
print(args.init)
action='store_true'
上例中args.init
的值将被设置为True
5 文件操作
5.1 获取文件夹下所有特定扩展名的文件名
- 示例
def get_files(path, extention = '.txt'):
find_files = []
f_list = os.listdir(path)
for i in f_list:
if os.path.splitext(i)[-1] == extention:
find_files.append(i)
return find_files
6 时间
6.1 计时
- 方法一:单位为秒,代码示例
import timeit
start = timeit.default_timer()
## DO SOMETHING
stop = timeit.default_timer()
print("spent {}".format(stop-start))
- 方法二:单位为秒,代码示例
import time
start = time.perf_counter()
## DO SOMETHING
stop = time.perf_counter()
print("Runtime: {}ms".format((stop-start)*1000)
用时间戳作为文件名
- 使用函数
time.strftime
,代码示例filename = time.strftime("%m-%d_%H-%M-%S", time.localtime(time.time()))