一直想学习一下Python语言,拥有动态语言的特性,还是解释型语言,拥有高级数据结构,可以以简单而高效的方式进行面向对象编程,并且Python类库众多,适合写脚本,特别是一些小工具,最近把Python语法大概捋了一遍,在这里记录学习的过程
一、简介
1. 什么是Python
Python是一种编程语言,支持高级数据结构,结构化,Python是一门解释性语言,无需编译即可运行,支持模块化,类库众多且重用性高,例如基础的IO,Socket,图形界面等,模块化使得Python适用于更多领域,绝大多数其他编程语言能做到的Python都能做到,甚至支持与二进制库连接起来,有一句话是这么说的:人生苦短,我用Python
2. 什么时候使用Python
pPython比较使用于编写工具脚本,例如如果你有一些大量的重复的工作,希望计算机可以自动帮你完成,而又找不到相关的软件可以比较完美的实现,这个时候就可以考虑写一个Python脚本来执行,例如:
- 例如批量扫描文件内容,并替换文件中的文本(执行某些操作)
- 批量修改文件名
- 从多个excel文件中提取相关信息并输出到一个excel中
- 批量抓取网页信息并保存到数据库(爬虫)
通常来说就是使用脚本自动完成一些自定义的行为,主要是Python支持的库(module)众多,能帮助你节省不少时间
当然如果你是开发人员,可能通过C++/C#/Java来写自动化的工具,但是这些工具可能会显得庞大而臃肿,可能会让人觉得这是烦躁而漫长的工作,那么你可以用Python试试
当然Python能做的事远不止这些,支持的类库涵盖了很多领域,如人工智能,机器学习,图像处理,金融,物理学等,当然,很多功能其他语言也能做到,Python最大的优势就是类库众多,处理灵活,我们很多时候都不需要重复造轮子,特别是对于追求效率的你来说,或许是个好选择,
语言只是个工具,没有语言是万能的,什么好用用什么
3. 安装Python
学习Python的时候建议使用Python 2.x版本,大多第三方库都基于2.x版本,3.x版本相对于2.x改动比较大,并且一些老的库不支持3.x,我这里使用的是Python 2.7.10
,mac系统自带Python,可以通过下面命令查看Python的版本
1 | # 默认情况下使用Python查看Python2的版本 |
4. 工具
与其他脚本语言类似(php, js)使用普通的文本编辑器即可,我这里用的是Sublime2,当然也可以使用一些集成IDE
- Atom:与Sublime类似,支持代码高亮,自动补齐
- PyCharm:JetBrains出的Python语言IDE,功能强大,收费
- Eclipse:有Python插件提供支持
如果是刚开始学习,推荐使用文本工具(Sublime或Atom)
5. 交互式编程
交互式编程相当于一问一答的方式,在Terminal输入Python进入交互式模式,与其他语言不同,Python不以分号结尾,并且通过缩进识别代码块
1 | localhost:~ bomo$ Python |
二、基础与语法
1. 数据类型
与其他高级语言一样,除了基础数据类型,Python也支持高级数据类型
Python支持如下数据类型
2. 运算符
+
-
*
/
%
//
,**
1
2
3
4
5
6# 取整(不大于该数)
11 // 3.0 # 3.0
11 // -3 # -4
# 幂运算,与其他语言的`^`类似
5 ** 2 # 25in
,not in
比较运算符,判断区间或集合是否存在某项is
,is not
判断两个对象是否相同is 与 == 的区别
1
2
3a, b = 1, 1.0
a == b # True
a is b # False
python(2.5+)也支持三元运算符,用法与C语言有点出入,形式为
1
x if x > y else y # 等价于C语言的 x > y ? x : y
在交互运算中,Python会把最近一次的表达式的值赋值给_
,__该变量是只读的,不要尝试给其赋值__,一些不需要的变量有时也用_
表示(其实跟普通的变量i一样),如for
1
2
3
4
5
6a = 10
10 + 32 # 42
a + _ # 52
for _ in range(0, 10):
print '这里不需要用到迭代的值'
3. 流程控制与循环
Python的流程控制跟其他语言差不多,关键字有:if-else
, for
, while
, break
, continue
, pass
3.1 if-else
1 | if x == 0: |
3.2 for
1 | words = ['mac', 'windows', 'linux'] |
3.3 pass
空语句,与C语言的分号;
类似,什么都不执行,通常用来表示一个空的代码块
- 注意for, if-else, while 后面都有冒号
:
- Python使用缩进来识别块(其他语言多数使用大括号来识别代码块)
- Python没有
do-while
语句 - Python没有
switch-case
,也可以参考:http://blog.sina.com.cn/s/blog_6409e7eb01018chn.html
4. 函数
4.1 函数定义
形式
1 | def 函数名(函数参数列表): |
eg: 输出一个Fibonacci斐波那契序列
1 | def fib(n): |
4.2 参数默认值
1 | i = 10 |
从上面例子可以看到,参数的默认值在解释器运行到函数的时候就确定了,如上面的变量b
,后面修改的的变量i与函数test没有关联了,有一点需要注意的是,如果默认参数是一个对象的时候,也是同样的,如下面例子
1 | def test(data=[]): # 默认参数为空list |
Python解释器在解释道函数test的时候就确定好了函数test的参数默认值,所以每次调用使用的参数对象都是同一个,上面函数应该定义为如下方式
1 | def test(data=None): # 默认参数为空list |
4.3 可变参数
1 | def test(a, *b): |
可变参数必须定义为最后一个(在可变字典参数前)
4.4 可变字典参数
1 | def test(a, *b, **c): |
可变字典参数必须定义在最后一个
4.5. lambda表达式
形式
1 | lambda 函数参数列表: 函数体 |
eg: 使用Lambda表达式给列表排序
1 | pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')] |
5. 装饰器
参见这里
6. 序列
首先看看迭代器类型,Python常用的序列类型有list, tuple, str
1 | squares = [1, 4, 9, 16, 25] # 列表 |
6.1. 字符串
字符串是特殊的列表
1 | print '"Yes," he said.' # 使用单双引号表示单行字符串:"..." '...' |
格式化字符串,Python使用%
隔开格式化字符串和值
1 | from math import pi |
当像%s
这种符号变多了之后,就很难分清楚哪个和哪个了,Python支持使用dict作为格式化参数,如下
1 | print '%(name)s is %(age)d years old' % {'name': 'bomo', 'age': 18} |
还有这种方式
1 | print '{name} is {age:2d} years old'.format(name='bomo', age=18) |
Python格式化字符串还支持索引
1 | print '{name} is {1:2d} years old'.format(12, 18, name='bomo') |
最后一种方式是最Pythonic的,也是最推荐的方式
6.2 序列常用操作
加法乘法
1
2squares + ['a', 'b'] # ['spam', 1234, 'a', 'b']
l = squares * 2 # ['spam', 1234, 'a', 'b', 'spam', 1234, 'a', 'b']元素操作
1
2
3
4
5
6
7squares.append('jobs') # 添加
squares.extend(['a', 'b', 'c', 'd']) # 添加集合
squares.insert(0, x) # 插入元素
squares.remove('b') # 删除值为'b'的第一个元素
squares.pop([1]) # 删除第1个元素,并返回该元素
squares.index('b') # 获取值为'b'的索引
squares.count('b') # 获取值为'b'的出现次数统计操作
1
2
3len(squares)
max(squares)
min(squares)删除操作
1
2
3a = [-1, 1, 66.25, 333, 333, 1234.5]
del a[0] # [1, 66.25, 333, 333, 1234.5]
del a[2:] # [1, 66.25]
6.3 切片的原理
切片内部是调用__getitem__
,__setitem__
,__delitem__
和slice
函数
1 | a = [1, 2, 3, 4, 5, 6] |
7. 元组tuple
元组相当于多维数组,与序列一样,元组元素支持任意类型,用括号表示,括号有时可以省略(不产生歧义的情况下)
1 | t = (1, 2) |
元组各个元素可以同时赋值
1 | t = (1, 2) |
元组使得函数返回多个值变得更加方便
1 | def get_point(): |
与列表不同,元组是不可变的,如果想修改,只能生成新的元组
8. 字典dict
用法与其他语言类似
1 | tel = {'jack': 4098, 'sape': 4139, 'bomo': 10086} |
列表推倒式和字典推导式
列表推导式
形式:[expression for value in collection if condition]
,相当于1
2
3
4
5result = []
for value in collection:
if condition:
result.append(expression)
return result例如
1
[i for i in range(1,100) if i > 90] # [91, 92, 93, 94, 95, 96, 97, 98, 99]
字典推导式
形式:{key_expression: value_expression for value in tuple}
,相当于1
2
3
4
5result = {}
for value in collection:
if condition:
result[key_expression] = value_expression
return result例如:
1
{x+1: x**2 for x in (2, 4, 6, 8) if x <= 6} # {3: 4, 5: 16, 7: 36}
9. 无序集set
1 | basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] |
10. 迭代器类型常用操作
enumerate
使用enumerate函数可以同时得到索引和值1
2for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)zip
多个循环可以用zip打包,以最短的list为准1
2
3
4
5
6
7
8
9
10questions = ['name', 'quest', 'favorite color']
answers = ['lancelot']
cc = ['lancelot', 'the holy grail', 'blue', 'eeeee']
for q, a, c in zip(questions, answers, cc):
print 'What is your {0}? It is {1}.{2}'.format(q, a, c)
# 输出
# What is your name? It is lancelot.
# What is your quest? It is the holy grail.
# What is your favorite color? It is blue.reversed
反序1
2
3
4for i in reversed([1,2,3]):
print(i)
# 输出:3, 2, 1
>>>iteritems
遍历字典使用iteritems可以同事获得key, value1
2
3
4
5
6knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.iteritems():
print k, v
# 输出
# gallahad the pure
# robin the bravefilter
过滤器,给定过滤函数和集合:filter(function, sequence)
1
2
3def f(x):
return x % 3 == 0 or x % 5 == 0
filter(f, range(2, 25)) # [3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24]map
给定集合和操作函数,返回操作后的集合:map(function, sequence)
1
2
3def cube(x):
return x*x
map(i, range(1, 6)) # [1, 4, 9, 16, 25, 36]reduce
首先操作前两个数,然后结果与后一个数运算,以此类推:reduce(function, sequence)
1
2
3
4
5def add(x,y):
return x+y
reduce(add, range(1, 11)) # 1+2+3+4+5+6+7+8+9+10=55
reduce(lambda (x, y): x + y, range(1, 11)) # 55
11. 迭代器与生成器
参见这里
12 类
12.1 构造函数__init__
,析构函数__del__
1 | class test: |
注意,Python的构造函数不支持重载,只能有一个构造函数,可以通过可变参数实现多构造函数
在调用父类的构造方法见后面新式类和经典类
12.2 方法与变量
类变量定义在类中,实例变量定义在构造函数中,Python中的类实例可以直接设置属性,如果属性不存在,则添加属性
1 | class test: |
12.3 类里面引用全局变量
当类里面需要引用外部的全局变量的时候需要,加上global关键字
1 | global_count = 0 |
12.4 实例方法,类方法,静态方法
在Python中这几种方法特别容易,类属性和方法不能重名,否则会相互覆盖
1 | class Person: |
其他语言如java和C#都只有静态方法和类方法,而Python多了一个类方法,在大多数情况下,使用静态方法即可,在需要获取调用类的信息的时候(如类变量,类类型,类名等),则需要使用类方法
方法的第一个参数被命名为 self。这仅仅是一个约定:对 Python 而言,名称 self 绝对没有任何特殊含义(但是请注意:如果不遵循这个约定,对其他的 Python 程序员而言你的代码可读性就会变差,而且有些类查看器程序也可能是遵循此约定编写的。),在交互式命令行中会报错
12.5 继承
父类放在子类定义的类名后的括号内,Python支持多继承
1 | class DerivedClassName(Base1, Base2, Base3): |
单继承:如果子类有自己实现的构造函数,则不会自动调用父类的构造函数,如果子类没有实现构造函数,则会继承父类的构造函数
多继承:如果子类有自己实现的构造函数,同单继承,不会主动调用父类的构造函数,如果子类没有实现自己的构造函数,则会从父类中优先选择有构造函数的父类(__深度搜索__)
判断实例与继承关系
1 | s = son() |
12.6 新式类和经典类
新式类:从object类继承的类,继承顺序广度优先
经典类:不从object继承的类,继承顺序深度优先,不支持super
1 | # 新式类 |
子类可以通过super(类, 对象)
获取父对象父类对象的实例,然后可以调用父类的(同名)方法,就相当于Java中的super
,C#中的base
13. 模块module, 包package
Python在处理功能复用组织结构切分为模块,包和面向对象的类,其结构类似于C#/Java的命名空间,用于
13.1 引用模块
1 | import math # 引用math模块 |
- 文件名就是模块的名字:
test.py
的模块名为test
- 第一次导入模块的时候会自动执行模块内的所有代码
- 通过Python执行py模块的时候
__name__
变量会被设为__main__
,如果是import,则不会,可以通过__name__
变量判断是否是命令行执行 - 使用下划线
_
前缀定义类私有函数或变量_xxx
单下划线开头,在from module import *
导入会忽略,但不是私有方法__xxx__
双下划线开头和结尾,系统定义名字__xxx
双下划线开头,类中的私有变量名
13.2 dir函数查看模块
可以通过dir
函数查看模块内定义的所有变量和函数
1 | import math |
13.3 模块搜索路径
在导入模块的时候,Python会自动从以下目录搜索该模块是否存在
- 输入脚本的目录(当前目录)。
- 环境变量 PYTHONPATH 表示的目录列表中搜索
- Python 默认安装路径中搜索
可以通过sys.path
查看所有目录
1 | import sys |
13.4 package包
多个模块组织成一个package,类似于java的jar包,C#的dll可执行文件,包在Python中相当于一个文件夹,包文件夹包含__init__.py
文件,该文件用于初始化package
1 | sound/ Top-level package |
使用package方式与module类似
1 | # 使用wavread需要引用sound.format |
13.5 __init__.py
文件
__init__.py
文件可以包含一些包初始化的内容,可以定义默认导入的模块
1 | __all__ = ["wavread", "wavwrite"] |
在使用from sound.formats import *
的时候只会导入wavread
, wavwrite
两个模块,而不会导入aiffread
模块
- 导入包的时候,先初始化
__init__.py
文件,再初始化模块文件
13.6 包内引用
只有包才能引用包,纯目录不能互相引用,所以只有目录下有__init__.py
文件才能被其他目录的模块引用
1 | from . import echo # 当前包同目录下的echo模块 |
13.7 模块操作
删除模块属性/函数
1 | class test: |
Python算是动态语言,属性和函数即写即用,不需要提前定义好,模块也可以即时导入即时卸载
14. 文档注释
文档注释跟在相应的定义后面:函数定义,类定义,文件定义(文件头)
1 | #!usr/bin/env Python |
可以通过help或__doc__
访问注释内容
1 | # 列出整个模块的所有注释 |
15. 异常
Python的异常处理和其他语言类似:try-except-finally
,抛出异常使用raise
1 | try: |
16. 多线程
参见这里
17. Python常用模块
time
1 | import time |
IO
1 | # 打印到屏幕 |
正则表达式
1 | import re |
match和search有第三个参数flag,match(pattern, input, flag)
1 | print(re.search(r'WWW', 'www.runoob.com', flags=re.I).string) |
flag | 用法 |
---|---|
I | 忽略大小写 |
M | 多行模式 |
S | 单选模式——点任意匹配模式 |
L | 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定 |
U | 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性 |
X | 详细模式。该模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。 |
本文记录自己在学习过程中总结的一些Python要点,接触过Java,C#,OC,Python的语法确实简单优雅,很少多余的东西,人生苦短,Python是岸