Python学习笔记与实战(上)

我最近在查看别人开发的一些脚本工具,发现有人用Python写了一些好用的脚本工具,于是我也开始学习了一下,这里把这几天学习到的一些感悟记录下来。另外一个就是能给学习Python的iOS开发同学做点入门普及。
我稍后会用Python写一个脚本工具,用于扫描我们工程文件中不再使用的类(UnUsedClasses).

Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言。它是一种解释型的语言,而我们平常用的Objective-C是编译型的语言。两者的区别在于Objective-C每次都要把代码通过编译器编译成机器能够读懂的机器码。而Python则是在运行的时候一行一行地翻译成机器码。所以Python的运行速度是比编译型的语言要慢的。
但是Python语言是一种跨平台、更加高级的语言,简洁优雅,便于快速开发。在学习过程中,我也发现Swift语言与Python之间有着许多相通之处。

在开发Python之前,我们首先需要安装Python.然而幸运的是,我们的Mac OS已经集成了Python2.7版本。通过调用终端,输入python,我们就可以查看当前的Python版本,如果没有的话,请升级你的Mac OS系统的版本即可,如下图:
Image

除了有开发环境外,我们还需要一个开发工具Sublime Text,其实Sublime Text这个工具的用处还挺多的,它还可以用来开发Lua。但是它们都有一些共同的弱点,都无法进行断点调试,需要自己打印日志来分析里面的代码。

此外我也是参考了廖雪峰同学的Python教程,他的这些系列教程相对比较入门,同时一些不懂的地方也自行google查询了,下面就开始进入正题吧。

让我们从Hello,world!开始:
如下图:
Image
这里要注意的是,我们用Sublime Text工具写的代码时,记得在顶部加上#!/usr/bin/env python,这样我们在接下来就能够获得一些简单的语法提示(如果要添加注释的话,使用#就可以了,与我们平时使用的//稍微有点不同),写了这一句话以后,我们如何运行我们的Python程序呢?

首先我们要把我们的程序另存为一个后缀为.py的文件,存放在磁盘的任意位置,然后再到我们的终端,输入如下命令python py文件路径
Image
如果你觉得麻烦的话,可以通过命令chmod a+x HelloWorld.py来达到直接运行的目的,其中HelloWorld.py为文件所在的路径地址,下次我们直接在终端上面输入py文件的路径地址就可以执行了。

此外我们也可以直接在终端上面输入Python语句来进行调试,方法是,先输入python回车,再输入Python语句,例如print 'Hello,World!',再回车,我们就可以看到下面打印的内容了。

下面对Python的一些基础语法进行一下分析,一些高级特性就不介绍了(也没有能力介绍)。

print

print 'hello, world'print 'hello, world''其实是一样的,也就是单引号与双引号并没有什么区别。
与Swift一样,我们并不需要在执行语句后面添加;,直接回车换行就可以了。

如果想要把几个字符串连接起来打印,直接使用逗号,就可以了,逗号所在的位置会被替换为空格。

>>>print 'The quick brown fox', 'jumps over', 'the lazy dog'
The quick brown fox jumps over the lazy dog

同时也支持运算结果的输出

>>>print '100 + 200 =', 100 + 200
100 + 200 = 300

格式化输入可以使用关键字%

>>> print 'Hello, %s' % 'world'
Hello, world

类似于C++里面的cin>>,我们也可以raw_input关键字来输入相关内容,例如

name = raw_input('please enter your name: ')
print 'hello,', name

字符串String

Python默认是ASCII编码,如果要输入中文内容的话,需要在顶部加上# -*- coding:UTF-8 -*-,这样我们就可以打印中文了。我们也可以通过关键字ordchr对字母和对应的数字相互转换

>>> ord('A')
65
>>> chr(65)
'A'

Unicode表示的字符串用u'...'表示.同时也可以用关键字encode()来进行转换

>>> u'ABC'.encode('utf-8')
'ABC'
>>> u'中文'.encode('utf-8')
'\xe4\xb8\xad\xe6\x96\x87'

关于String的更多用法
1、子字符串的提取 str[:6]
2、字符串包含 判断操作符:innot in

"He" in str
"she" not in str

String模块,还提供了很多方法,如
S.find(substring, [start [,end]]) #可指范围查找子串,返回索引值,否则返回-1
S.rfind(substring,[start [,end]]) #反向查找
S.index(substring,[start [,end]]) #同find,只是找不到产生ValueError异常
S.rindex(substring,[start [,end]])#同上反向查找
S.count(substring,[start [,end]]) #返回找到子串的个数
S.lowercase() #所有小写字母
S.uppercase() #所有大写字母
S.capitalize() #首字母大写
S.lower() #转小写
S.upper() #转大写
S.swapcase() #大小写互换
S.digits() #数字0~9
S.letters() #所有字母(大小写)
S.printable() #可打印字符的字符串
S.punctuation() #所有标点
S.split(str, ' ') #将string转list,以空格切分
S.join(list, ' ') #将list转string,以空格连接
len(str) #串长度
cmp("my friend", str) #字符串比较。第一个大,返回1,也可以直接使用==
max('abcxyz') #寻找字符串中最大的字符
min('abcxyz') #寻找字符串中最小的字符
oat(str) #变成浮点数,float("1e-1") 结果为0.1
int(str) #变成整型, int("12") 结果为12
int(str,base) #变成base进制整型数,int("11",2) 结果为2
long(str) #变成长整型,
long(str,base) #变成base进制长整型

数组List

Python内置的一种数据类型是列表:List,而且这个list默认是可变数组,即可以动态地插入、删除里面的元素。同时List里面的元素类型可以是多样化的,既可以存放字符串,也可以存放数字,感觉这一点确实NB,因为我们所接触到的语言里面大多都只能存放一种数据类型。

