本文首发于“生信补给站”公众号 https://mp.weixin.qq.com/s/-x2V_41lJlQX4xp8GXPKLA
0引言
微信公众号终于可以插代码了,Python 可以走一波了。首先我承认不是硬核搞 IT 的,太高级的玩法也玩不来,讲讲下面基本的还可以,之后带点机器学习、金融工程和量化投资的实例也是可以。
- Python 入门篇 (上)
- Python 入门篇 (下)
- 数组计算之 NumPy
- 科学计算之 SciPy
- 数据结构之 Pandas
- 基本可视化之 Matplotlib
- 统计可视化之 Seaborn
- 交互可视化之 Bokeh
- 炫酷可视化之 PyEcharts
- 机器学习之 Sklearn
- 深度学习之 TensorFlow
- 深度学习之 Keras
- 深度学习之 PyTorch
- 深度学习之 MXnet
整个系列力求精简和实用 (可能不会完整,但看完此贴举一反三也不要完整,追求完整的建议去看书),到了「难点处」我一定会画图帮助读者理解。Python 系列的入门篇的目录如下,本帖是上篇,只涵盖前三个节,下篇接着后两节。
对于任何一种计算机语言,我觉得最重要的就是「数据类型」「条件语句 & 迭代循环」和「函数」,这三方面一定要打牢基础。此外 Python 非常简洁,一行代码 (one-liner) 就能做很多事情,很多时候都用了各种「解析式」,比如列表、字典和集合解析式。
在学习本贴前感受一下这个问题:如何把以下这个不规则的列表 a 里的所有元素一个个写好,专业术语叫打平 (flatten)?
a = [1, 2, [3, 4], [[5, 6], [7, 8]]]
魔法来了 (这一行代码有些长,用手机的建议横屏看)
fn = lambda x: [y for l in x for y in fn(l)] if type(x) is list else [x]fn(a)
[1, 2, 3, 4, 5, 6, 7, 8]
这一行代码,用到了迭代、匿名函数、递推函数、解析式这些技巧。初学者一看只会说“好酷啊,但看不懂”,看完本帖和下帖后,我保证你会说“我也会这样用了,真酷!”
1基本数据类型
Python 里面有自己的内置数据类型 (build-in data type),本节介绍基本的三种,分别是整型 (int),浮点型 (float),和布尔型 (bool)。
1.1 整型
整数 (integer) 是最简单的数据类型,和下面浮点数的区别就是前者小数点后没有值,后者小数点后有值。例子如下:
a = 1031print( a, type(a) )
1031 <class 'int'>
通过 print 的可看出 a 的值,以及类 (class) 是 int。Python 里面万物皆对象(object),「整数」也不例外,只要是对象,就有相应的属性 (attributes) 和方法 (methods)。
知识点
通过 dir( X ) 和help( X ) 可看出 X 对应的对象里可用的属性和方法。
- X 是 int,那么就是 int 的属性和方法
- X 是 float,那么就是 float 的属性和方法
等等
dir(int)
['__abs__', '__add__', ... '__xor__', 'bit_length', 'conjugate', ... 'real', 'to_bytes']
红色的是 int 对象的可用方法,蓝色的是 int 对象的可用属性。对他们你有个大概印象就可以了,具体怎么用,需要哪些参数 (argument),你还需要查文档。看个bit_length的例子
a.bit_length()
11
该函数是找到一个整数的二进制表示,再返回其长度。在本例中 a = 1031, 其二进制表示为 ‘10000000111’ ,长度为 11。
1.2 浮点型
简单来说,浮点型 (float) 数就是实数, 例子如下:
print( 1, type(1) )print( 1., type(1.) )
1 <class 'int'> 1.0 <class 'float'>
加一个小数点 . 就可以创建 float,不能再简单。有时候我们想保留浮点型的小数点后 n 位。可以用 decimal 包里的 Decimal 对象和 getcontext() 方法来实现。
import decimalfrom decimal import Decimal
Python 里面有很多用途广泛的包 (package),用什么你就引进 (import) 什么。包也是对象,也可以用上面提到的dir(decimal) 来看其属性和方法。比如 getcontext() 显示了 Decimal 对象的默认精度值是 28 位 (prec=28),展示如下:
decimal.getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
让我们看看 1/3 的保留 28 位长什么样?
d = Decimal(1) / Decimal(3)d
Decimal('0.3333333333333333333333333333')
那保留 4 位呢?用 getcontext().prec 来调整精度哦。
decimal.getcontext().prec = 4 e = Decimal(1) / Decimal(3)e
Decimal('0.3333')
高精度的 float 加上低精度的 float,保持了高精度,没毛病。
d + e
Decimal('0.6666333333333333333333333333')
1.3 布尔型
布尔 (boolean) 型变量只能取两个值,True 和 False。当把布尔变量用在数字运算中,用 1 和 0 代表 True 和 False。
T = TrueF = Falseprint( T + 2 )print( F - 8 )
3 -8
除了直接给变量赋值 True 和 False,还可以用 bool(X) 来创建变量,其中 X 可以是
- 基本类型:整型、浮点型、布尔型
- 容器类型:字符、元组、列表、字典和集合
基本类型
print( type(0), bool(0), bool(1) )print( type(10.31), bool(0.00), bool(10.31) )print( type(True), bool(False), bool(True) )
<class 'int'> False True <class 'float'> False True <class 'bool'> False True
bool 作用在基本类型变量的总结:X 只要不是整型 0、浮点型 0.0,bool(X) 就是 True,其余就是 False。
容器类型
print( type(''), bool( '' ), bool( 'python' ) )print( type(()), bool( () ), bool( (10,) ) )print( type([]), bool( [] ), bool( [1,2] ) )print( type({}), bool( {} ), bool( {'a':1, 'b':2} ) )print( type(set()), bool( set() ), bool( {1,2} ) )
<class 'str'> False True <class 'tuple'> False True <class 'list'> False True <class 'dict'> False True <class 'set'> False True
bool 作用在容器类型变量的总结:X 只要不是空的变量,bool(X) 就是 True,其余就是 False。
知识点
确定bool(X) 的值是 True 还是 False,就看 X 是不是空,空的话就是 False,不空的话就是 True。
- 对于数值变量,0, 0.0 都可认为是空的。
- 对于容器变量,里面没元素就是空的。
此外两个布尔变量 P 和 Q 的逻辑运算的结果总结如下表:
2容器数据类型
上节介绍的整型、浮点型和布尔型都可以看成是单独数据,而这些数据都可以放在一个容器里得到一个「容器类型」的数据,比如:
- 字符 (str) 是一容器的字节 char,注意 Python 里面没有 char 类型的数据,可以把单字符的 str 当做 char。
- 元组 (tuple)、列表 (list)、字典 (dict) 和集合 (set) 是一容器的任何类型变量。
2.1 字符
字符用于处理文本 (text) 数据,用「单引号 ’」和「双引号 “」来定义都可以。
创建字符
t1 = 'i love Python!'print( t1, type(t1) )t2 = "I love Python!"print( t2, type(t2) )
i love Python! <class 'str'> I love Python! <class 'str'>
字符中常见的内置方法 (可以用 dir(str) 来查) 有
- capitalize():大写句首的字母
- split():把句子分成单词
- find(x):找到给定词 x 在句中的索引,找不到返回 -1
- replace(x, y):把句中 x 替代成 y
- strip(x):删除句首或句末含 x 的部分
t1.capitalize()
'I love python!'
t2.split()
['I', 'love', 'Python!']
print( t1.find('love') )print( t1.find('like') )
2 -1
t2.replace( 'love Python', 'hate R' )
'I hate R!'
print( 'http://www.python.org'.strip('htp:/') )print( 'http://www.python.org'.strip('.org') )
www.python.org http://www.python
索引和切片
s = 'Python'print( s )print( s[2:4] )print( s[-5:-2] )print( s[2] )print( s[-1] )
Python th yth t n
知识点
Python 里面索引有三个特点 (经常让人困惑):
- 从 0 开始 (和 C 一样),不像 Matlab 从 1 开始。
- 切片通常写成 start:end 这种形式,包括「start 索引」对应的元素,不包括「end索引」对应的元素。因此 s[2:4] 只获取字符串第 3 个到第 4 个元素。
- 索引值可正可负,正索引从 0 开始,从左往右;负索引从 -1 开始,从右往左。使用负数索引时,会从最后一个元素开始计数。最后一个元素的位置编号是 -1。
这些特点引起读者对切片得到什么样的元素感到困惑。有个小窍门可以帮助大家快速锁定切片的元素,如下图。
与其把注意力放在元素对应的索引,不如想象将元素分开的隔栏,显然 6 个元素需要 7 个隔栏,隔栏索引也是从 0 开始,这样再看到 start:end 就认为是隔栏索引,那么获取的元素就是「隔栏 start」和「隔栏 end」之间包含的元素。如上图:
- string[2:4] 就是「隔栏 2」和「隔栏 4」之间包含的元素,即 th
- string[-5:-2] 就是「隔栏 -5」和「隔栏 -2」之间包含的元素,即 yth