文章和代码等曾经归档至【Github仓库:https://github.com/timerring/dive-into-AI 】或者公众号【AIShareLab】回复 python数据分析 也可获取。
缩进
倡议应用四个空格(tab)作为默认的缩进。
Python的语句不须要用分号结尾。然而,分号却能够用来给同在一行的语句切分:
a = 5; b = 6; c = 7
Python不倡议将多条语句放到一行,这会升高代码的可读性。
函数和对象办法调用
你能够用圆括号调用函数,传递零个或几个参数,或者将返回值给一个变量:
result = f(x, y, z)g()
简直Python中的每个对象都有附加的函数,称作办法,能够用来拜访对象的内容。能够用上面的语句调用:
obj.some_method(x, y, z)
变量和参数传递
在Python中,a和b实际上是同一个对象,即原有列表[1, 2, 3]。能够在a中增加一个元素,而后查看b:
In [8]: a = [1, 2, 3]In [9]: b = aIn [10]: a.append(4)In [11]: bOut[11]: [1, 2, 3, 4]
赋值也被称作绑定,咱们是把一个名字绑定给一个对象。变量名有时可能被称为绑定变量。
当你将对象作为参数传递给函数时,新的局域变量创立了对原始对象的援用,而不是复制。
def append_element(some_list, element): some_list.append(element)
In [27]: data = [1, 2, 3]In [28]: append_element(data, 4)In [29]: dataOut[29]: [1, 2, 3, 4]
强类型
变量是在非凡命名空间中的对象的名字,类型信息保留在对象本身中。一些人可能会说Python不是“类型化语言”。这是不正确的,看上面的例子:
In [16]: '5' + 5---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-16-f9dbf5f0b234> in <module>()----> 1 '5' + 5TypeError: must be str, not int
在某些语言中,例如Visual Basic,字符串‘5’可能被默认转换(或投射)为整数,因而会产生10。但在其它语言中,例如JavaScript,整数5会被投射成字符串,后果是联结字符串‘55’。在这个方面,Python被认为是强类型化语言,意味着每个对象都有明确的类型(或类),默认转换只会产生在特定的状况下,例如:
In [17]: a = 4.5In [18]: b = 2# String formatting, to be visited laterIn [19]: print('a is {0}, b is {1}'.format(type(a), type(b)))a is <class 'float'>, b is <class 'int'>In [20]: a / bOut[20]: 2.25
你能够用isinstance
函数查看对象是某个类型的实例:
In [21]: a = 5In [22]: isinstance(a, int)Out[22]: True
isinstance
能够用类型元组,查看对象的类型是否在元组中:
In [23]: a = 5; b = 4.5In [25]: isinstance(b, (int, float))Out[25]: True
属性和办法
Python的对象通常都有属性(其它存储在对象外部的Python对象)和办法(对象的从属函数能够拜访对象的外部数据)。能够用obj.attribute_name
的模式拜访属性和办法:
In [1]: a = 'foo'In [2]: a.<Press Tab>a.capitalize a.format a.isupper a.rindex a.stripa.center a.index a.join a.rjust a.swapcasea.count a.isalnum a.ljust a.rpartition a.titlea.decode a.isalpha a.lower a.rsplit a.translatea.encode a.isdigit a.lstrip a.rstrip a.uppera.endswith a.islower a.partition a.split a.zfilla.expandtabs a.isspace a.replace a.splitlinesa.find a.istitle a.rfind a.startswith
也能够用getattr
函数,通过名字拜访属性和办法:
In [27]: getattr(a, 'split')Out[27]: <function str.split>
在其它语言中,拜访对象的名字通常称作“反射”。本书不会大量应用getattr
函数和相干的hasattr
和setattr
函数,应用这些函数能够高效编写原生的、可重复使用的代码。
鸭子类型
常常地,你可能不关怀对象的类型,只关怀对象是否有某些办法或用处。这通常被称为“鸭子类型”,来自“走起来像鸭子、叫起来像鸭子,那么它就是鸭子”的说法。例如,你能够通过验证一个对象是否遵循迭代协定,判断它是可迭代的。对于许多对象,这意味着它有一个__iter__
魔术办法,其它更好的判断办法是应用iter
函数:
def isiterable(obj): try: iter(obj) return True except TypeError: # not iterable return False
这个函数会返回字符串以及大多数Python汇合类型为True
:
In [29]: isiterable('a string')Out[29]: TrueIn [30]: isiterable([1, 2, 3])Out[30]: TrueIn [31]: isiterable(5)Out[31]: False
我总是用这个性能编写能够承受多种输出类型的函数。
常见的例子是编写一个函数能够承受任意类型的序列(list、tuple、ndarray)或是迭代器。你可先测验对象是否是列表(或是NUmPy数组),如果不是的话,将其转变成列表:
if not isinstance(x, list) and isiterable(x): x = list(x)
引入
在Python中,模块就是一个有.py
扩展名、蕴含Python代码的文件。假如有以下模块:
# some_module.pyPI = 3.14159def f(x): return x + 2def g(a, b): return a + b
如果想从同目录下的另一个文件拜访some_module.py
中定义的变量和函数,能够:
import some_moduleresult = some_module.f(5)pi = some_module.PI
或者:
from some_module import f, g, PIresult = g(5, PI)
应用as
关键词,你能够给引入起不同的变量名:
import some_module as smfrom some_module import PI as pi, g as gfr1 = sm.f(pi)r2 = gf(6, pi)
二元运算符和比拟运算符
判断两个援用是否指向同一个对象,能够应用is
办法。is not
能够判断两个对象是不同的:
In [35]: a = [1, 2, 3]In [36]: b = aIn [37]: c = list(a)In [38]: a is bOut[38]: TrueIn [39]: a is not cOut[39]: True
因为list
总是创立一个新的Python列表(即复制),咱们能够判定c是不同于a的。应用is
比拟与==
运算符不同,如下:
In [40]: a == cOut[40]: True
is
和is not
罕用来判断一个变量是否为None
,因为只有一个None
的实例:
In [41]: a = NoneIn [42]: a is NoneOut[42]: True
可变与不可变对象
Python中的大多数对象,比方列表、字典、NumPy数组,和用户定义的类型(类),都是可变的。意味着这些对象或蕴含的值能够被批改:
In [43]: a_list = ['foo', 2, [4, 5]]In [44]: a_list[2] = (3, 4)In [45]: a_listOut[45]: ['foo', 2, (3, 4)]
其它的,例如字符串和元组,是不可变的:
In [46]: a_tuple = (3, 5, (4, 5))In [47]: a_tuple[1] = 'four'---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-47-b7966a9ae0f1> in <module>()----> 1 a_tuple[1] = 'four'TypeError: 'tuple' object does not support item assignment
标量类型
Python的规范库中有一些内建的类型,用于解决数值数据、字符串、布尔值,和日期工夫。这些单值类型被称为标量类型,本书中称其为标量。日期和工夫解决会另外探讨,因为它们是规范库的datetime
模块提供的。
数值类型
Python的次要数值类型是int
和float
。int
能够存储任意大的数:
In [48]: ival = 17239871In [49]: ival ** 6Out[49]: 26254519291092456596965462913230729701102721
浮点数应用Python的float
类型。每个数都是双精度(64位)的值。也能够用迷信计数法示意:
In [50]: fval = 7.243In [51]: fval2 = 6.78e-5
不能失去整数的除法会失去浮点数:
In [52]: 3 / 2Out[52]: 1.5
要取得C-格调的整除(去掉小数局部),能够应用底除运算符//:
In [53]: 3 // 2Out[53]: 1
字符串
能够用单引号或双引号来写字符串:
a = 'one way of writing a string'b = "another way"
对于有换行符的字符串,能够应用三引号,'''或"""都行:
c = """This is a longer string thatspans multiple lines"""
字符串c
理论蕴含四行文本,"""前面和lines前面的换行符。能够用count
办法计算c
中的新的行:
In [55]: c.count('\n')Out[55]: 3
Python的字符串是不可变的,不能批改字符串:
In [56]: a = 'this is a string'In [57]: a[10] = 'f'---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-57-5ca625d1e504> in <module>()----> 1 a[10] = 'f'TypeError: 'str' object does not support item assignmentIn [58]: b = a.replace('string', 'longer string')In [59]: bOut[59]: 'this is a longer string'
通过以上的操作,变量a
并没有被批改:
In [60]: aOut[60]: 'this is a string'
许多Python对象应用str
函数能够被转化为字符串:
In [61]: a = 5.6In [62]: s = str(a)In [63]: print(s)5.6
字符串是一个序列的Unicode字符,因而能够像其它序列,比方列表和元组一样解决:
In [64]: s = 'python'In [65]: list(s)Out[65]: ['p', 'y', 't', 'h', 'o', 'n']In [66]: s[:3]Out[66]: 'pyt'
语法s[:3]
被称作切片,实用于许多Python序列。
反斜杠是转义字符,意思是它备用来示意特殊字符,比方换行符\n或Unicode字符。要写一个蕴含反斜杠的字符串,须要进行本义:
In [67]: s = '12\\34'In [68]: print(s)12\34
如果字符串中蕴含许多反斜杠,但没有特殊字符,这样做就很麻烦。幸好,能够在字符串后面加一个r,表明字符就是它本身:
In [69]: s = r'this\has\no\special\characters'In [70]: sOut[70]: 'this\\has\\no\\special\\characters'
r示意raw。
将两个字符串合并,会产生一个新的字符串:
In [71]: a = 'this is the first half 'In [72]: b = 'and this is the second half'In [73]: a + bOut[73]: 'this is the first half and this is the second half'
字符串的模板化或格式化,是另一个重要的主题。Python 3拓展了此类的办法,这里只介绍一些。字符串对象有format
办法,能够替换格式化的参数为字符串,产生一个新的字符串:
In [74]: template = '{0:.2f} {1:s} are worth US${2:d}'
在这个字符串中,
{0:.2f}
示意格式化第一个参数为带有两位小数的浮点数。{1:s}
示意格式化第二个参数为字符串。{2:d}
示意格式化第三个参数为一个整数。
要替换参数为这些格式化的参数,咱们传递format
办法一个序列:
In [75]: template.format(4.5560, 'Argentine Pesos', 1)Out[75]: '4.56 Argentine Pesos are worth US$1'
字符串格式化是一个很深的主题,有多种办法和大量的选项,能够管制字符串中的值是如何格式化的。举荐参阅Python官网文档。
字节和Unicode
在Python 3及以上版本中,Unicode是一级的字符串类型,这样能够更统一的解决ASCII和Non-ASCII文本。在老的Python版本中,字符串都是字节,不应用Unicode编码。如果晓得字符编码,能够将其转化为Unicode。看一个例子:
In [76]: val = "español"In [77]: valOut[77]: 'español'
能够用encode
将这个Unicode字符串编码为UTF-8:
In [78]: val_utf8 = val.encode('utf-8')In [79]: val_utf8Out[79]: b'espa\xc3\xb1ol'In [80]: type(val_utf8)Out[80]: bytes
如果你晓得一个字节对象的Unicode编码,用decode
办法能够解码:
In [81]: val_utf8.decode('utf-8')Out[81]: 'español'
工作中碰到的文件很多都是字节对象,自觉地将所有数据编码为Unicode是不可取的。
尽管用的不多,你能够在字节文本的后面加上一个b:
In [85]: bytes_val = b'this is bytes'In [86]: bytes_valOut[86]: b'this is bytes'In [87]: decoded = bytes_val.decode('utf8')In [88]: decoded # this is str (Unicode) nowOut[88]: 'this is bytes'
None
None是Python的空值类型。如果一个函数没有明确的返回值,就会默认返回None:
In [97]: a = NoneIn [98]: a is NoneOut[98]: TrueIn [99]: b = 5In [100]: b is not NoneOut[100]: True
None也经常作为函数的默认参数:
def add_and_maybe_multiply(a, b, c=None): result = a + b if c is not None: result = result * c return result
另外,None不仅是一个保留字,还是惟一的NoneType的实例:
In [101]: type(None)Out[101]: NoneType
日期和工夫
Python内建的datetime
模块提供了datetime
、date
和time
类型。datetime
类型联合了date
和time
,是最常应用的:
In [102]: from datetime import datetime, date, timeIn [103]: dt = datetime(2011, 10, 29, 20, 30, 21)In [104]: dt.dayOut[104]: 29In [105]: dt.minuteOut[105]: 30
依据datetime
实例,你能够用date
和time
提取出各自的对象:
In [106]: dt.date()Out[106]: datetime.date(2011, 10, 29)In [107]: dt.time()Out[107]: datetime.time(20, 30, 21)
strftime
办法能够将datetime格式化为字符串:
In [108]: dt.strftime('%m/%d/%Y %H:%M')Out[108]: '10/29/2011 20:30'
strptime
能够将字符串转换成datetime
对象:
In [109]: datetime.strptime('20091031', '%Y%m%d')Out[109]: datetime.datetime(2009, 10, 31, 0, 0)
表2-5列出了所有的格式化命令。
当你聚类或对工夫序列进行分组,替换datetimes的time字段有时会很有用。例如,用0替换分和秒:
In [110]: dt.replace(minute=0, second=0)Out[110]: datetime.datetime(2011, 10, 29, 20, 0)
因为datetime.datetime
是不可变类型,下面的办法会产生新的对象。
两个datetime对象的差会产生一个datetime.timedelta
类型:
In [111]: dt2 = datetime(2011, 11, 15, 22, 30)In [112]: delta = dt2 - dtIn [113]: deltaOut[113]: datetime.timedelta(17, 7179)In [114]: type(delta)Out[114]: datetime.timedelta
后果timedelta(17, 7179)
指明了timedelta
将17天、7179秒的编码方式。
将timedelta
增加到datetime
,会产生一个新的偏移datetime
:
In [115]: dtOut[115]: datetime.datetime(2011, 10, 29, 20, 30, 21)In [116]: dt + deltaOut[116]: datetime.datetime(2011, 11, 15, 22, 30)
控制流
if、elif和else
if
前面能够跟一个或多个elif
,所有条件都是False时,还能够增加一个else
:
if x < 0: print('It's negative')elif x == 0: print('Equal to zero')elif 0 < x < 5: print('Positive but smaller than 5')else: print('Positive and larger than or equal to 5')
如果某个条件为True,前面的elif
就不会被执行。当应用and和or时,复合条件语句是从左到右执行,也能够把比拟式串在一起:
In [120]: 4 > 3 > 2 > 1Out[120]: True
for循环
for循环是在一个汇合(列表或元组)中进行迭代,或者就是一个迭代器。for循环的规范语法是:
for value in collection: # do something with value
你能够用continue使for循环提前,跳过剩下的局部。看上面这个例子,将一个列表中的整数相加,跳过None。
break只中断for循环的最内层,其余的for循环仍会运行。
如果汇合或迭代器中的元素序列(元组或列表),能够用for循环将其不便地拆分成变量:
for a, b, c in iterator: # do something
While循环
while循环指定了条件和代码,当条件为False或用break退出循环,代码才会退出:
x = 256total = 0while x > 0: if total > 500: break total += x x = x // 2
pass
pass是Python中的非操作语句。代码块不须要任何动作时能够应用(作为未执行代码的占位符);因为Python须要应用空白字符划定代码块,所以须要pass:
if x < 0: print('negative!')elif x == 0: # TODO: put something smart here passelse: print('positive!')
range
range函数返回一个迭代器,它产生一个均匀分布的整数序列:
In [122]: range(10)Out[122]: range(0, 10)In [123]: list(range(10))Out[123]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range的三个参数是(终点,起点,步进):
In [124]: list(range(0, 20, 2))Out[124]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]In [125]: list(range(5, 0, -1))Out[125]: [5, 4, 3, 2, 1]
能够看到,range产生的整数不包含起点。range的常见用法是用序号迭代序列:
seq = [1, 2, 3, 4]for i in range(len(seq)): val = seq[i]
能够应用list来存储range在其余数据结构中生成的所有整数,默认的迭代器模式通常是你想要的。尽管range能够产生任意大的数,但任意时刻耗用的内存却很小。
三元表达式
Python中的三元表达式能够将if-else语句放到一行里。语法如下:
value = true-expr if condition else false-expr
true-expr
或false-expr
能够是任何Python代码。它和上面的代码成果雷同:
if condition: value = true-exprelse: value = false-expr
尽管应用三元表达式能够压缩代码,但会升高代码可读性。