>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates
['Michael', 'Bob', 'Tracy']

同样的,我们可以使用关键字len()来获取数组里面元素的个数,append()在末尾追回元素,pop()删除末尾的元素等等,其更加具体的操作如下:
list的方法
L.append(var) #追加元素
L.insert(index,var) #在指定位置插入元素
L.pop(var) #返回最后一个元素,并从list中删除之
L.remove(var) #删除第一次出现的该元素
L.count(var) #该元素在列表中出现的个数
L.index(var) #该元素的位置,无则抛异常
L.extend(list) #追加list,即合并list到L上
L.sort() #排序
L.reverse() #倒序
List 操作符:,+,*,关键字del
a[1:] #片段操作符,用于子list的提取
[1,2]+[3,4] #为[1,2,3,4]。同extend()
[2]*4 #为[2,2,2,2]
del L[1] #删除指定下标的元素
del L[1:3] #删除指定下标范围的元素
List的复制
L1 = L #L1为L的别名,用C来说就是指针地址相同,对L1操作即对L操作。函数参数就是这样传递的
L1 = L[:] #L1为L的克隆,即另一个拷贝,这里是一个浅拷贝。

字典Dictionary

dict = {'ob1':'computer', 'ob2':'mouse', 'ob3':'printer'}

但这里要注意的是keyIntegerstring类型,value可以是任意类型。

Dictionary的方法
D.get(key, 0) #同dict[key],多了个没有则返回缺省值,0。[]没有则抛异常
D.has_key(key) #有该键返回TRUE,否则FALSE
D.keys() #返回字典键的列表
D.values() #返回字典值的列表

D.update(dict2) #增加合并字典
D.popitem() #得到一个pair,并从字典中删除它。已空则抛异常
D.clear() #清空字典,同del dict
D.copy() #拷贝字典
D.cmp(dict1,dict2) #比较字典,(优先级为元素个数、键大小、键值大小) 第一个大返回1,小返回-1,一样返回0

Dictionary的复制
dict1 = dict #别名
dict2=dict.copy() #克隆,即另一个拷贝。

元组Tuple

这个和Swift语言里面的是一样的
tuple = ('a', 'b', 'c', 'd', 'e')
可以用List[],:操作符提取元素,就是不能修改里面的元素,可以与List互相转换。
调用方法为tuple(ls)list(ls)

条件判断

Python中if语句后面要接冒号:,里面的执行语句通过缩进来实现,else if可以简写为elif,例子如下,条件判断时不需要加(),只要是bool值为True或者是False就可以了。

age = 3
if age >= 18:
    print 'adult'
elif age >= 6:
    print 'teenager'
else:
    print 'kid'

循环与遍历

对数组进行遍历,我们可以使用下面的方法,这一点Swift也与Python很像

names = ['Michael', 'Bob', 'Tracy']
for name in names:
    print name

也可以通过关键字range()来进行循环,range是一个0到小于某个值的区间,如range(100)表示0到99之间的数字。

sum = 0
for x in range(101):
    sum = sum + x
print sum

函数

我们可以通过def来定义一个函数,参数可以直接在()内填写,可以传多个参数,以及默认参数,这点与c++是类似的,所不同的时,其可以返回元组对象,可以理解为多个对象,这与Swift也是一致的。

import math #导入math模块

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny

>>> r = move(100, 100, 60, math.pi / 6)
>>> print r
(151.96152422706632, 70.0)

文件操作

获取文件夹下面的所有文件,通过os.listdir()可以遍历到里面的所以文件,通过os.path.join(rootDir, lists)方法可以把文件路径拼成一个绝对路径。通过os.path.isdir()方法可以判断当前是不是一个文件夹。

import os #导入os模块

def getAllFile(rootDir): 
    for lists in os.listdir(rootDir): 
        path = os.path.join(rootDir, lists) 
        resourcefile.append(path)
        if os.path.isdir(path): 
            getAllFile(path) 

getAllFile('文件夹目录')

此外,我们也可以通过os.walk来遍历文件夹,

import os #导入os模块

for root, dirs, files in os.walk(srcdir, topdown=False):
    for name in files:
         print name

其中,root为根目录,dirs为文件夹,而files为文件。

os.path.splitext()可以直接获取文件的扩展名,而
os.path.split()可以拆分路径

>>> os.path.split('/Users/michael/testdir/file.txt')
('/Us
ers/michael/testdir', 'file.txt')
>>> os.path.splitext('/path/to/file.txt')
('/path/to/file', '.txt')

更多关于os模块的操作请参考os模块

正则表达式

一些基础的正则表达式内容可以参考我之前写的内容,浅谈iOS中的正则表达式。这里主要谈一些在Python中使用正则表达式的一些需要注意的地方。
首先,我们需要引入re模块,在re模块中有三个常用的方法
re.match() #这里是对整个字符串进行匹配
re.search() #匹配任意字段,找到第一个之后就不再继续找了
re.findall() #查找整个字符串里面相匹配的字符
例如

>>>import re #导入re模块
>>>contactInfo = 'Doe, John: 555-1212'
>>>match = re.search(r'(\w+), (\w+): (\S+)', contactInfo)
>>> match.group(1)
'Doe'

这里在字符串前面加上r,就可以不再需要进行转义了,不然\要写成\\
其中group对象是用圆括号()包围正则表达式的特定部分,其第0位是默认被用来记录整个查找结果,所以group(1)输入的结果是Doe.

后续:

其它高级模块,如网络错误处理数据库进程与线程模块的内容暂时还没有涉及到,大家如果有兴趣的话,可以自行google学习。

2015-08-20 20:13138