机器学习之python基础(二)
综述
这一系列博客是记录我在学习python和机器学习的过程中的一些实践过程和体会,学习python时用到的参考书籍是《python学习手册 第四版》,即《learning python》的中文版。学习机器学习时所用的主要参考书籍是《机器学习实战》,还参考了CSDN博客平台上博客名为zouxy09的部分博客文章(博客后面附有url链接),实现其中的各种算法所使用的程序语言是python,实验平台是Ubuntu14.04,所使用的python版本是2.7.6。如果有博友想要与我进行交流可以在博客后面留言,或者发邮件到我的邮箱zouchaobin@foxmail.com。由于python3.0以后的版本与python3.0之前的版本有较大改变,所以为了某些代码的兼容性(如print函数),也为了便于直接使用《python学习手册》中的源代码(这本书的源代码是基于python3.x的),我决定采用以下处理方式:
from __future__ import print_function from __future__ import division
在每个代码文件的开头加入以上两行代码,这样的话就可以使用python3.x的print函数和除法运算了,这样便于将这些代码稍加修改就能移植到python3.x的平台上。
python表达式
python表达式是处理对象的最基本的工具,当一个数字(或其他对象)与操作符相结合时,python执行时将计算得到一个值。表达式的类型有如下一些:
操作符 描述
yield x 生成器函数发送协议lambda args:expression 生成匿名函数x if y else z 三元选择表达式x or y 逻辑或(只有x为假,才会计算y)x and y 逻辑与(只有x为真,才会计算y)not x 逻辑非x in y,x not in y 成员关系(可迭代对象,集合)x is y,x is not y 对象实体测试x<y, x<=y, x>y, x>=y, x==y, x!=y 大小比较(python中可以使用x<y<z表示x<y and y<z),集合子集和超集值相等性操作符(其中python2.6中x!=y还可写作x<>y,python3.0去掉了后者)x | y 位或,集合并集x ^ y 位异或,集合对称差x & y 位与,集合交集x << y, x >> y 左移或者右移y位x+y, x-y 加法/合并, 减法,集合差集x*y, x%y, x /y, x //y 乘法/重复,余数/格式化,除法:真除法或floor除法(floor除法在python2.6和3.0中都是会把余数小数部分去掉,而x/y在2.6中会截除为整数,3.0会保留小数)-x, +x 一元减法,识别~x 按位求补(取反)x ** y 冥运算(x的y次方)x[i] 索引(序列,映射及其他)点号取属性运算,函数调用x[i,j,k] 分片x(...) 调用(函数,方法,类和其他可调用的)x.attr 属性调用(...) 元组,表达式,生成器表达式[...] 列表,列表解析{...} 字典,集合,集合和字典解析
变量和基本的表达式:
变量在它第一次赋值时创建
变量在表达式中使用将被替换位它们的值
变量在表达式中使用之前必须被赋值(此时才是真正创建变量)
变量像对象一样不需要在一开始进行声明(使用时赋值才声明,这是python不同于C语言等其他语言的地方)
以下是比较结构的表达式:
乘法:
乘法在python中即可以作为普通的数学运算符号,也可以作为“重复”的符号:
除法:
python中支持2种除法:
x / y:
传统除法和真除法,这个操作在python2.6或之前的版本对于整数会省去小数部分只保留整数部分,而对于浮点数会保留小数部分,在python3.0中则没有区别,整数和浮点数都保留小数部分。
x // y:
floor除法,结果会省去小数部分而只保留整数部分
下面的实验调用了__future__模块,故使用的是python3.0以后的操作,对于x/y实现真除法,对于x//y实现floor除法。
由于除法的截断误差在一些精度要求较高的地方容易引起错误,所以在使用的时候需要注意。
print函数
python3.0以后的print做了较大改变:print([object,...][,sep=''][,end='\n'][,file=sys.stdout]),方括号中的参数项是可选的,并且可能会在一个给定的调用中省略,并且=后面的值都给出了参数的缺省默认值,其中sep用于指定把字符串分隔开的一个或多个文本表示,end用于指定字符串结尾符号,这些都将打印到流file中,并且file也是可以指定的,默认为标准输出stdout。个人感觉新的print方法使用起来更方便,所以我在程序的开始加入下面两行来使用python3.0版本以后的新的print方法和新的除法:下面就是print最常用的方法:from __future__ import print_function from __future__ import division
其中的sep参数指定了用何种分隔符来分隔3个对象x,y,z,而end指定了用什么字符来作为整个输出的结束,以下是运行结果:from __future__ import print_function from __future__ import division x = 'I' y = "love" z = 'you' print('$$$1') print(x,y,z) print('$$$2') print(x,y,z,sep='') print('$$$3') print(x,y,z,sep=',') print('$$$4') print(x,y,z,sep='...') print('$$$5') print(x,y,z,end='') print('$$$6') print(x,y,z,end='...') print('$$$7') print(x,y,z,end='!\n') print('$$$8') print(x,y,z,sep=',',end='!\n') print('$$$9') print(x,y,z,sep='...',end='!\n')
此外python3.0以后的print方法的高级用法中还可以打印内容到一个指定的文件或者其他兼容对象,而不是仅仅打印到屏幕,通过指定参数file来实现。
python语句
python中的表达式如下(引自《python学习手册》第四版):
if条件判断语句
python中没有end来声明程序块的结束,也没有花括号{ }来说明,只是靠代码上相同的缩进来区别,缩进的字符数不做要求,但是属于同一个代码块的缩进长度要一致,每行语句末尾也不需要像C语言一样用分号(;)来结束(虽然有分号时python也默认正确)。
python中语句中的圆括号有时是可以省去的,比如 if x<y 等价于 if(x<y),并且往往在行末加上一对冒号(:)来说明下面的代码是属于这个代码块的,并且要求下面的代码缩进一致。对于两个if的说法,如下所示:
则由于else是与第一个if对齐的,所以它属于第一个if,而在C语言中由于它离第二个if最近,所以属于第二个if。a=1 b=2 c=3 s1='love' s2='good' if a==1 and b==2: if c==3: print(s1) else: print(s2)
以下是if判断语句和表达式:from __future__ import print_function from __future__ import division a=1 b=2 c=3 s1='love' s2='good' if a==1 and b==2: if c==3: print(s1) else: print(s2) print('the second one a=2') a = 2 if a==1 and b==2: if c==3: print(s1) print('the end') else: print(s2)
运行结果如下:
while循环语句
while循环的用法跟C语言差不多:
使用python3.4测试运行结果如下:from __future__ import print_function from __future__ import division while True: reply = input('Ener text:') if reply == 'stop': break elif not reply.isdigit(): print('Bad!' * 8) else: print(int(reply) ** 2) print('Bye')
for循环语句
for循环在python中是一个通用的序列迭代器:可以遍历任何有序的序列对象内的元素(包括字符串,列表,元组等)。
运行结果如下:# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import division l = ["spam", "eggs", "ham"] for x in l: print(x, end='\n') t = (1, 2, 3, 4, 5) sum = 0 for x in t: sum = sum + x print(sum) d = {'a':1, 'c':3, 'b':2} for key in d: print(key, '=>', d[key])
for循环在python中用得很多,而且执行效率比while快,在对序列的操作上有很多的优势,并且在很多时候利用很简单的代码可以实现很复杂的功能,比如下面这个例子的way2这种方法就用得很多,大多数时候我们只需要用最简单最少的代码去实现我们的功能,而将更多的后台操作交给python去完成:
# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import division a,b,c = 0, 0, 0 for (a,b,c) in ((1,2,3), (4,5,6)): print(a, b, c) items = ['aaa', 111, (4,5), 2.01] tests = [(4,5), 3.14] print('way1:') for key in tests: for item in items: if item == key: print(key, 'was found') break; else: print(key, 'was not found') #下面几行代码实现了与上面几行代码同样的功能 #但是却用了比上面更少而且更清晰的方法 #这样的代码易懂,也更pythonic print('way2:') for key in tests: if key in items: print(key, 'was found') else: print(key, 'was not found')
另外python中for循环还经常跟range方法联合使用来进行序列的间隔遍历
运行结果如下:# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import division print(list(range(3))) print(list(range(2,6))) print(list(range(1,9,2)))#指定步长为2 l = [1, 2, 3, 4, 5, 6, 7, 8, 9] print(l) for i in range(1,len(l),2): <span style="white-space:pre"> </span>l[i] += 1 print(l)
内置的zip方法也让我们可以并行使用多个序列,当序列的长度不同时,zip会以最短序列的长度来截断所得到的元组:
可以看到,利用range(1,9,2)产生来1-9步长为2的list,然后利用符循环操作了l中的第 2,4,6,8个元素+1。运行结果如下:# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import division l1=[1,2,3,4] l2=[5,6,7,8] l3=[9,10,11,12] l4=[13,14,15,16,17,18,19,20] l = list(zip(l1,l2,l3)) L = list(zip(l1,l2,l3,l4)) print('l:',l) print('L:',L)#当序列的长度不同时,zip会以最短序列的长度来截断所得到的元组 for (x,y,z) in zip(l1,l2,l3): print(x,y,z, '--', x+y+z)
另外还可以使用zip方法构造字典,如下所示:运行结果如下:# -*- coding: utf-8 -*- from __future__ import print_function from __future__ import division keys = ['name', 'age', 'is_student'] values = ['Bill', 20, 'yes'] d1 = dict(zip(keys, values)) print('d1:', d1) d2 = dict(zip(values, keys)) print('d2:', d2)
还有跟更多的有关迭代和循环的方法我们后续用到的时候再来讲解,更多更详细的内容请参考《python学习手册》第四版。