python 学习(一)

前言

在18年的时候就把python的基本语法过了一遍了,无奈matlab和mathematica太好用了,所以python这个工具就一直被我给冷落了,现在重新拾起。文中的内容,有些是书本里面的,有些源自于菜鸟教程和一些零散的博客所汇聚而成,仅供自己学习和参考使用。

基础知识

  1. 以下划线开头的标识符是有特殊意义的。以单下划线开头 _foo 的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用 from xxx import * 而导入。 以双下划线开头的__foo 代表类的私有成员,以双下划线开头和结尾的 __foo__ 代表 Python 里特殊方法专用的标识,如 __init__() 代表类的构造函数。

  2. if __name__ == ‘__main__‘的意思是:当.py文件被直接运行时,if __name__ == ‘__main__‘之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__ == ‘__main__‘之下的代码块不被运行。

  3. 对程序计时可用如下两种方式:

    1)time.time() 返回的是一个浮点型类型。这里获取的也是程序的执行时间。使用方法如下所示

    start = time.time()
    #^_^
    end = time.time()
    print (end-start)

    2) time.clock()返回程序开始或第一次被调用clock()以来的CPU时间。这里获得的是CPU的执行时间。调用方式只需要把time.time()换成 time.clock()即可。

读取文件

读取文件夹下所有的文件

import os
fileList = os.listdir(path)

序列函数

enumerate函数

迭代一个序列时,你可能想跟踪当前项的序号。手动的方法可能是下面这样:

i = 0 
for value in collection:
# do something with value
i += 1

因为这么做很常见,Python内建了一个 enumerate 函数,可以返回 (i, value) 元组序列:

for i, value in enumerate(collection): 
# do something with value

当你索引数据时,使用 enumerate 的一个好方法是计算序列(唯一的) dict 映射到位置的值。

zip函数

zip 可以将多个列表、元组或其它序列成对组合成一个元组列表。zip 可以处理任意多的序列,元素的个数取决于最短的序列。zip 的常见用法之一是同时迭代多个序列,可以结合 enumerate 使用:

for i, (a, b) in enumerate(zip(seq1, seq2)):
print('{0}: {1}, {2}'.format(i, a, b))

字典

字典可能是Python最为重要的数据结构。它更为常见的名字是哈希映射或关联数组。它是键值对的大小可变集合,键和值都是Python对象。创建字典的方法之一是使用大括号,用冒号分隔键和值:

empty_dict = {} 
d1 = {'a' : 'some value', 'b' : [1, 2, 3, 4]}

可以像访问列表或元组中的元素一样,访问、插入或设定字典中的元素,也可以用检查列表和元组是否包含某个值的方法,检查字典中是否包含某个键。keys 和 values 是字典的键和值的迭代器方法。虽然键值对没有顺序,这两个方法可以用相同的顺序输出键和值:用 update 方法可以将一个字典与另一个融合:

d1.update({'b' : 'foo', 'c' : 12})

update 方法是原地改变字典,因此任何传递给 update 的键的旧的值都会被舍弃。

用序列创建字典

可能想将两个序列配对组合成字典。下面是一种写法:

mapping = {}
for key, value in zip(key_list, value_list):
mapping[key] = value

因为字典本质上是2元元组的集合,dict可以接受2元元组的列表:

mapping = dict(zip(range(5), reversed(range(5))))

下面的逻辑很常见:

if key in some_dict: 
value = some_dict[key]
else:
value = default_value

因此,dict的方法get和pop可以取默认值进行返回,上面的if-else语句可以简写成下面:

value = some_dict.get(key, default_value)

有效的键类型

字典的值可以是任意Python 对象,而键通常是不可变的标量类型(整数、浮点型、字符串)或元组(元组中的对象必须是不可变的)。这被称为“可哈希性”。可以用 hash 函数检测一个对象是否是可哈希的。 要用列表当做键,一种方法是将列表转化为元组,只要内部元素可以被哈希,它也就可以被哈希。

集合

集合是无序的不可重复的元素的集合。可以把它当做字典,但是只有键没有值。可以用两种方式创建集合:通过 set 函数或使用尖括号 set 语句.集合支持合并、交集、差分和对称差等数学集合运算. 合并是取两个集合中不重复的元素。可以用 union 方法,或者运算符|.交集的元素包含在两个集合中。可以用 intersection 或&运算符.所有逻辑集合操作都有另外的原地实现方法,可以直接用结果替代集合的内容。对于大的集合,这么做效率更高.与字典类似,集合元素通常都是不可变的。要获得类似列表的元素,必须转换成元组.

