Python

Since Jan.26th,2016

1、ubuntu 下运行 python 的几种方式

  • 在 terminal下,直接python进入交互模式,然后开始正常输入代码,每输入一行就执行一行。

  • 在 terminal 下,python /home/rancho/桌面/test.py,即以默认的 python 版本执行该文件,一次性输出结果,不再是一行一行的了。

  • 在 terminal 下,直接执行./home/rancho/桌面/helloworld.py的命令,前提是需要在【helloworld.py】这个文件中的首行先用#!开头注明使用的解释器。

    注:需要执行属性。

  • 在编辑器中,如 sublime text 3,输入后直接 ctrl+B,即在下方命令窗口中出现执行结果。

2、关于print时代码的多行输入

  • '''…'''用来注释多行(本质上为一串字符串)。

  • \用来转义\n\t等等字符,每个需要转义的字符前都要家加\,而r则用来简化,只要在引号前加r,引号中的就被作为原始字符串输出。
    代码示例如下:
    >>> print('\ttest')
    test
    >>> print('\ttest')
    \ttest
    >>> print(r'\ttest')
    \ttest
    但是,需要特别注意的是r似乎不能把引号本身作为原始字符串输出,只能用\来实现。
    比如输出三个单引号,用r会报错,

    print(r''''')
    

但是用\则正常。

  print('\'\'\'')

另外,正则表达式中的一些特殊符号似乎也不能用r转义,比如输出.就必须用代码\.来实现。

  • 在一个字符串中,行末的单独一个反斜杠表示字符串在下一行继续,而不是开始一个新的行。如下图等价于 "This is the first sentence. This is the second sentence."

    <http://old.sebug.net/paper/python/ch04s03.html>

    注:除了字符串中,\也能起到连接多行的作用。

    <http://old.sebug.net/paper/python/ch04s08.html>

3、递归函数中的ifreturn

  • 递归函数实现的一个重要原因是函数内部调用了它本身,其实也就是return的内容还是不明确的,仍然需要调用它本身来实现的,比如一个表达式。因此一旦当return的内容确定下来,比如变成了一个常熟或是字符串,则这个函数就结束了,return后的语句不会被再次执行。
    比如
    def fact(n):
    if n == 1:
    return 1
    return n*fact(n - 1)

    print(fact(5))
    

输出得到的是120,即5!,事实上当进行到5×4×3×2×fact(1)的时候,由于n == 1,因此return得到的不再是一个表达式,而是常数1,从而,返回的5×4×3×2×fact(1)也成为了一个确定的值,120,函数return一个确定值的目标已经的达到,也就不再进行接下来的语句,即函数调用完毕了。
但是
x=19
if x >= 17:
print(x)
print(x)
则会得到两个19的输出结果,因为if语句的语法中就没有执行后跳过下面所有语句的定义,仍会执行print(x)

4、range()的用法

  • range(n)是指从0到n,但要注意的是0是被包括的,n是不被包括的,也就是0~(n-1)。

我们所做的只是提供两个数,range返回一个序列的数。这个序列从第一个数开始到第二个数为止。例如,range(1,5)给出序列[1, 2, 3, 4]。默认地,range的步长为1。如果我们为range提供第三个数,那么它将成为步长。例如,range(1,5,2)给出[1,3]。记住,range 向上延伸到第二个数,即它不包含第二个数。
在C/C++中,如果你想要写for (int i = 0; i < 5; i++),那么用Python,你写成for i in range(0,5)。你会注意到,Python的for循环更加简单、明白、不易出错。
http://old.sebug.net/paper/python/ch06s04.html

range输出的是有序的。

  • 另一点要注意的是,在for i in range(5)这样的循环中并不是隐藏了i += 1这样的语句(注意 python 中没有i++),而是先通过range(5)生成了一个可遍历的对象(迭代器?),而后对它进行遍历。因此在循环内部改变i的值不影响循环进行。
    举例代码:
for i in xrange(5):
    print i, 
    i = 100
    print i

输出为:

0 100
1 100
2 100
3 100
4 100

显然,每次执行完i = 100的语句并输出后,进行下一次循环时,i又变成了下一个数,而与100无关了。
所以,forrange的这一条组合式的语句有两个意义:
1.提供了一个一定次数的循环。
2.为每次循环提供了一定一个按照固定规律变化的值(i)。

5、输出时* times的用法

  • print('test' * 5)得到输出为testtesttesttesttest

6、enumerate的用法

  • enumerate(列举,枚举)
# iter list with index:
  print('iter enumerate([\'A\', \'B\', \'C\']')
  for i, value in enumerate(['A', 'B', 'C']):
      print(i, value)

https://github.com/michaelliao/learn-python3/blob/master/samples/advance/do_iter.py

得到的输出结果为

iter enumerate(['A', 'B', 'C'])
  0 A
  1 B
  2 C

因此,就可以通过这种方式把list变成索引-元素对,在迭代时同时迭代这二者。

7、isinstance的用法

  • 可以判断一个变量是否是某些类型中的一种(例如第三条就是两种类型)
    >>> isinstance('test', str)
    True
    >>> isinstance('313', str)
    True
    >>> isinstance(313, (int,str))
    True
    还可以用来判断是否是可迭代对象
    from collections import Iterable
    >>> isinstance([], Iterable)
    True
    >>> isinstance({}, Iterable)
    True
    >>> isinstance('test', Iterable)
    True
    >>> isinstance((x for x in range(3)), Iterable)
    True

8、关于内置字符串处理函数

  • 内置字符串处理函数可以看成是是新生成了一个字符串,而[]所在位置不同决定了是先提取再进行函数处理还是先进行函数处理再提取。
    当然,在某些情况下两者有相同的效果,比如下面的两段代码就分别自定义了一个首字母大写,其他小写的函数,输出效果完全相同。
    这是第一段:
    def normalize(name):
    return name.upper()[0] + name.lower()[1:]

    L1 = ['adam', 'LISA', 'barT']
    L2 = list(map(normalize, L1))
    print(L2)
    

这是第二段:
def normalize(name):
return name.upper()[0] + name.lower()[1:]

  L1 = ['adam', 'LISA', 'barT']
  L2 = list(map(normalize, L1))
  print(L2)

输出结果都是
['Adam', 'Lisa', 'Bart']

9、关于在dictionary中通过value查找key

  • 用迭代实现

    search_age = 19
    dict = {'george':16, 'amber': 19}
    for x, y in dict.items():
        if y == search_age:
            print(x)
    

输出结果为

  amber

特别注意:上述的x和y都是任意更换的,完全可以换成name和age,即字典被创建的时候key和value是没有变量来指向的,无论是x,y还是name,age都是临时用来迭代的。

10、关于切片

  • 对于y = x[a:b:c]
    当c > 0时,a,b缺省值为0,len[x]。
    当c < 0时,a,b缺省值为-1,-len[x] - 1。因此y = x[::-1]即为x的倒序。

11、关于字符串或list相等的比较

  • 如果要比较两个字符串或list是否相等,可以直接用==进行比较。

12、关于字符串和list的方法

  • list的方法似乎是直接作用于list本身的。
    fs = []
    fs.append('test')
    print(fs)
    输出为
    ['test']
  • 字符串的方法似乎是创建了一个新的字符串,而非直接作用于字符串本身。
    gs = 'GGG'
    gs.lower()
    print(gs)
    输出为
    GGG

13、关于python输出时取消自动换行

  • 在python2中是在句末直接加,即可
    a = [1,2,3,4,5]
    for i in a:
    print i,
    得到输出
    1 2 3 4 5
  • 在python3中是用end来控制,不光可以取消换行,还可以任意设定间隔
    a = [1,2,3,4,5]
    for i in a:
    print(i, end = ' ')
    得到输出
    1 2 3 4 5
    又比如
    a = [1,2,3,4,5]
    for i in a:
    print(i, end = '\t')
    得到输出
    1 2 3 4 5

14、含有0个或1个项目的元组

  • 含有0个或1个项目的tuple

一个空的元组由一对空的圆括号组成,如myempty = ()。然而,含有单个元素的元组就不那么简单了。你必须在第一个(唯一一个)项目后跟一个逗号,这样Python才能区分元组和表达式中一个带圆括号的对象。即如果你想要的是一个包含项目2
的元组的时候,你应该指明singleton = (2 , )
http://old.sebug.net/paper/python/ch09s03.html

也就是说
string = (2)
print(5 - string)
这时string被认为是一个int,输出为
3

string = (2,)
print(5 - string)
此时string才被认为是一个tuple,会报错。

15、关于字典增加元素

  • dictionary增加元素与list不同,它没有append方法(应当注意到dict是无序的)。
    直接为dictionary创建一个键/值对即可。
    she = {}
    she['lomo'] = 'test'
    print(she)
    输出为
    {'lomo': 'test'}
    事实上,代码和更改一个key对应的value是一样的,不过当这个key已经存在的时候是更改,而当它不存在的时候则是创建。

16、关于file和open方法

  • python2中fileopen基本没区别,而在python3则没有了file的方法。
    f = open('poem.txt', 'w')
    以上代码是可行的,直接创建了文件,而若将open换为file,则在python3中是会报错的。

17、关于pickle模块

  • python2中含有CPickle和pickle模块(注意大小写),而python3中移除了CPickle模块。
  • python2中储存器模块使用中使用的是rw等,而python3中则需要用rbwb等,b表示二进制。

18、关于range和xrange

  • python3中已经取消了xrange,而python2中xrangerange共存。

19、关于decode和encode

  • decode是把其他编码方式编码的字符串转换成用unicode编码的字符串。
    str.decode('utf-8')
    上述代码表示把utf-8编码的字符串转换成用unicode编码的字符串。
  • encode则是相反,把unicode编码的字符串转化为其他编码方式编码的字符串。
    str.encode('utf-8')
    上述代码表示把unicode编码的字符串转换成用utf-8编码的字符串。
    可能在爬虫爬取的网络数据的写入读出时会用到以上两种编码方式。

19、关于正则表达式

  • {m,n}中,逗号,前后不可有空格(容易习惯性地在逗号后面加空格),总之,在书写正则表达式的时候,不用考虑美观问题的空格,怎么简洁贴切怎么来。
  • .能匹配任意除\n以外的字符,因此.*?只适合于一行内的任意匹配,而要跨行匹配的话,应当使用[\s\S]*?\s匹配空白符,\S匹配非空白符)。
  • ^一般表示匹配字符串开头或多行字符串的每一行开头,但当它以这样的形式[^...]出现时,表示取反,如[^abc]表示不是 abc 的其他字符。

20、关于文件读写

  • open('/home/rancho/test.txt', 'module')module可以是以下几种

r 只能读
r+ 可读可写,不会创建不存在的文件。如果直接写文件,则从顶部开始写,覆盖之前此位置的内容,如果先读后写,则会在文件最后追加内容。
w+ 可读可写 如果文件存在 则覆盖整个文件 不存在则创建
w 只能写 覆盖整个文件 不存在则创建
a 只能写 从文件底部添加内容 不存在则创建
a+ 可读可写 从文件顶部读取内容 从文件底部添加内容 不存在则创建
https://segmentfault.com/q/1010000003813594

  • 在打开一个文件的情况下,只要不关闭,写入是可以进行多次的,并且是连续的,每次都是在上次的基础上继续写入的。即在一个with…as…块中,可以多次使用write方法,后面的不会覆盖前面的。
    但是一旦关闭文件后,再次打开时,如果用的是w模式,则会全部覆盖重写。
  • 对于readreadlines两个方法,都只能读取一次,再进行读取就会变空白。而readline则可以进行逐行读取,虽然表面是多次读取,实际上每短文本内容也只被读取了一次。
  • 对于非二进制文件(纯文本),使用w读写方式;而对于二进制文本(音乐,视频,图像等),要采用wb读写方式,不然可能会出现问题(不同的系统下可能问题不一样)。
  • 对于w+,实际上是不能读取到原文件内容的,因为它会先执行清空操作。也就是说你能够读取到的是你写入的内容。

21 、关于urllib(urllib2)模块

  • urllib2和urllib在python3中合并为了urllib,而在python2中主要区别在于urllib2可以接受一个Request类的对象,从而可以设置headers等。
  • response = urllib.urlopen('https://www.baidu.com/')后想要取得网页的源代码,需要用read方法,response.read()得到的是一个字符串,这里有两点需要注意:
    • read方法使用后response就变为空了,也就是read方法只能用一次,而后无论是使用response还是response.read()得到的都不是刚才的数据了。
      比如说要在使用response.read()的同时测得字符串长度,则应该先foobar = response.read()把其保存在其他变量里,然后再对foobar使用len函数。
      可以通过一下以下代码感受一下
      import urllib
      import re

      url = 'http://tieba.baidu.com/p/3138733512?see_lz=1&pn=5'
      response = urllib.urlopen(url)
      print len(response.read())
      print len(response.read())
      

输出为
212251
0

  • read得到的网页源代码往往很长,会保存在内存中进行接下来的一系列操作,每对一段进行操作后最好要及时将它写入文件,不要累加在同一个变量下多次分块操作后最后统一写入文件,这样容易导致内存爆掉。

22、关于PyQt

  • 设定快捷键时在+前后不要留空格,即输入一个完整的字符串。
  • 在坐标系指定位置时(一般以px为单位),从左上角开始,x 从左到右,y 从上到下。
    但碰到网格布局时,是一行一行从上往下来的,然后再是一列一列从左往右去的,比如(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)

23、关于中文字符编码

  • 在 python2.x 中,加入以下代码可以解决绝大多数问题
    # -- coding: utf-8 --
    import sys
    reload(sys)
    sys.setdefaultencoding( "utf-8" )
    • 第一行主要是解决 python 文件(源文件)对字符串的编码。
    • 后三行主要是更改系统(指的是具体的操作系统,比如 ubuntu )默认的编码方式,因为在 python2.x 中,encode函数无所谓直接从一种格式到另一种格式,但decode函数在转化时需要用系统默认编码作为中介,而默认的一般是 ascii ,不支持中文,所以即使转换的双方是 unicode 和 utf-8 ,都支持中文,仍然报错。所以这三行主要是解决由于打开文件,网页源码获取等等广泛的 python 应用过程中引起的编码格式转化问题。
    • 以上解决绝大多数问题是指 python 解释器不会报错,但是仍可能碰到乱码问题,这就需要再次用decodeencode函数进行转化了。
    • 需要注意的是,真正的原理并不像上述文字说的那么简单,涉及到 python2.x 中的字符串和 byte 数组类型, python 有时会自动地转化编码格式等等问题,因此有时可能会碰到编码问题不在上述文字阐述理解的范围内,但实际上都是 python2.x 在编码上的一个设计问题(据说要考虑到兼容性),而 python3.x 似乎对这方面就有所改善,在字符串和 byte 数组类型上有改变。

24、关于错误处理时的 try 语句

  • try…except…是一个组合,不可拆分,即不可单独使用try。当然在语句块最后加finally是可以的

25、关于 Windows 和 Linux 跨平台的问题

  • 文件路径
    • 使用os.absname('.')查看得到的当前目录可能是当前的 python 文件(.py)所在目录,但也可能是编辑器或者 IDE 所在目录。所以要选择当前 python 文件(.py)所在目录应当避免使用os.absname('.'),虽然在某些情况下得到的是我们想要的。

      可以使用以下几种方式:

      • sys.argv[0]得到的是当前 python 文件(.py)的绝对路径,若要查看目录,则可以用os.path.dirname(sys.argv[0]),保险起见可以使用os.path.abspath(os.path.dirname(sys.argv[0])),记得先导入os即可。
      • os.path.dirname(__file__)也是可以得到当前 python 文件(.py)所在目录的。

      跨平台编译时路径的准确性尤显重要因此,因此可以定义一个通过上述的代码定义一个basepath作为基础目录,而资源文件(与 python 文件放在同一目录下)绝对路径可以用以下代码实现
      basepath + os.sep + 'background.jpg'

    • 路径前最好加上r,若在 linux 下问题不大,但在 windows 下,会出现\的转义问题,因此最好养成习惯,只要有路径,就使用r
      例子如下,此为 ubuntu 下代码
      'background.jpg'
      此为 windows 下代码
      r'C:\Users\Rancho\Desktop\background.jpg'

26、判断变量或字符是否为整数的方法

  • 判断变量
    一般来说用isinstance是可行的,但是不幸的是,布尔值也是int下的一个子类,因此isinstance(True, int)会得到True的输出,故此判断是否是整数的更合适的方法,应当是使用type(3) == int来判断。
    注意print int, type(3), type('test')结果如下:
    <type 'int'> <type 'int'> <type 'str'>
    注意正则表达式针对的是字符串,也就是说你要是想用它来判断必须要先将当前变量转化为字符串,而正则表达式判断出来也只是这个字符串所携带的信息是否是整数,和从根本上判断上变量是否是整形变量还是有区别的。
  • 判断字符
    除了使用正则表达式,也可以使用'isdigit'方法,
    test = '313'
    print test.isdigit()
    test = 'lomo'
    print test.isdigit()
    输出为
    True
    False
    同理,对于判断字母(注意是判断字符是否为字母),有isalpha方法。
    但要注意的是,bool 类型的变量没有isdigitisalpha之类的方法,若使用会报错。

27、关于 and 和 or 以及 not 的优先顺序

  • and 优先于 or
  • not 会和紧邻的结合

28、关于删除数组中元素的几种方法(del,remove,pop)

  • remove是通过指定value,并且用从头开始搜索的方式来删除第一个符合的元素,要求输入的变量为 value
    test = ['t', 'e', 's', 't']
    test.remove('t')
    print test
    test.remove(test[0])
    print test
    输出为
    ['e', 's', 't']
    ['s', 't']
  • pop是通过指定索引来确定要删除元素的位置,要求输入的变量为 index ,同时还会返回被删除的 value
    test = ['t', 'e', 's', 't']
    print test.pop(3)
    print test
    输出为
    t
    ['t', 'e', 's']
  • delremove类似,也是通过指定 value 来删除的,但因为它不是数组的方法,因此还要指定数组
    test = ['t', 'e', 's', 't']
    del test[3]
    print test
    输出为
    ['t', 'e', 's']
    注意,
    • 不可以把del test[3]替换为del 't'
    • delremove一样,作为通过 value 来删除的方法,都是从头搜索,一旦遇到符合条件的即删除,然后结束,也就是只会删除第一个符合条件的。因此要精确删除的话,还是需要pop来指定索引位置的。

29、关于排列组合

  • 可以通过itertools这个库来实现快速的排列组合,组合使用combinations函数,排列使用premutations函数。两者都接受参数来指定挑选的元素的个数
    import itertools
    test = [1,2,3]
    print list(itertools.combinations(test, 2))
    print list(itertools.permutations(test, 2))
    输出为
    [(1, 2), (1, 3), (2, 3)]
    [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
    注意到,itertools是个迭代器的库,因此对于combinationspermutations两个函数的返回结果都是迭代器,如果需要一次性输出的需要转化为 list 形式。

30、关于 set 和 list 的性能问题

  • 二者性能差距很大,set可能比list快上百倍以上,因此对大数据的遍历,查找,删除等,尽量利用set,或者将list转为set后进行操作。

31、爬虫中将cookie的字符串转化为字典形式

  • pre = "utf8=✓&authenticity_token=P/W5Eok1+QuvE2FgNomsDbFYBWYNWl1zv0a2K3smQjTPXeafoVXuJYnzWStGl4jzxZq8TKSbsXsFoBcL1uRo8A==&entry[field_1][]=UlT9&commit=提交"
    cookies={} 
    for line in pre.split('&'): 
    #其设置为1就会把字符串拆分成2份
        name,value=line.strip().split('=',1)
        print name,value
        cookies[name]=value
    

以上代码将&作为连接字符,具体因情况而变。

32、scipy内模块的导入问题

  • 大概就是说scipy是一系列模块的集合,如果你只import scipy,那么 optimize 等这些模块是不会自动导入的,所以你需要这样导入,from scipy import optimize,然后就可以使用scipy.optimize了。
    https://github.com/scipy/scipy/issues/4005

33、科学计算时的浮点数和整数

  • python2 中科学计算时还是不要用from __future__ import division来用\表示精确除法代替原本的截断除法(只取结果整数部分)了,因为这仅仅在普通表达式中起效,当用到一些第三方库的时候,就不一定识别\为精确除法了。所以目前建议,简单的计算的话,还是把每个数都写成浮点数而非整数形式好了。

33、解方程

  • 一般使用sympy.solvescipy.optimize.fsolve
    https://www.zhihu.com/question/34987285
    • 因为 lambda 函数的特殊性,我现在还没有找到 python 中方便快速的字符串转 lambda 的方法,因此有时候scipy.optimize.fsolve还是挺不适合的。
    • 要注意sympy.solve得到的是一个数组。

34、求导数

  • 一般使用sympy.diff,接受参数是一个字符串。
    输入:
import sympy
expression = sympy.diff('3.0*x**2.0+2.0*x')
print expression
print type(expression)

输出:

6*x + 2
<class 'sympy.core.add.Add'>

还可以配合sympy.solve一起使用(求导数的零点):

x0 = sympy.solve(sympy.diff(expression))
print x0
[-0.333333333333333]

35、numpy 中的 mgridmeshgrid

  • meshgrid用法(用()
>>> x1 = np.arange(1, 11, 2)
>>> y1 = np.arange(-12, -3, 3)
>>> x1, y1 = np.meshgrid(x1,y1)
>>> x1
array([[1, 3, 5, 7, 9], 
         [1, 3, 5, 7, 9],
         [1, 3, 5, 7, 9]])
>>> y1
array([[-12, -12, -12, -12, -12],
         [ -9, -9, -9, -9, -9],
         [ -6, -6, -6, -6, -6]])
  • mgrid用法(用[]
>>> x2, y2 = np.mgrid[1:11:2, -12:-3:3]
>>> x2
array([[1, 1, 1],
        [3, 3, 3],
        [5, 5, 5],
        [7, 7, 7],
        [9, 9, 9]])
>>> y2
array([[-12, -9, -6],
        [-12, -9, -6],
        [-12, -9, -6],
        [-12, -9, -6],
        [-12, -9, -6]])

另一种用法是不提供步长参数,但提供数量参数

xs,ys = np.mgrid[-4:1:30j,0.8:1.1:30j] 

其中的30j表示的是从 start 到 end 的总个数,如果两个不一致,会取大的那个。保证两者个数一致。

36、matplotlib 画图

  • 2D 折线图或散点图
import matplotlib.pyplot as plt
plt.figure()
ax = plg.gca()
ax.set_aspect(1) # 使横纵坐标轴对单位区间的实际长度(axes per unit length)相等
plt.plot(x,y,'rx-',linewidth=2,markersize=5,label='test')
plt.xlim([-1,1])
plt.title()
plt.xlabel()
plt.ylabel()
plt.legend()
plt.show()
  • 3D 折线图
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
ax.plot(xs,ys,'rx-',zs=zs,linewidth=2,markersize=5,label='test')
ax.set_zlim([-1,1])
plt.title()
ax.set_title()
ax.set_xlabel()
ax.set_ylabel()
ax.legend()
plt.show()
  • 3D 曲面图
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

  k,b=np.mgrid[1:3:3j,4:6:3j]
  f_kb=3*k+2*b+1

  fig = plt.figure()
  ax = fig.add_subplot(111,projection='3d')
  ax.plot_surface(k,b,f_kb)
  plt.show()

在画 3D 图前,我们一般用mgridmeshgrid来生成需要 x,y轴上的变量矩阵。画 3D 图的要求是 z 矩阵的行数等于 x 矩阵的行数列数等于 y 矩阵的列数。也就是由如下的对应关系(以 3 阶矩阵为例):

y1,1 y1,2 y1,3
x1,1 z1,1 z1,2 z1,3
x2,1 z2,1 z2,2 z2,3
x3,1 z3,1 z3,2 z3,3

mgrid为例,我们看mgrid生成的矩阵可以发现,x 的每一行都是一样的,而 y 的每一列都是一样的,这其实是为了代入 z 的函数进行计算比较方便,比如 z 就可以直接生成z = 2*x + 3*y,正好是一一对应的。
colorbar:注意,如果要显示 colorbar,需要在 plot_surface 时先指定映射

from matplotlib import cm
 ax.plot_surface(k,b,f_kb,cmap=cm.coolwarm)
fig.colorbar(surf, shrink=0.5, aspect=5)
ax.legend()
  • 等高线图(2D 和 3D)
    2D 代码:
k,b=np.mgrid[1:3:3j,4:6:3j]
f_kb=3*k+2*b+1

  fig = plt.figure()
  ax = fig.add_subplot(111)
  ax.contour(k,b,f_kb,np.logspace(-2, 2, 70))
  plt.show()

在处理数据时和 3D 曲面图是一样的,都是用到了mgridmeshgrid函数,而上述代码中contour的第四个参数是指 z 轴取 0.01 到 100 之间,并划分成70个平面,即有 70 条等高线充满这个范围(但实际显示可能不到70条,因为还要看 x 轴和 y 轴的范围限制)。

如果我只想画出 z=1,z=2,z=3 这 3 条等高线呢?
plt.contour(X, Y, Z,[1,2,3])

要注意的是contour(X, Y, Z,1)的意思是只画一条等高线出来,至于是哪一条,就不知道了,而contour(X, Y, Z,[1])的意思是画出 z=1 的这一条等高线。
http://blog.csdn.net/william_2015/article/details/47304687

如果需要对等高线加上图例,不能直接通过ax.contour(xc,yc,zc,label='text')实现,而需要单独设置,比如:

CS = ax.contour(xc,yc,zc)
CS.collections[0].set_label('text')
ax.legend()

同样地,设置 linewidth 等属性也类似,使用CS.collections[0].set_linewidth(2)等语句来实现。
其实,等高线图可以直接在图上标出每条线代表的值,而不需要通过图例。具体代码如下:

CS = ax.contour(xc,yc,zc)
ax.clabel(CS)

因为这不是图例,所以不需要legend方法即可显示。
最后,如果要画 3D 的等高线图,只要将

ax = fig.add_subplot(111)

改为

ax = fig.add_subplot(111,projection='3d')

即可。

  • 在同一个 figure 中同时画 2D 和 3D
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212,projection='3d')
plt.show()
  • 3D 图中坐标轴的隐藏,背景颜色的设置等
color_bg = (0.1843,0.3098,0.3098)
color_green = 'g'
color_yellow = '#f06215'
color_white = '#ffffff'
color_red = 'r'
fig = plt.figure(facecolor=color_bg) # 设置外围颜色
fig.suptitle('3D Realtime Re-modeling',color=color_white) # 设置主标题颜色
ax = fig.add_subplot(111,projection='3d',axisbg=(0.1843,0.3098,0.3098)) # 设置画图区域背景颜色
ax.w_xaxis.set_pane_color(color_bg) # 设置坐标平面颜色
ax.w_zaxis.line.set_lw(0.) # 设置 z 轴线宽(类似语句对 x,y无效)
ax.tick_params(axis='x', colors=color_white) # 设置坐标轴刻度颜色
ax.set_xlabel('x',color=color_red) # 设置坐标轴标签颜色
ax.set_xlim([1,6]) # 设置坐标轴范围
ax.set_yticks(np.linspace(1,4,4)) # 设置坐标轴刻度
ax.set_zticks([]) # 设置坐标轴无刻度
plt.gca().invert_yaxis() # 翻转坐标轴

如果要设置网格线参数,需要在实例化 figure 之前设置如下代码:

from matplotlib import rcParams
rcParams['grid.linestyle'] = '-'
rcParams['grid.color'] = 'g'
rcParams['grid.linewidth'] = 0.5

如果要隐藏所有坐标轴:

ax._axis3don = False
  • 动态画图(实时更新)
    正常情况下plt.show()会阻塞线程,因此需要plt.ion(),这样的话plt.show()就不会阻塞线程,程序可以继续运行。但是图像仍然不会更新,需要使用循环plt.pause(0.05),在这 0.05s 的时间内更新图像并支持鼠标移动,因为是循环,所以感觉不到明显的阻塞。如果 pause 时间过长的话,那么这段时间内新的数据就会无法绘制图像,会导致图像绘制的延迟。
  • 设置坐标轴
    注意ax.set_yticks或者plt.yticks都要在plot后执行才能生效。
  • 设置 subplot 之间的间距
plt.subplot(121)
plt.plot(x_list, y_list)
plt.subplots_adjust(wspace = 0.05, hspace=0.05)

关于 subplots_adjust 的参数说明:

subplots_adjust(left=None, bottom=None, right=None, top=None,
                wspace=None, hspace=None)
left  = 0.125  # the left side of the subplots of the figure
right = 0.9    # the right side of the subplots of the figure
bottom = 0.1   # the bottom of the subplots of the figure
top = 0.9      # the top of the subplots of the figure
wspace = 0.2   # the amount of width reserved for blank space between subplots,
               # expressed as a fraction of the average axis width
hspace = 0.2   # the amount of height reserved for white space between subplots,
               # expressed as a fraction of the average axis height
  • 消除保存的图片两侧的空白
    在 jupyter 中看图片两侧可能没有空白,但保存下来的图片会显示有空白,消除空白的方法是在保存时加上bbox_inches='tight'
fig = plt.figure()
fig.savefig('test.png', bbox_inches='tight')
  • 保存高质量的图片
    使用 svg 格式(可能会很大,可以和 raw 格式匹敌)或者高 dpi 的 png 格式
fig = plt.figure()
fig.savefig('test.png', dpi=600)
fig = plt.figure()
fig.savefig('test.svg')

37、numpy 中为矩阵添加一行(列)和在同一行(列)中添加元素

  • numpy.c_
>>> a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> b = np.ones(3)
>>> np.c_[a,b]
array([[ 1.,  2.,  3.,  1.],
         [ 4.,  5.,  6.,  1.],
         [ 7.,  8.,  9.,  1.]])

其实有好几种实现函数,见http://www.tuicool.com/articles/ZVrUjq3

  • numpy.append
>>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.append(np.array([1,2,3]),[4,5,6])
array([1, 2, 3, 4, 5, 6])

38、numpy 中 array 的复制

  • 不能直接使用 =或切片([:]),应该使用显式复制,即copy
import numpy as np
a = np.array([[1,2,3]])
b = np.copy()

这一点和 list 不同,对于 list,=不会复制数据,而切片可以。对于 numpy 中的 array,=和切片都不会复制数据,需要copy才可以。
参考http://blog.csdn.net/xidianliutingting/article/details/51682867

39、numpy 中 array 和 matrix 对一维的处理

  • array 把一维看成列向量,而 matrix 则看成以行数为 1 的矩阵(行向量

    In [1]: np.array([1,1,1]).shape
    Out[1]: (3,)
    In [2]: np.matrix([1,1,1]).shape
    Out[2]: (1, 3)
    

40、pandas 基本操作

  • 按标签取出一行(得到series):df.ix['lable'](比如在使用 describe之后)

    # df is a dataframe
    
  • 求标准差:pandas 求标准差是样本标准差(N-1),numpy 求标准差是总体标准差(N)。因此需要求样本标准差(无偏)时,

    df.std()
    

    需要求总体标准差时,需要用values转成 numpy 的 array 计算,

    df.values.std()
    

41、超长字符串的声明

  • 特殊格式

    long_string = (
        'Lorem ipsum dolor sit amet, consectetur adipisicing elit, '
        'sed do eiusmod tempor incididunt ut labore et dolore magna '
        'aliqua. Ut enim ad minim veniam, quis nostrud exercitation '
        'ullamco laboris nisi ut aliquip ex ea commodo consequat. '
        'Duis aute irure dolor in reprehenderit in voluptate velit '
        'esse cillum dolore eu fugiat nulla pariatur. Excepteur sint '
        'occaecat cupidatat non proident, sunt in culpa qui officia '
        'deserunt mollit anim id est laborum.'
    )
    

    参考http://stackoverflow.com/questions/8577027/how-to-declare-a-long-string-in-python

42、缺失值(NAN)

  • 缺失值不能用==判断

    In [11]: None == None
    Out[11]: True
    In [12]: np.nan == np.nan
    Out[12]: False
    
  • 可以使用pandas.isnull()来判断单个数据是否是NAN

43、字典 key 搜索

44、requests 库

  • 消除 SSL warning
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容