这两天在看这本 Data Science from Scrach ( PDF地址 ),是本不错的通俗易懂的数据科学入门书籍。其中一个章节介绍了一下 Python 的基础语法和数据科学常用的进阶语法,觉得介绍得不错,很简洁明了,所以将其翻译一下放在这里以作备忘。
数据科学中常用的 Python 语法(基础)
数据科学中常用的 Python 语法(进阶)
本章侧重于介绍在数据处理中非常有用的 Python 基础语法和功能(基于 Python 2.7 )。
空格格式
许多语言使用括号来控制代码块,但 Python 用的是缩进:1
2
3
4
5
6
7for i in [1, 2, 3, 4, 5]:
print i # "for i"循环的第一行
for j in [1, 2, 3, 4, 5]:
print j # "for j"循环的第一行
print i + j # "for j"循环的最后一行
print i # "for i"循环的最后一行
print "done looping"
这使得 Python 的代码非常易于阅读,但也意味着你要时刻注意格式。括号里的空格将会被忽略,这在写长表达式时很有用:
1 | long_winded_computation = (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20) |
也使得代码变得好读:
1 | list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] |
多行语句
可以用一个反斜杠来表示连接中断的两行(这种做法很少用):1
2two_plus_three = 2 + \
3
模块 Modules
不论是 Python 自带的模块还是自己下载的第三方的模块,都需要需要通过手动导入才能使用。
1.简单地直接导入整个模块:
1 | import re |
这里导入的 re 模块是用于正则表达式的。导入模块后,可以直接将模块名字作为前缀(re.)来调用具体功能。
2.如果调入的模块名称已经在代码中被使用,可以将模块导入时映射到另一个名称中:
1 | import re as regex |
3.如果你很坏,你就可以将整个模块都导入到当前命名空间,这可能在不经意间覆盖你已经定义好的变量:
1 | match = 10 |
因为你是个好人,所以我相信你不会这么做的。
四则运算 Arithmetic
Python 2.7 默认使用整除,所以 $ 5 / 2 = 2 $.但很多时候我们并不想要整除,所以可以导入这个模块:
1 | from __future__ import division |
导入后,就有 $5 / 2 = 2.5$.
整除:$5 // 2 = 2$.
函数 Functions
函数定义
函数是能够接收 0 个或多个输入,并返回一定输出的一个规则。在 Python 中,我们用 def 函数名(参数) 定义一个函数:
1 | def double(x): |
函数使用
在 Python 中,函数是最低等级的存在,这意味着我们可以将函数赋值给一个变量,也可以将它作为一个参数传递给其他变量:
1 | def apply_to_one(f): |
匿名函数
还可以通过 lambda 来创建匿名函数:
1 | y = apply_to_one(lambda x: x + 4) # 等于 5 |
可以将 lambda 赋值给其他变量,但大多数人会建议你还是尽量使用 def :
1 | another_double = lambda x: 2 * x # 不建议 |
补充:
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。
函数参数传递
函数参数可以定义默认值,函数表达式不加参数将使用默认值,加参数将传递指定值:
1 | def my_print(message="my default message"): |
有时候直接通过参数名称来指定参数也很好用:
1 | def subtract(a=0, b=0): |
字符串 Strings
可以使用单引号或双引号来创建字符串(引号一定要配对):
1 | single_quoted_string = 'data science' |
用反斜杠来表示转义字符,如:
1 | tab_string = "\t" # 表示制表符 tab |
当你想要使用反斜杠本身 (用于 Windows 目录或者正则表达式), 可以通过使用原始字符串 r” “ 定义:
1 | not_tab_string = r"\t" # 表示字符 '\' 和 't' |
利用三个双引号创建多行字符串:
1 | multi_line_string = """这是第一行 |
异常处理 Exception
当程序出错,Python 会发生一个 异常(exception),我们不对其进行处理的话,程序将会终止执行。捕获异常可以用 try 和 except 语句:
1 | try: |
尽管在其他语言中,异常被看作是不好的现象,但在 Python 中,多处理异常将会使你的代码更加简洁干净。
列表 Lists
创建列表
列表是简单的有序集合,也是 Python 中最基础的数据结构 (类似其他语言中的数组,但列表具有一些额外的特性)。创建一个列表:
1 | integer_list = [1, 2, 3] |
访问列表中的值
你可以通过方括号索引列表中的值:
1 | x = range(10) # 列表获得列表 x = [0, 1, ..., 9] |
截取列表
可以用方括号截取列表:
1 | first_three = x[:3] # [-1, 1, 2] |
可以用 in 来查看某元素是否在列表中:
1 | 1 in [1, 2, 3] # True |
这种元素查找方式效率很低,只有在列表很小或者你不在意查找时间的情况下再去使用。
拼接列表
Python 中很容易就能拼接两个列表:
1 | x = [1, 2, 3] |
如果你不想修改原列表 x ,你可以使用“加”运算符创建一个新的列表:
1 | x = [1, 2, 3] |
经常用这样的方式一次在列表中添加一个元素:
1 | x = [1, 2, 3] |
列表分解
如果你知道列表中有多少个元素,那么很容易就能分解这个列表:
1 | x, y = [1, 2] # 当前 x = 1, y = 2 |
等式两边元素数目不一致的话,你将会得到一个 值错误,所以我们更经常用下划线来存放列表剩下的部分:
1 | _, y = [1, 2] # 当前 y == 2, 不管第一个元素 |
元组 Tuples
列表和元组很像,和列表唯一的区别就是,元组中的元素不能被修改。
元组创建
可以使用圆括号或者不加任何括号来创建元组:
1 | my_tuple = (1, 2) |
利用元组能够很方便地从函数中获取多个返回值:
1 | def sum_and_product(x, y): |
元组(和列表)都支持同时赋值多个元素:
1 | x, y = 1, 2 # 当前 x = 1, y = 2 |
字典 Dictionaries
字典创建
Python 中的另一个基础数据结构是字典,它能让你通过关键字(key)快速获得对应的值(value):
1 | empty_dict = {} # 非常 Python 化的空字典定义 |
字典元素查找
你可以用方括号加关键字来查找对应的值:
1 | joels_grade = grades["Joel"] # 等于 80 |
如果要查找的关键字不在字典中,将返回一个 键错误(KeyError) :
1 | try: |
可以通过 in 来查看关键字是否在字典中:
1 | joel_has_grade = "Joel" in grades # True |
字典有一个可以返回默认值的方法,当要查找的关键字不在字典中将会返回设定的默认值(而不是发生异常):
1 | joels_grade = grades.get("Joel", 0) # 等于 80 |
字典修改
可以用方括号来创建、修改字典中的键值对:
1 | grades["Tim"] = 99 # 替换旧的值 |
我们将会经常像这样使用字典来表达数据的结构:
1 | tweet = { |
除了查找特定关键字,我们还可以像这样操作所有关键字:
1 | tweet_keys = tweet.keys() # 得到一个关键字(键)列表 |
字典中的键是唯一的,而且列表不能用作字典的关键字(键)。如果你需要一个多部分的关键字,你可以使用元组,或者通过某种途径将关键字转换成字符串。
内置字典
如果你正试图统计一个文档中每个词出现的频率,一个显然的做法是创建一个字典,词作为关键字,频率作为对应的值。然后遍历文档,遇到出现过的词就让字典对应键值自增 1 ,遇到未出现过的词就在字典中添加一个键值对:
1 | word_counts = {} |
当然,你也可以像这样用“先斩后奏”的方式来提前处理一个缺失的键:
1 | word_counts = {} |
第三个方法是使用 get ,这个方法对于缺失键的处理表现优异:
1 | word_counts = {} |
内置字典就跟普通字典一样,唯一的区别就是,当你试图在字典中查找一个不存在的键时,内置字典将利用你提供的关键字自动创建一个键值对。为了使用内置字典,你需要导入 collections 函数库:
1 | from collections import defaultdict |
在列表、普通字典甚至自定义的函数中,默认字典也都很好用:
1 | dd_list = defaultdict(list) # list() 生成一个空列表 |
这种方法很有用,以后我们要获取字典中的某些键值结果时,就无需再检查键是否存在了。
计数器 Counter
计数器可以直接将一组值转换成类似字典的对象,关键字为这组中的某个元素,对应的值为该元素出现的次数。这在创建直方图的时候会经常用到:
1 | from collections import Counter |
这样我们就有了一个很方便的统计词频的方法:
1 | word_counts = Counter(document) |
计数器还有一个很常用的方法 _most_common_,可以直接得到最高频的几个词和对应的频率:
1 | # 输出前 10 个最高频的词以及他们的计数值 |
集合 Sets
Python 中另一种数据结构是集合,集合是一组不同元素的收集。
可以这样创建一个集合并向其中添加元素:
1 | s = set() |
使用集合的两大理由:
第一,集合中的 in 操作非常高效。当一个数据集中的元素数量非常庞大的时候,以集合的形式来查找元素显然比列表更加合适:
1 | stopwords_list = ["a","an","at"] + hundreds_of_other_words + ["yet", "you"] |
第二,用集合来获取一组数据中不同的元素非常方便:
1 | item_list = [1, 2, 3, 1, 2, 3] |
不过实际上,集合的使用频率还是没有字典和列表高。
条件语句
在绝大多数编程语言中,你都可以像这样用 if 来表示条件分支:
1 | if 1 > 2: |
你也可以像这样将条件分支语句写在一行中,但这很少用:
1 | parity = "even" if x % 2 == 0 else "odd" |
循环语句
while 循环
Python 中的 while 循环:
1 | x = 0 |
for 循环
更常用的是使用 for-in 循环:
1 | for x in range(10): |
更复杂的逻辑表达式可以使用 continue 和 break 语句:
1 | for x in range(10): |
结果将会输出 0, 1, 2,和 4。
真值 Truthiness
Python 中的布尔变量 Booleans 用法和其他语言差不多,唯一的区别是首字母一定要大写:
1 | one_is_less_than_two = 1 < 2 # 为 True |
Python 使用 None 来表示一个值不存在,类似其他语言中的 null :
1 | x = None |
Python 允许你用其他值代替布尔值,以下皆等价于“False”:
- False
- None
- [] (一个空列表)
- {} (一个空字典)
- “”
- set()
- 0
- 0.0
类似的也有很多“True”的等价值,这让你非常方便地判断空列表、空字符串以及空字典等等。
当然,如果你不能预见结果的话,可能会在使用过程中出错:
1 | s = some_function_that_returns_a_string() |
一个更简单的做法,该做法效果等同于上面的做法:
1 | first_char = s and s[0] |
如果第一个值为真,将返回第二个值,否则返回第一个值。
类似地,如果 x 可能是一个数字也可能为空,那么这样可以得到一个肯定为数字的 x :
1 | safe_x = x or 0 |
Python 中还有一个 all 函数,在每个元素都为“True”时函数返回“True”。any 函数,只要有一个元素为“True”就返回“True”。比如对于一个每一个元素都为“真”的列表,all 函数将返回“True”,否则将返回“False”:
1 | all([True, 1, { 3 }]) # True |