列表、集合和字典推导式

列表推导式允许用户方便的从一个集合过滤元素,形成列表在传递参数的过程中还可以修改元素。形式如下

[expr for val in collection if condition]

它等同于下面的 for 循环:

result = [ ]
for val in collection:
if condition:
result.append(expr)

用相似的方法,还可以推导集合和字典。字典的推导式如下所示

dic = {key: value-expr for value in collection if condition}

集合的推导式与列表很像,只不过用的是尖括号

set_comp = {expr for value in collection if condition}

与列表推导式类似,集合与字典的推导也很方便,而且使代码的读写都很容易。来看前面的字符串列表。假如我们只想要字符串的长度,用集合推导式的方法非常方便.

Python 合并字典

1,使用 update() 方法,第二个参数合并第一个参数

def Merge(dict1, dict2): 
return(dict2.update(dict1))

2, 使用 **, 函数将参数以字典的形式导入

def Merge(dict1, dict2): 
res = {**dict1, **dict2}
return res

函数

函数使用 def 关键字声明,用 return 关键字返回值,如果到达函数末尾时没有遇到任何一条return语句,则返回 None。 函数可以有一些位置参数(positional)和一些关键字参数(keyword)。关键字参数通常用于指定 默认值或可选参数。

命名空间、作用域

函数可以访问两种不同作用域中的变量:全局(global)和局部(local)。任何在函数中赋值的变量默认都是被分配到局部命名空间(local namespace)中的。局部命名空间是在函数被调用时创建的,函数参数会立即填入该命名空间。在函数执行完毕之后,局部命名空间就会被销毁

生成器

能以一种一致的方式对序列进行迭代(比如列表中的对象或文件中的行)。通过一种叫做迭代器协议 iterator protocol,它是一种使对象可迭代的通用方式)的方式实现的,一个原生的使对象可迭代的方法。生成器(generator)是构造新的迭代对象的一种简单方式。一般的函数执行之后只会返回单个值,而生成器则是以延退的方式返回一个值序列,即每返回一个值之后暂停,直到下一个值被请求时再继续。要创建一个生成器,只需将函数中的 return 替换为 yeild 即可。调用该生成器时,没有任何代码会被立即执行。直到请求元素时,它オ会开始执行其代码。

生成器表达式

另一种更简洁的构造生成器的方法是使用生成器表达式(generator expression)。这是一种类似于列表、字典、集合推导式的生成器。其创建方式为,把列表推导式两端的方括号改成圆括号。

python字符串前面加u,r,b的含义

u/U:表示unicode字符串。不是仅仅是针对中文, 可以针对任何的字符串,代表是对字符串进行unicode编码。一般英文字符在使用各种编码下, 基本都可以正常解析, 所以一般不带u;但是中文, 必须表明所需编码, 否则一旦编码转换就会出现乱码。
建议所有编码方式采用utf8

r/R:非转义的原始字符串。与普通字符相比,其他相对特殊的字符,其中可能包含转义字符,即那些,反斜杠加上对应字母,表示对应的特殊含义的,比如最常见的”\n”表示换行,”\t”表示Tab等。而如果是以r开头,那么说明后面的字符,都是普通的字符了,即如果是“\n”那么表示一个反斜杠字符,一个字母n,而不是表示换行了。以r开头的字符,常用于正则表达式,对应着re模块。

b:bytes。python3.x里默认的str是(py2.x里的)unicode, bytes是(py2.x)的str, b”“前缀代表的就是bytespython2.x里, b前缀没什么具体意义, 只是为了兼容python3.x的这种写法。

文件和操作系统

为了打开一个文件以便读写,可以使用内置的open函数以及一个相对或绝对的文件路径。从文件中取出的行都带有完整的行结束符(EOL),因此你常常会看到下面这样的代码(得到一组没有EOL的行):

lines = [x.rstrip() for x in open(path)]

如果使用open创建文件对象,一定要用close关闭它。关闭文件可以返回操作系统资源:

f.close()

用with语句可以可以更容易地清理打开的文件:

with open (path) as f:
lines = [x.rstrip() for x in f]

这样可以在退出代码块时,自动关闭文件。向文件写入,可以使用文件的write或writelines方法。例如,创建一个无空行版的

with open('tmp.txt','w') as handle:
handle.writelines(x for x in open(path) if len(x) > 1)
with open('tmp.txt') as f:
lines = f.readlines()

最常用的文件方法如下表所示:

方法   说明
read([size])   以字符串形式返回文件数据,可选的size参数用于说明读取的字节数
readlines([size])   将文件返回为行列表,可选参数size
write(str)   将字符串写入文件
close()   关闭句柄
flush()   清空内部I/O缓存区,并将数据强行写回磁盘
seek(pos)   移动到指定的文件位置(整数)
tell   以整数形式返回当前文件位置
closed()   如果文件已关闭,则为True

一种更方便的方法将Unicode转换为另一种编码:

sink_path = 'sink.txt'
with open(path) as source:
with open(sink_path,'xt',encoding = 'iso-88859-1') as sink:
sink.write(source.read())

注意,不要在二进制模式中使用seek。如果文件位置位于定义Unicode字符的字节的中间位置,读取后面会产生错误.

python文件打开方式

r只读,r+读写,不创建新的文件,w新建文件只写入,w+新建读写,二者都会将文件内容清零。r+:可读可写,若文件不存在,则报错;w+: 可读可写,若文件不存在,则创建一个新的文件。a:附加写方式打开,不可读;a+: 附加读写方式打开。使用’r’一般情况下最常用的,但是在进行读取二进制文件时,可能会出现文档读取不全的现象;使用’rb’按照二进制位进行读取的,不会将读取的字节转换成字符,二进制文件用二进制读取用’rb,’rt‘模式下,python在读取文本时会自动把\r\n转换成\n,文本文件用二进制读取用‘rt’。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。

python绘图

matplotlib

matplotlib 是python中最有名的绘图库,在编写较大的应用程序时使用matplotlib会更加有效。如果需要绘制某种类型的图表,在http://matplotlib.sourceforge.net/gallery.html 这个页面找到对应自己需要的,然后粘贴复制即可,基本上略微的修改就可以直接的拿来使用了。和matlab中的绘图十分的相似,如果熟悉matlab绘图的话,对于了解这块绘图会有十分大的帮助。有的时候不得不佩服那些粘贴复制的,带我兜兜转转,问题没解决掉,反而使得时间浪费了不少。看了Dipanjan Sarkar的博客,绘图就是门艺术,这里就简要的说明下seaborn绘图的命令。

显示中文标题

更改编码方式以及使用本地字体,可用参考如下代码。

# -*- coding: UTF-8 -*-            
## 上面更改编码方式,下面解决中文显示
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False

seaborn 的使用

在工作的时候遇到的问题,由于需要进行不同参数下的误差对比,所以用到了这个,这里简略的说明几个用法

  1. ax.set_title(‘your title’), 设置标题

  2. f.savefig(‘yourPic.eps’, dpi=360) ,保存图片,其中dpi可以理解为设置分辨率的。

  3. ax.invert_xaxis(), x轴内容进行转过来显示。

  4. ax.tick_params(axis=’x’,labelsize=6),刻度调整.

  5. sns.set(),样式控制sns.set(style=’white’,palette=’muted’,color_codes=True),style为图表的背景主题,有5种主题可以选择:darkgrid (默认), whitegrid,dark,white,ticks, palette为设置主体颜色,有6种可以选择:deep,muted,pastel,bright,dark,colorblind

  6. 用despine进行边框控制:white和ticks参数的样式,都可以删除上方和右方坐标轴上不需要的边框。despine(top=True, right=True, left=False, bottom=False, offset=None, trim=False),默认无参数的情况下,是删除上面及右边的边框。offset可设置边框的偏移距离,trim设置删除边框的范围.

下面给出seaborn.heatmap详细的参数说明,主要摘抄了 计科小白兔的博文

seaborn.heatmap(data, vmin=None, vmax=None, cmap=None, center=None, robust=False,
annot=None, fmt='.2g', annotkws=None, linewidths=0, linecolor='white', cbar=True,
cbarkws=None, cbar_ax=None, square=False, ax=None, xticklabels=True, yticklabels=True, mask=None, **kwargs)

1,data:矩阵数据集,可以使numpy的数组(array),如果是pandas的dataframe,则df的index/column信息会分别对应到heatmap的columns和rows.
2,vmax,vmin, 图例中最大值和最小值的显示值,没有该参数时默认不显示.
3,linewidths,热力图矩阵之间的间隔大小
4, cmap,热力图颜色
5, ax,绘制图的坐标轴,否则使用当前活动的坐标轴。
6, annot,annotate的缩写,annot默认为False,当annot为True时,在heatmap中每个方格写入数据。
7, annot_kws,当annot为True时,可设置各个参数,包括大小,颜色,加粗,斜体字等:sns.heatmap(x, annot=True, ax=ax2, annot_kws={‘size’:9,’weight’:’bold’, ‘color’:’blue’})
8, fmt,格式设置,决定annot注释的数字格式,小数点后几位等;
9, cbar : 是否画一个颜色条
10, cbar_kws : 颜色条的参数

pandas的数据结构介绍

要使用pandas,得熟悉提供的两个主要数据结构:Series和DataFrame。

Series

Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关 的数据标签(即索引)组成,感觉和字典有一点相似。Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引,于是会自动 创建一个0到N-1(N为数据的长度)的整数型索引。pandas的isnull和notnull函数可用于检测缺失数据。对于许多应用而言,Series最重要的一个功能是,它会根据运算的索引标签自动对齐数据。

DataFrame

DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字 符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用 同一个索引)。DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构),建DataFrame的办法有很多,最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典。DataFrame构造函数所能接受的各种数据如下所示。

  1. Numpy 中的集合函数
方法   说明
unique(x)   计算 x 中的唯一元素,并返回有序结果
intersect1d(x,y)   计算 x 和 y 中的公共元素,并返回有序结果
union1d(x,y)   计算 x 和 y 的并集,并返回有序结果
in1d(x,y)   得到一个表示“x 的元素是否包含于 y”的布尔型数组
setdiff1d(x,y)   集合的差,即元素在 x 中且不在 y 中
setxor1d(x,y)   集合的对称差,即存在于一个数组中但不同时存在于两个数组中的元素

伪随机数生成,部分 numpy random 函数

函数   说明
seed   确定随机数生成器的种子
permutation   返回一个序列的随机排列或返回一个随机排列的范围
shuffle   对一个序列就地随机排列
rand   产生均匀分布的样本值
randint   从给定的上下限范围内随机选取整数
randn   产生正态分布(平均值为 0, 标准差为 1) 的样本值,类似于 MATLAB 接口
binomial   产生二项分布的样本值
normal   产生正态(高斯)分布的样本值
beta   产生 beta 分布的样本值
chisquare   产生卡方分布的样本值
gamma   产生 Gamma 分布的样本值
uniform   产生在[0,1) 中均匀分布的样本值

这里重点的说一下如何使用 pandas + DataFrame 输出 xlsx 文件,这也是自己在工作中经常会遇到的一个问题,这里字典就会很有用处。这里先介绍下批量生成字符串的一种很简单的方法,比如自己在处理运动指令IP值时,对于机器人来说,有六个轴的,自己写 IP1,IP2,IP3 ..., 久而久之就会很烦的。。。。下面这样就会使得问题变得很简单(类似的,对于字符串可用 %s 来替代)

indexNames = ['IP%d'%i for i in range(1,7) ]

这样配合着字典,比如

for i in range(6):
dict[indexNames[i]] = IP[:,i] #这里IP的矩阵大小为N*6

再利用

df = pd.DataFrame(dic)
df.to_excel('test.xlsx',index=False)

即可将结果输出到 *.xlsx 文件中去了, 这里忘了交代个事,就是需要引入相关的包

import pandas as pd
from pandas import DataFrame

参考

[1] 菜鸟教程

CMakeLists Eigen FCPX GNU Gazebo Git Interest KDL Life Linux Matrix ODE ROS Ros UML Ubuntu VcXsrv algorithm algorithms axis-angle bode calibration chrome control cpp data_struct dots figure gdb latex launch life linux mac math matlab memory motor moveit operator optimal algorithm python robot robotics ros ros2 rtb simulation stl thread tools twist urdf velocity vim web work wsl
知识共享许可协议