《利用Python進行數(shù)據(jù)分析·第2版》第2章 Python語法基礎(chǔ)褒脯,IPython和Jupyter Notebooks


第1章 準備工作
第2章 Python語法基礎(chǔ)追他,IPython和Jupyter Notebooks
第3章 Python的數(shù)據(jù)結(jié)構(gòu)坟募、函數(shù)和文件
第4章 NumPy基礎(chǔ):數(shù)組和矢量計算
第5章 pandas入門
第6章 數(shù)據(jù)加載、存儲與文件格式
第7章 數(shù)據(jù)清洗和準備
第8章 數(shù)據(jù)規(guī)整:聚合邑狸、合并和重塑
第9章 繪圖和可視化
第10章 數(shù)據(jù)聚合與分組運算
第11章 時間序列
第12章 pandas高級應(yīng)用
第13章 Python建模庫介紹
第14章 數(shù)據(jù)分析案例
附錄A NumPy高級應(yīng)用
附錄B 更多關(guān)于IPython的內(nèi)容(完)


當(dāng)我在2011年和2012年寫作本書的第一版時懈糯,可用的學(xué)習(xí)Python數(shù)據(jù)分析的資源很少。這部分上是一個雞和蛋的問題:我們現(xiàn)在使用的庫单雾,比如pandas昂利、scikit-learn和statsmodels,那時相對來說并不成熟铁坎。2017年蜂奸,數(shù)據(jù)科學(xué)、數(shù)據(jù)分析和機器學(xué)習(xí)的資源已經(jīng)很多硬萍,原來通用的科學(xué)計算拓展到了計算機科學(xué)家扩所、物理學(xué)家和其它研究領(lǐng)域的工作人員。學(xué)習(xí)Python和成為軟件工程師的優(yōu)秀書籍也有了朴乖。

因為這本書是專注于Python數(shù)據(jù)處理的祖屏,對于一些Python的數(shù)據(jù)結(jié)構(gòu)和庫的特性難免不足。因此买羞,本章和第3章的內(nèi)容只夠你能學(xué)習(xí)本書后面的內(nèi)容袁勺。

在我來看,沒有必要為了數(shù)據(jù)分析而去精通Python畜普。我鼓勵你使用IPython shell和Jupyter試驗示例代碼期丰,并學(xué)習(xí)不同類型、函數(shù)和方法的文檔吃挑。雖然我已盡力讓本書內(nèi)容循序漸進钝荡,但讀者偶爾仍會碰到?jīng)]有之前介紹過的內(nèi)容。

本書大部分內(nèi)容關(guān)注的是基于表格的分析和處理大規(guī)模數(shù)據(jù)集的數(shù)據(jù)準備工具舶衬。為了使用這些工具埠通,必須首先將混亂的數(shù)據(jù)規(guī)整為整潔的表格(或結(jié)構(gòu)化)形式。幸好逛犹,Python是一個理想的語言端辱,可以快速整理數(shù)據(jù)梁剔。Python使用得越熟練,越容易準備新數(shù)據(jù)集以進行分析舞蔽。

最好在IPython和Jupyter中親自嘗試本書中使用的工具荣病。當(dāng)你學(xué)會了如何啟動Ipython和Jupyter,我建議你跟隨示例代碼進行練習(xí)喷鸽。與任何鍵盤驅(qū)動的操作環(huán)境一樣众雷,記住常見的命令也是學(xué)習(xí)曲線的一部分灸拍。

筆記:本章沒有介紹Python的某些概念做祝,如類和面向?qū)ο缶幊蹋憧赡軙l(fā)現(xiàn)它們在Python數(shù)據(jù)分析中很有用鸡岗。
為了加強Python知識混槐,我建議你學(xué)習(xí)官方Python教程,https://docs.python.org/3/轩性,或是通用的Python教程書籍声登,比如:

  • Python Cookbook,第3版揣苏,David Beazley和Brian K. Jones著(O’Reilly)
  • 流暢的Python悯嗓,Luciano Ramalho著 (O’Reilly)
  • 高效的Python,Brett Slatkin著 (Pearson)

2.1 Python解釋器

Python是解釋性語言卸察。Python解釋器同一時間只能運行一個程序的一條語句脯厨。標準的交互Python解釋器可以在命令行中通過鍵入python命令打開:

$ python
Python 3.6.0 | packaged by conda-forge | (default, Jan 13 2017, 23:17:12)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 5
>>> print(a)
5

>>>提示輸入代碼。要退出Python解釋器返回終端坑质,可以輸入exit()或按Ctrl-D合武。

運行Python程序只需調(diào)用Python的同時,使用一個.py文件作為它的第一個參數(shù)涡扼。假設(shè)創(chuàng)建了一個hello_world.py文件稼跳,它的內(nèi)容是:

print('Hello world')

你可以用下面的命令運行它(hello_world.py文件必須位于終端的工作目錄):

$ python hello_world.py
Hello world

一些Python程序員總是這樣執(zhí)行Python代碼的,從事數(shù)據(jù)分析和科學(xué)計算的人卻會使用IPython吃沪,一個強化的Python解釋器汤善,或Jupyter notebooks,一個網(wǎng)頁代碼筆記本票彪,它原先是IPython的一個子項目萎津。在本章中,我介紹了如何使用IPython和Jupyter抹镊,在附錄A中有更深入的介紹锉屈。當(dāng)你使用%run命令,IPython會同樣執(zhí)行指定文件中的代碼垮耳,結(jié)束之后颈渊,還可以與結(jié)果交互:

$ ipython
Python 3.6.0 | packaged by conda-forge | (default, Jan 13 2017, 23:17:12)
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: %run hello_world.py
Hello world

In [2]:

IPython默認采用序號的格式In [2]:遂黍,與標準的>>>提示符不同。

2.2 IPython基礎(chǔ)

在本節(jié)中俊嗽,我們會教你打開運行IPython shell和jupyter notebook雾家,并介紹一些基本概念。

運行IPython Shell

你可以用ipython在命令行打開IPython Shell绍豁,就像打開普通的Python解釋器:

$ ipython
Python 3.6.0 | packaged by conda-forge | (default, Jan 13 2017, 23:17:12)
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: a = 5
In [2]: a
Out[2]: 5

你可以通過輸入代碼并按Return(或Enter)芯咧,運行任意Python語句。當(dāng)你只輸入一個變量竹揍,它會顯示代表的對象:

In [5]: import numpy as np

In [6]: data = {i : np.random.randn() for i in range(7)}

In [7]: data
Out[7]: 
{0: -0.20470765948471295,
 1: 0.47894333805754824,
 2: -0.5194387150567381,
 3: -0.55573030434749,
 4: 1.9657805725027142,
 5: 1.3934058329729904,
6: 0.09290787674371767}

前兩行是Python代碼語句敬飒;第二條語句創(chuàng)建一個名為data的變量,它引用一個新創(chuàng)建的Python字典芬位。最后一行打印data的值无拗。

許多Python對象被格式化為更易讀的形式,或稱作pretty-printed昧碉,它與普通的print不同英染。如果在標準Python解釋器中打印上述data變量,則可讀性要降低:

>>> from numpy.random import randn
>>> data = {i : randn() for i in range(7)}
>>> print(data)
{0: -1.5948255432744511, 1: 0.10569006472787983, 2: 1.972367135977295,
3: 0.15455217573074576, 4: -0.24058577449429575, 5: -1.2904897053651216,
6: 0.3308507317325902}

IPython還支持執(zhí)行任意代碼塊(通過一個華麗的復(fù)制-粘貼方法)和整段Python腳本的功能被饿。你也可以使用Jupyter notebook運行大代碼塊四康,接下來就會看到。

運行Jupyter Notebook

notebook是Jupyter項目的重要組件之一狭握,它是一個代碼闪金、文本(有標記或無標記)、數(shù)據(jù)可視化或其它輸出的交互式文檔哥牍。Jupyter Notebook需要與內(nèi)核互動毕泌,內(nèi)核是Jupyter與其它編程語言的交互編程協(xié)議。Python的Jupyter內(nèi)核是使用IPython嗅辣。要啟動Jupyter撼泛,在命令行中輸入jupyter notebook:

$ jupyter notebook
[I 15:20:52.739 NotebookApp] Serving notebooks from local directory:
/home/wesm/code/pydata-book
[I 15:20:52.739 NotebookApp] 0 active kernels
[I 15:20:52.739 NotebookApp] The Jupyter Notebook is running at:
http://localhost:8888/
[I 15:20:52.740 NotebookApp] Use Control-C to stop this server and shut down
all kernels (twice to skip confirmation).
Created new window in existing browser session.

在多數(shù)平臺上,Jupyter會自動打開默認的瀏覽器(除非指定了--no-browser)澡谭≡柑猓或者,可以在啟動notebook之后蛙奖,手動打開網(wǎng)頁http://localhost:8888/潘酗。圖2-1展示了Google Chrome中的notebook。

筆記:許多人使用Jupyter作為本地的計算環(huán)境雁仲,但它也可以部署到服務(wù)器上遠程訪問仔夺。這里不做介紹,如果需要的話攒砖,鼓勵讀者自行到網(wǎng)上學(xué)習(xí)缸兔。

圖2-1 Jupyter notebook啟動頁面

要新建一個notebook日裙,點擊按鈕New,選擇“Python3”或“conda[默認項]”惰蜜。如果是第一次昂拂,點擊空格,輸入一行Python代碼抛猖。然后按Shift-Enter執(zhí)行格侯。

圖2-2 Jupyter新notebook頁面

當(dāng)保存notebook時(File目錄下的Save and Checkpoint),會創(chuàng)建一個后綴名為.ipynb的文件财著。這是一個自包含文件格式联四,包含當(dāng)前筆記本中的所有內(nèi)容(包括所有已評估的代碼輸出)∑盎拢可以被其它Jupyter用戶加載和編輯碎连。要加載存在的notebook灰羽,把它放到啟動notebook進程的相同目錄內(nèi)驮履。你可以用本書的示例代碼練習(xí),見圖2-3廉嚼。

雖然Jupyter notebook和IPython shell使用起來不同玫镐,本章中幾乎所有的命令和工具都可以通用。

圖2-3 Jupyter查看一個存在的notebook的頁面

Tab補全

從外觀上怠噪,IPython shell和標準的Python解釋器只是看起來不同恐似。IPython shell的進步之一是具備其它IDE和交互計算分析環(huán)境都有的tab補全功能。在shell中輸入表達式傍念,按下Tab矫夷,會搜索已輸入變量(對象、函數(shù)等等)的命名空間:

In [1]: an_apple = 27

In [2]: an_example = 42

In [3]: an<Tab>
an_apple    and         an_example  any

在這個例子中憋槐,IPython呈現(xiàn)出了之前兩個定義的變量和Python的關(guān)鍵字和內(nèi)建的函數(shù)any双藕。當(dāng)然,你也可以補全任何對象的方法和屬性:

In [3]: b = [1, 2, 3]

In [4]: b.<Tab>
b.append  b.count   b.insert  b.reverse
b.clear   b.extend  b.pop     b.sort
b.copy    b.index   b.remove

同樣也適用于模塊:

In [1]: import datetime

In [2]: datetime.<Tab>
datetime.date          datetime.MAXYEAR       datetime.timedelta
datetime.datetime      datetime.MINYEAR       datetime.timezone
datetime.datetime_CAPI datetime.time          datetime.tzinfo

在Jupyter notebook和新版的IPython(5.0及以上)阳仔,自動補全功能是下拉框的形式忧陪。

筆記:注意戳气,默認情況下售担,IPython會隱藏下劃線開頭的方法和屬性,比如魔術(shù)方法和內(nèi)部的“私有”方法和屬性伏社,以避免混亂的顯示(和讓新手迷惑F谰亍)這些也可以tab補全叶堆,但是你必須首先鍵入一個下劃線才能看到它們。如果你喜歡總是在tab補全中看到這樣的方法斥杜,你可以IPython配置中進行設(shè)置虱颗「┟龋可以在IPython文檔中查找方法。

除了補全命名上枕、對象和模塊屬性咐熙,Tab還可以補全其它的。當(dāng)輸入看似文件路徑時(即使是Python字符串)辨萍,按下Tab也可以補全電腦上對應(yīng)的文件信息:

In [7]: datasets/movielens/<Tab>
datasets/movielens/movies.dat    datasets/movielens/README
datasets/movielens/ratings.dat   datasets/movielens/users.dat

In [7]: path = 'datasets/movielens/<Tab>
datasets/movielens/movies.dat    datasets/movielens/README
datasets/movielens/ratings.dat   datasets/movielens/users.dat

結(jié)合%run棋恼,tab補全可以節(jié)省許多鍵盤操作。

另外锈玉,tab補全可以補全函數(shù)的關(guān)鍵詞參數(shù)(包括等于號=)爪飘。見圖2-4。

圖2-4 Jupyter notebook中自動補全函數(shù)關(guān)鍵詞

后面會仔細地學(xué)習(xí)函數(shù)拉背。

自省

在變量前后使用問號师崎?,可以顯示對象的信息:

In [8]: b = [1, 2, 3]

In [9]: b?
Type:       list
String Form:[1, 2, 3]
Length:     3
Docstring:
list() -> new empty list
list(iterable) -> new list initialized from iterable's items

In [10]: print?
Docstring:
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file:  a file-like object (stream); defaults to the current sys.stdout.
sep:   string inserted between values, default a space.
end:   string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
Type:      builtin_function_or_method

這可以作為對象的自省椅棺。如果對象是一個函數(shù)或?qū)嵗椒ɡ缯郑x過的文檔字符串,也會顯示出信息两疚。假設(shè)我們寫了一個如下的函數(shù):

def add_numbers(a, b):
    """
    Add two numbers together

    Returns
    -------
    the_sum : type of arguments
    """
    return a + b

然后使用?符號床估,就可以顯示如下的文檔字符串:

In [11]: add_numbers?
Signature: add_numbers(a, b)
Docstring:
Add two numbers together

Returns
-------
the_sum : type of arguments
File:      <ipython-input-9-6a548a216e27>
Type:      function

使用??會顯示函數(shù)的源碼:

In [12]: add_numbers??
Signature: add_numbers(a, b)
Source:
def add_numbers(a, b):
    """
    Add two numbers together

    Returns
    -------
    the_sum : type of arguments
    """
    return a + b
File:      <ipython-input-9-6a548a216e27>
Type:      function

?還有一個用途,就是像Unix或Windows命令行一樣搜索IPython的命名空間诱渤。字符與通配符結(jié)合可以匹配所有的名字丐巫。例如,我們可以獲得所有包含load的頂級NumPy命名空間:

In [13]: np.*load*?
np.__loader__
np.load
np.loads
np.loadtxt
np.pkgload

%run命令

你可以用%run命令運行所有的Python程序勺美。假設(shè)有一個文件ipython_script_test.py

def f(x, y, z):
    return (x + y) / z

a = 5
b = 6
c = 7.5

result = f(a, b, c)

可以如下運行:

In [14]: %run ipython_script_test.py

這段腳本運行在空的命名空間(沒有import和其它定義的變量)递胧,因此結(jié)果和普通的運行方式python script.py相同。文件中所有定義的變量(import赡茸、函數(shù)和全局變量缎脾,除非拋出異常),都可以在IPython shell中隨后訪問:

In [15]: c
Out [15]: 7.5

In [16]: result
Out[16]: 1.4666666666666666

如果一個Python腳本需要命令行參數(shù)(在sys.argv中查找)坛掠,可以在文件路徑之后傳遞赊锚,就像在命令行上運行一樣。

筆記:如果想讓一個腳本訪問IPython已經(jīng)定義過的變量屉栓,可以使用%run -i舷蒲。

在Jupyter notebook中,你也可以使用%load友多,它將腳本導(dǎo)入到一個代碼格中:

>>> %load ipython_script_test.py

    def f(x, y, z):
        return (x + y) / z
    a = 5
    b = 6
    c = 7.5

    result = f(a, b, c)

中斷運行的代碼

代碼運行時按Ctrl-C牲平,無論是%run或長時間運行命令,都會導(dǎo)致KeyboardInterrupt域滥。這會導(dǎo)致幾乎所有Python程序立即停止纵柿,除非一些特殊情況蜈抓。

警告:當(dāng)Python代碼調(diào)用了一些編譯的擴展模塊,按Ctrl-C不一定將執(zhí)行的程序立即停止昂儒。在這種情況下沟使,你必須等待,直到控制返回Python解釋器渊跋,或者在更糟糕的情況下強制終止Python進程腊嗡。

從剪貼板執(zhí)行程序

如果使用Jupyter notebook,你可以將代碼復(fù)制粘貼到任意代碼格執(zhí)行拾酝。在IPython shell中也可以從剪貼板執(zhí)行燕少。假設(shè)在其它應(yīng)用中復(fù)制了如下代碼:

x = 5
y = 7
if x > 5:
    x += 1

    y = 8

最簡單的方法是使用%paste%cpaste函數(shù)。%paste可以直接運行剪貼板中的代碼:

In [17]: %paste
x = 5
y = 7
if x > 5:
    x += 1

    y = 8
## -- End pasted text --

%cpaste功能類似蒿囤,但會給出一條提示:

In [18]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:x = 5
:y = 7
:if x > 5:
:    x += 1
:
:    y = 8
:--

使用%cpaste客们,你可以粘貼任意多的代碼再運行。你可能想在運行前材诽,先看看代碼底挫。如果粘貼了錯誤的代碼,可以用Ctrl-C中斷岳守。

鍵盤快捷鍵

IPython有許多鍵盤快捷鍵進行導(dǎo)航提示(類似Emacs文本編輯器或UNIX bash Shell)和交互shell的歷史命令凄敢。表2-1總結(jié)了常見的快捷鍵碌冶。圖2-5展示了一部分湿痢,如移動光標。

圖2-5 IPython shell中一些快捷鍵的說明
表2-1 IPython的標準快捷鍵

Jupyter notebooks有另外一套龐大的快捷鍵扑庞。因為它的快捷鍵比IPython的變化快譬重,建議你參閱Jupyter notebook的幫助文檔。

魔術(shù)命令

IPython中特殊的命令(Python中沒有)被稱作“魔術(shù)”命令罐氨。這些命令可以使普通任務(wù)更便捷臀规,更容易控制IPython系統(tǒng)。魔術(shù)命令是在指令前添加百分號%前綴栅隐。例如塔嬉,可以用%timeit(這個命令后面會詳談)測量任何Python語句,例如矩陣乘法租悄,的執(zhí)行時間:

In [20]: a = np.random.randn(100, 100)

In [20]: %timeit np.dot(a, a)
10000 loops, best of 3: 20.9 μs per loop

魔術(shù)命令可以被看做IPython中運行的命令行谨究。許多魔術(shù)命令有“命令行”選項,可以通過泣棋?查看:

In [21]: %debug?
Docstring:
::

  %debug [--breakpoint FILE:LINE] [statement [statement ...]]

Activate the interactive debugger.

This magic command support two ways of activating debugger.
One is to activate debugger before executing code.  This way, you
can set a break point, to step through the code from the point.
You can use this mode by giving statements to execute and optionally
a breakpoint.

The other one is to activate debugger in post-mortem mode.  You can
activate this mode simply running %debug without any argument.
If an exception has just occurred, this lets you inspect its stack
frames interactively.  Note that this will always work only on the last
traceback that occurred, so you must call this quickly after an
exception that you wish to inspect has fired, because if another one
occurs, it clobbers the previous one.

If you want IPython to automatically do this on every exception, see
the %pdb magic for more details.

positional arguments:
  statement             Code to run in debugger. You can omit this in cell
                        magic mode.

optional arguments:
  --breakpoint <FILE:LINE>, -b <FILE:LINE>
                        Set break point at LINE in FILE.

魔術(shù)函數(shù)默認可以不用百分號胶哲,只要沒有變量和函數(shù)名相同。這個特點被稱為“自動魔術(shù)”潭辈,可以用%automagic打開或關(guān)閉鸯屿。

一些魔術(shù)函數(shù)與Python函數(shù)很像澈吨,它的結(jié)果可以賦值給一個變量:

In [22]: %pwd
Out[22]: '/home/wesm/code/pydata-book

In [23]: foo = %pwd

In [24]: foo
Out[24]: '/home/wesm/code/pydata-book'

IPython的文檔可以在shell中打開,我建議你用%quickref%magic學(xué)習(xí)下所有特殊命令寄摆。表2-2列出了一些可以提高生產(chǎn)率的交互計算和Python開發(fā)的IPython指令谅辣。

表2-2 一些常用的IPython魔術(shù)命令

集成Matplotlib

IPython在分析計算領(lǐng)域能夠流行的原因之一是它非常好的集成了數(shù)據(jù)可視化和其它用戶界面庫,比如matplotlib婶恼。不用擔(dān)心以前沒用過matplotlib屈藐,本書后面會詳細介紹。%matplotlib魔術(shù)函數(shù)配置了IPython shell和Jupyter notebook中的matplotlib熙尉。這點很重要联逻,其它創(chuàng)建的圖不會出現(xiàn)(notebook)或獲取session的控制,直到結(jié)束(shell)检痰。

在IPython shell中包归,運行%matplotlib可以進行設(shè)置,可以創(chuàng)建多個繪圖窗口铅歼,而不會干擾控制臺session:

In [26]: %matplotlib
Using matplotlib backend: Qt4Agg

在JUpyter中公壤,命令有所不同(圖2-6):

In [26]: %matplotlib inline
圖2-6 Jupyter行內(nèi)matplotlib作圖

2.3 Python語法基礎(chǔ)

在本節(jié)中,我將概述基本的Python概念和語言機制椎椰。在下一章厦幅,我將詳細介紹Python的數(shù)據(jù)結(jié)構(gòu)、函數(shù)和其它內(nèi)建工具慨飘。

語言的語義

Python的語言設(shè)計強調(diào)的是可讀性确憨、簡潔和清晰。有些人稱Python為“可執(zhí)行的偽代碼”瓤的。

使用縮進休弃,而不是括號

Python使用空白字符(tab和空格)來組織代碼,而不是像其它語言圈膏,比如R塔猾、C++、JAVA和Perl那樣使用括號稽坤≌傻椋看一個排序算法的for循環(huán):

for x in array:
    if x < pivot:
        less.append(x)
    else:
        greater.append(x)

冒號標志著縮進代碼塊的開始,冒號之后的所有代碼的縮進量必須相同尿褪,直到代碼塊結(jié)束睦擂。不管是否喜歡這種形式,使用空白符是Python程序員開發(fā)的一部分茫多,在我看來祈匙,這可以讓python的代碼可讀性大大優(yōu)于其它語言。雖然期初看起來很奇怪,經(jīng)過一段時間夺欲,你就能適應(yīng)了跪帝。

筆記:我強烈建議你使用四個空格作為默認的縮進,可以使用tab代替四個空格些阅。許多文本編輯器的設(shè)置是使用制表位替代空格伞剑。某些人使用tabs或不同數(shù)目的空格數(shù),常見的是使用兩個空格市埋。大多數(shù)情況下黎泣,四個空格是大多數(shù)人采用的方法,因此建議你也這樣做缤谎。

你應(yīng)該已經(jīng)看到抒倚,Python的語句不需要用分號結(jié)尾。但是坷澡,分號卻可以用來給同在一行的語句切分:

a = 5; b = 6; c = 7

Python不建議將多條語句放到一行托呕,這會降低代碼的可讀性。

萬物皆對象

Python語言的一個重要特性就是它的對象模型的一致性频敛。每個數(shù)字项郊、字符串、數(shù)據(jù)結(jié)構(gòu)斟赚、函數(shù)着降、類、模塊等等拗军,都是在Python解釋器的自有“盒子”內(nèi)任洞,它被認為是Python對象。每個對象都有類型(例如食绿,字符串或函數(shù))和內(nèi)部數(shù)據(jù)侈咕。在實際中,這可以讓語言非常靈活器紧,因為函數(shù)也可以被當(dāng)做對象使用。

注釋

任何前面帶有井號#的文本都會被Python解釋器忽略楼眷。這通常被用來添加注釋铲汪。有時,你會想排除一段代碼罐柳,但并不刪除掌腰。簡便的方法就是將其注釋掉:

results = []
for line in file_handle:
    # keep the empty lines for now
    # if len(line) == 0:
    #   continue
    results.append(line.replace('foo', 'bar'))

也可以在執(zhí)行過的代碼后面添加注釋。一些人習(xí)慣在代碼之前添加注釋张吉,前者這種方法有時也是有用的:

print("Reached this line")  # Simple status report

函數(shù)和對象方法調(diào)用

你可以用圓括號調(diào)用函數(shù)齿梁,傳遞零個或幾個參數(shù),或者將返回值給一個變量:

result = f(x, y, z)
g()

幾乎Python中的每個對象都有附加的函數(shù),稱作方法勺择,可以用來訪問對象的內(nèi)容创南。可以用下面的語句調(diào)用:

obj.some_method(x, y, z)

函數(shù)可以使用位置和關(guān)鍵詞參數(shù):

result = f(a, b, c, d=5, e='foo')

后面會有更多介紹省核。

變量和參數(shù)傳遞

當(dāng)在Python中創(chuàng)建變量(或名字)稿辙,你就在等號右邊創(chuàng)建了一個對這個變量的引用∑遥考慮一個整數(shù)列表:

In [8]: a = [1, 2, 3]

假設(shè)將a賦值給一個新變量b:

In [9]: b = a

在有些方法中邻储,這個賦值會將數(shù)據(jù)[1, 2, 3]也復(fù)制。在Python中旧噪,a和b實際上是同一個對象吨娜,即原有列表[1, 2, 3](見圖2-7)。你可以在a中添加一個元素淘钟,然后檢查b:

In [10]: a.append(4)

In [11]: b
Out[11]: [1, 2, 3, 4]
圖2-7 對同一對象的雙重引用

理解Python的引用的含義萌壳,數(shù)據(jù)是何時、如何日月、為何復(fù)制的袱瓮,是非常重要的。尤其是當(dāng)你用Python處理大的數(shù)據(jù)集時爱咬。

筆記:賦值也被稱作綁定尺借,我們是把一個名字綁定給一個對象。變量名有時可能被稱為綁定變量精拟。

當(dāng)你將對象作為參數(shù)傳遞給函數(shù)時燎斩,新的局域變量創(chuàng)建了對原始對象的引用,而不是復(fù)制蜂绎。如果在函數(shù)里綁定一個新對象到一個變量栅表,這個變動不會反映到上一層。因此可以改變可變參數(shù)的內(nèi)容师枣。假設(shè)有以下函數(shù):

def append_element(some_list, element):
    some_list.append(element)

然后有:

In [27]: data = [1, 2, 3]

In [28]: append_element(data, 4)

In [29]: data
Out[29]: [1, 2, 3, 4]

動態(tài)引用怪瓶,強類型

與許多編譯語言(如JAVA和C++)對比,Python中的對象引用不包含附屬的類型践美。下面的代碼是沒有問題的:

In [12]: a = 5

In [13]: type(a)
Out[13]: int

In [14]: a = 'foo'

In [15]: type(a)
Out[15]: str

變量是在特殊命名空間中的對象的名字洗贰,類型信息保存在對象自身中。一些人可能會說Python不是“類型化語言”陨倡。這是不正確的敛滋,看下面的例子:

In [16]: '5' + 5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-16-f9dbf5f0b234> in <module>()
----> 1 '5' + 5
TypeError: must be str, not int

在某些語言中,例如Visual Basic兴革,字符串‘5’可能被默許轉(zhuǎn)換(或投射)為整數(shù)绎晃,因此會產(chǎn)生10蜜唾。但在其它語言中,例如JavaScript庶艾,整數(shù)5會被投射成字符串袁余,結(jié)果是聯(lián)結(jié)字符串‘55’。在這個方面落竹,Python被認為是強類型化語言泌霍,意味著每個對象都有明確的類型(或類),默許轉(zhuǎn)換只會發(fā)生在特定的情況下述召,例如:

In [17]: a = 4.5

In [18]: b = 2

# String formatting, to be visited later
In [19]: print('a is {0}, b is {1}'.format(type(a), type(b)))
a is <class 'float'>, b is <class 'int'>

In [20]: a / b
Out[20]: 2.25

知道對象的類型很重要朱转,最好能讓函數(shù)可以處理多種類型的輸入。你可以用isinstance函數(shù)檢查對象是某個類型的實例:

In [21]: a = 5

In [22]: isinstance(a, int)
Out[22]: True

isinstance可以用類型元組积暖,檢查對象的類型是否在元組中:

In [23]: a = 5; b = 4.5

In [24]: isinstance(a, (int, float))
Out[24]: True

In [25]: isinstance(b, (int, float))
Out[25]: True

屬性和方法

Python的對象通常都有屬性(其它存儲在對象內(nèi)部的Python對象)和方法(對象的附屬函數(shù)可以訪問對象的內(nèi)部數(shù)據(jù))藤为。可以用obj.attribute_name訪問屬性和方法:

In [1]: a = 'foo'

In [2]: a.<Press Tab>
a.capitalize  a.format      a.isupper     a.rindex      a.strip
a.center      a.index       a.join        a.rjust       a.swapcase
a.count       a.isalnum     a.ljust       a.rpartition  a.title
a.decode      a.isalpha     a.lower       a.rsplit      a.translate
a.encode      a.isdigit     a.lstrip      a.rstrip      a.upper
a.endswith    a.islower     a.partition   a.split       a.zfill
a.expandtabs  a.isspace     a.replace     a.splitlines
a.find        a.istitle     a.rfind       a.startswith

也可以用getattr函數(shù)夺刑,通過名字訪問屬性和方法:

In [27]: getattr(a, 'split')
Out[27]: <function str.split>

在其它語言中缅疟,訪問對象的名字通常稱作“反射”。本書不會大量使用getattr函數(shù)和相關(guān)的hasattrsetattr函數(shù)遍愿,使用這些函數(shù)可以高效編寫原生的存淫、可重復(fù)使用的代碼。

鴨子類型

經(jīng)常地沼填,你可能不關(guān)心對象的類型桅咆,只關(guān)心對象是否有某些方法或用途。這通常被稱為“鴨子類型”坞笙,來自“走起來像鴨子岩饼、叫起來像鴨子,那么它就是鴨子”的說法薛夜。例如籍茧,你可以通過驗證一個對象是否遵循迭代協(xié)議,判斷它是可迭代的梯澜。對于許多對象寞冯,這意味著它有一個__iter__魔術(shù)方法,其它更好的判斷方法是使用iter函數(shù):

def isiterable(obj):
    try:
        iter(obj)
        return True
    except TypeError: # not iterable
        return False

這個函數(shù)會返回字符串以及大多數(shù)Python集合類型為True

In [29]: isiterable('a string')
Out[29]: True

In [30]: isiterable([1, 2, 3])
Out[30]: True

In [31]: isiterable(5)
Out[31]: False

我總是用這個功能編寫可以接受多種輸入類型的函數(shù)腊徙。常見的例子是編寫一個函數(shù)可以接受任意類型的序列(list简十、tuple、ndarray)或是迭代器撬腾。你可先檢驗對象是否是列表(或是NUmPy數(shù)組),如果不是的話恢恼,將其轉(zhuǎn)變成列表:

if not isinstance(x, list) and isiterable(x):
    x = list(x)

引入

在Python中民傻,模塊就是一個有.py擴展名、包含Python代碼的文件。假設(shè)有以下模塊:

# some_module.py
PI = 3.14159

def f(x):
    return x + 2

def g(a, b):
    return a + b

如果想從同目錄下的另一個文件訪問some_module.py中定義的變量和函數(shù)漓踢,可以:

import some_module
result = some_module.f(5)
pi = some_module.PI

或者:

from some_module import f, g, PI
result = g(5, PI)

使用as關(guān)鍵詞牵署,你可以給引入起不同的變量名:

import some_module as sm
from some_module import PI as pi, g as gf

r1 = sm.f(pi)
r2 = gf(6, pi)

二元運算符和比較運算符

大多數(shù)二元數(shù)學(xué)運算和比較都不難想到:

In [32]: 5 - 7
Out[32]: -2

In [33]: 12 + 21.5
Out[33]: 33.5

In [34]: 5 <= 2
Out[34]: False

表2-3列出了所有的二元運算符。

要判斷兩個引用是否指向同一個對象喧半,可以使用is方法奴迅。is not可以判斷兩個對象是不同的:

In [35]: a = [1, 2, 3]

In [36]: b = a

In [37]: c = list(a)

In [38]: a is b
Out[38]: True

In [39]: a is not c
Out[39]: True

因為list總是創(chuàng)建一個新的Python列表(即復(fù)制),我們可以斷定c是不同于a的挺据。使用is比較與==運算符不同取具,如下:

In [40]: a == c
Out[40]: True

isis not常用來判斷一個變量是否為None,因為只有一個None的實例:

In [41]: a = None

In [42]: a is None
Out[42]: True
表2-3 二元運算符

可變與不可變對象

Python中的大多數(shù)對象扁耐,比如列表暇检、字典、NumPy數(shù)組婉称,和用戶定義的類型(類)块仆,都是可變的。意味著這些對象或包含的值可以被修改:

In [43]: a_list = ['foo', 2, [4, 5]]

In [44]: a_list[2] = (3, 4)

In [45]: a_list
Out[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

記住,可以修改一個對象并不意味就要修改它俗壹。這被稱為副作用科汗。例如,當(dāng)寫一個函數(shù)策肝,任何副作用都要在文檔或注釋中寫明肛捍。如果可能的話,我推薦避免副作用之众,采用不可變的方式拙毫,即使要用到可變對象。

標量類型

Python的標準庫中有一些內(nèi)建的類型棺禾,用于處理數(shù)值數(shù)據(jù)缀蹄、字符串、布爾值膘婶,和日期時間缺前。這些單值類型被稱為標量類型,本書中稱其為標量悬襟。表2-4列出了主要的標量衅码。日期和時間處理會另外討論,因為它們是標準庫的datetime模塊提供的脊岳。

表2-4 Python的標量

數(shù)值類型

Python的主要數(shù)值類型是intfloat逝段。int可以存儲任意大的數(shù):

In [48]: ival = 17239871

In [49]: ival ** 6
Out[49]: 26254519291092456596965462913230729701102721

浮點數(shù)使用Python的float類型垛玻。每個數(shù)都是雙精度(64位)的值。也可以用科學(xué)計數(shù)法表示:

In [50]: fval = 7.243

In [51]: fval2 = 6.78e-5

不能得到整數(shù)的除法會得到浮點數(shù):

In [52]: 3 / 2
Out[52]: 1.5

要獲得C-風(fēng)格的整除(去掉小數(shù)部分)奶躯,可以使用底除運算符//:

In [53]: 3 // 2
Out[53]: 1

字符串

許多人是因為Python強大而靈活的字符串處理而使用Python的帚桩。你可以用單引號或雙引號來寫字符串:

a = 'one way of writing a string'
b = "another way"

對于有換行符的字符串,可以使用三引號嘹黔,'''或"""都行:

c = """
This is a longer string that
spans 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 assignment

In [58]: b = a.replace('string', 'longer string')

In [59]: b
Out[59]: 'this is a longer string'

經(jīng)過以上的操作,變量a并沒有被修改:

In [60]: a
Out[60]: 'this is a string'

許多Python對象使用str函數(shù)可以被轉(zhuǎn)化為字符串:

In [61]: a = 5.6

In [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序列开呐。后面會更詳細的介紹烟勋,本書中用到很多切片。

反斜杠是轉(zhuǎn)義字符筐付,意思是它備用來表示特殊字符卵惦,比如換行符\n或Unicode字符。要寫一個包含反斜杠的字符串瓦戚,需要進行轉(zhuǎn)義:

In [67]: s = '12\\34'

In [68]: print(s)
12\34

如果字符串中包含許多反斜杠沮尿,但沒有特殊字符,這樣做就很麻煩较解。幸好畜疾,可以在字符串前面加一個r,表明字符就是它自身:

In [69]: s = r'this\has\no\special\characters'

In [70]: s
Out[70]: 'this\\has\\no\\special\\characters'

r表示raw印衔。

將兩個字符串合并啡捶,會產(chǎn)生一個新的字符串:

In [71]: a = 'this is the first half '

In [72]: b = 'and this is the second half'

In [73]: a + b
Out[73]: 'this is the first half and this is the second half'

字符串的模板化或格式化,是另一個重要的主題奸焙。Python 3拓展了此類的方法瞎暑,這里只介紹一些。字符串對象有format方法与帆,可以替換格式化的參數(shù)為字符串了赌,產(chǎn)生一個新的字符串:

In [74]: template = '{0:.2f} {1:s} are worth US${2:d}'

在這個字符串中,

  • {0:.2f}表示格式化第一個參數(shù)為帶有兩位小數(shù)的浮點數(shù)玄糟。
  • {1:s}表示格式化第二個參數(shù)為字符串勿她。
  • {2:d}表示格式化第三個參數(shù)為一個整數(shù)。

要替換參數(shù)為這些格式化的參數(shù)阵翎,我們傳遞format方法一個序列:

In [75]: template.format(4.5560, 'Argentine Pesos', 1)
Out[75]: '4.56 Argentine Pesos are worth US$1'

字符串格式化是一個很深的主題嫂拴,有多種方法和大量的選項播揪,可以控制字符串中的值是如何格式化的贮喧。推薦參閱Python官方文檔筒狠。

這里概括介紹字符串處理,第8章的數(shù)據(jù)分析會詳細介紹箱沦。

字節(jié)和Unicode

在Python 3及以上版本中辩恼,Unicode是一級的字符串類型,這樣可以更一致的處理ASCII和Non-ASCII文本谓形。在老的Python版本中灶伊,字符串都是字節(jié),不使用Unicode編碼寒跳。假如知道字符編碼聘萨,可以將其轉(zhuǎn)化為Unicode⊥看一個例子:

In [76]: val = "espa?ol"

In [77]: val
Out[77]: 'espa?ol'

可以用encode將這個Unicode字符串編碼為UTF-8:

In [78]: val_utf8 = val.encode('utf-8')

In [79]: val_utf8
Out[79]: b'espa\xc3\xb1ol'

In [80]: type(val_utf8)
Out[80]: bytes

如果你知道一個字節(jié)對象的Unicode編碼米辐,用decode方法可以解碼:

In [81]: val_utf8.decode('utf-8')
Out[81]: 'espa?ol'

雖然UTF-8編碼已經(jīng)變成主流,但因為歷史的原因书释,你仍然可能碰到其它編碼的數(shù)據(jù):

In [82]: val.encode('latin1')
Out[82]: b'espa\xf1ol'

In [83]: val.encode('utf-16')
Out[83]: b'\xff\xfee\x00s\x00p\x00a\x00\xf1\x00o\x00l\x00'

In [84]: val.encode('utf-16le')
Out[84]: b'e\x00s\x00p\x00a\x00\xf1\x00o\x00l\x00'

工作中碰到的文件很多都是字節(jié)對象翘贮,盲目地將所有數(shù)據(jù)編碼為Unicode是不可取的。

雖然用的不多爆惧,你可以在字節(jié)文本的前面加上一個b:

In [85]: bytes_val = b'this is bytes'

In [86]: bytes_val
Out[86]: b'this is bytes'

In [87]: decoded = bytes_val.decode('utf8')

In [88]: decoded  # this is str (Unicode) now
Out[88]: 'this is bytes'

布爾值

Python中的布爾值有兩個狸页,True和False。比較和其它條件表達式可以用True和False判斷扯再。布爾值可以與and和or結(jié)合使用:

In [89]: True and True
Out[89]: True

In [90]: False or True
Out[90]: True

類型轉(zhuǎn)換

str芍耘、bool、int和float也是函數(shù)熄阻,可以用來轉(zhuǎn)換類型:

In [91]: s = '3.14159'

In [92]: fval = float(s)

In [93]: type(fval)
Out[93]: float

In [94]: int(fval)
Out[94]: 3

In [95]: bool(fval)
Out[95]: True

In [96]: bool(0)
Out[96]: False

None

None是Python的空值類型斋竞。如果一個函數(shù)沒有明確的返回值,就會默認返回None:

In [97]: a = None

In [98]: a is None
Out[98]: True

In [99]: b = 5

In [100]: b is not None
Out[100]: True

None也常常作為函數(shù)的默認參數(shù):

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內(nèi)建的datetime模塊提供了datetimedatetime類型复濒。datetime類型結(jié)合了datetime脖卖,是最常使用的:

In [102]: from datetime import datetime, date, time

In [103]: dt = datetime(2011, 10, 29, 20, 30, 21)

In [104]: dt.day
Out[104]: 29

In [105]: dt.minute
Out[105]: 30

根據(jù)datetime實例,你可以用datetime提取出各自的對象:

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可以將字符串轉(zhuǎn)換成datetime對象:

In [109]: datetime.strptime('20091031', '%Y%m%d')
Out[109]: datetime.datetime(2009, 10, 31, 0, 0)

表2-5列出了所有的格式化命令巧颈。

表2-5 Datetime格式化指令(與ISO C89兼容)

當(dāng)你聚類或?qū)r間序列進行分組畦木,替換datetimes的time字段有時會很有用。例如砸泛,用0替換分和秒:

In [110]: dt.replace(minute=0, second=0)
Out[110]: datetime.datetime(2011, 10, 29, 20, 0)

因為datetime.datetime是不可變類型十籍,上面的方法會產(chǎn)生新的對象蛆封。

兩個datetime對象的差會產(chǎn)生一個datetime.timedelta類型:

In [111]: dt2 = datetime(2011, 11, 15, 22, 30)

In [112]: delta = dt2 - dt

In [113]: delta
Out[113]: datetime.timedelta(17, 7179)

In [114]: type(delta)
Out[114]: datetime.timedelta

結(jié)果timedelta(17, 7179)指明了timedelta將17天、7179秒的編碼方式勾栗。

timedelta添加到datetime惨篱,會產(chǎn)生一個新的偏移datetime

In [115]: dt
Out[115]: datetime.datetime(2011, 10, 29, 20, 30, 21)

In [116]: dt + delta
Out[116]: datetime.datetime(2011, 11, 15, 22, 30)

控制流

Python有若干內(nèi)建的關(guān)鍵字進行條件邏輯、循環(huán)和其它控制流操作围俘。

if砸讳、elif和else

if是最廣為人知的控制流語句。它檢查一個條件界牡,如果為True簿寂,就執(zhí)行后面的語句:

if x < 0:
    print('It's negative')

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就不會被執(zhí)行。當(dāng)使用and和or時挽荠,復(fù)合條件語句是從左到右執(zhí)行:

In [117]: a = 5; b = 7

In [118]: c = 8; d = 4

In [119]: if a < b or c > d:
   .....:     print('Made it')
Made it

在這個例子中克胳,c > d不會被執(zhí)行,因為第一個比較是True:

也可以把比較式串在一起:

In [120]: 4 > 3 > 2 > 1
Out[120]: True

for循環(huán)

for循環(huán)是在一個集合(列表或元組)中進行迭代坤按,或者就是一個迭代器毯欣。for循環(huán)的標準語法是:

for value in collection:
    # do something with value

你可以用continue使for循環(huán)提前,跳過剩下的部分臭脓⌒锍看下面這個例子,將一個列表中的整數(shù)相加来累,跳過None:

sequence = [1, 2, None, 4, None, 5]
total = 0
for value in sequence:
    if value is None:
        continue
    total += value

可以用break跳出for循環(huán)砚作。下面的代碼將各元素相加,直到遇到5:

sequence = [1, 2, 0, 4, 6, 5, 2, 1]
total_until_5 = 0
for value in sequence:
    if value == 5:
        break
    total_until_5 += value

break只中斷for循環(huán)的最內(nèi)層嘹锁,其余的for循環(huán)仍會運行:

In [121]: for i in range(4):
   .....:     for j in range(4):
   .....:         if j > i:
   .....:             break
   .....:         print((i, j))
   .....:
(0, 0)
(1, 0)
(1, 1)
(2, 0)
(2, 1)
(2, 2)
(3, 0)
(3, 1)
(3, 2)
(3, 3)

如果集合或迭代器中的元素序列(元組或列表)葫录,可以用for循環(huán)將其方便地拆分成變量:

for a, b, c in iterator:
    # do something

While循環(huán)

while循環(huán)指定了條件和代碼,當(dāng)條件為False或用break退出循環(huán)领猾,代碼才會退出:

x = 256
total = 0
while x > 0:
    if total > 500:
        break
    total += x
    x = x // 2

pass

pass是Python中的非操作語句米同。代碼塊不需要任何動作時可以使用(作為未執(zhí)行代碼的占位符);因為Python需要使用空白字符劃定代碼塊摔竿,所以需要pass:

if x < 0:
    print('negative!')
elif x == 0:
    # TODO: put something smart here
    pass
else:
    print('positive!')

range

range函數(shù)返回一個迭代器面粮,它產(chǎn)生一個均勻分布的整數(shù)序列:

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的三個參數(shù)是(起點,終點继低,步進):

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產(chǎn)生的整數(shù)不包括終點。range的常見用法是用序號迭代序列:

seq = [1, 2, 3, 4]
for i in range(len(seq)):
    val = seq[i]

可以使用list來存儲range在其他數(shù)據(jù)結(jié)構(gòu)中生成的所有整數(shù),默認的迭代器形式通常是你想要的柴底。下面的代碼對0到99999中3或5的倍數(shù)求和:

sum = 0
for i in range(100000):
    # % is the modulo operator
    if i % 3 == 0 or i % 5 == 0:
        sum += i

雖然range可以產(chǎn)生任意大的數(shù)婿脸,但任意時刻耗用的內(nèi)存卻很小汇荐。

三元表達式

Python中的三元表達式可以將if-else語句放到一行里念恍。語法如下:

value = true-expr if condition else false-expr

true-exprfalse-expr可以是任何Python代碼幅骄。它和下面的代碼效果相同:

if condition:
    value = true-expr
else:
    value = false-expr

下面是一個更具體的例子:

In [126]: x = 5
In [127]: 'Non-negative' if x >= 0 else 'Negative'

Out[127]: 'Non-negative'

和if-else一樣挑秉,只有一個表達式會被執(zhí)行。因此准颓,三元表達式中的if和else可以包含大量的計算美浦,但只有True的分支會被執(zhí)行。

雖然使用三元表達式可以壓縮代碼答憔,但會降低代碼可讀性。


第1章 準備工作
第2章 Python語法基礎(chǔ)掀抹,IPython和Jupyter Notebooks
第3章 Python的數(shù)據(jù)結(jié)構(gòu)虐拓、函數(shù)和文件
第4章 NumPy基礎(chǔ):數(shù)組和矢量計算
第5章 pandas入門
第6章 數(shù)據(jù)加載、存儲與文件格式
第7章 數(shù)據(jù)清洗和準備
第8章 數(shù)據(jù)規(guī)整:聚合傲武、合并和重塑
第9章 繪圖和可視化
第10章 數(shù)據(jù)聚合與分組運算
第11章 時間序列
第12章 pandas高級應(yīng)用
第13章 Python建模庫介紹
第14章 數(shù)據(jù)分析案例
附錄A NumPy高級應(yīng)用
附錄B 更多關(guān)于IPython的內(nèi)容(完)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蓉驹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子揪利,更是在濱河造成了極大的恐慌态兴,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疟位,死亡現(xiàn)場離奇詭異瞻润,居然都是意外死亡,警方通過查閱死者的電腦和手機甜刻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門绍撞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人得院,你說我怎么就攤上這事傻铣。” “怎么了祥绞?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵非洲,是天一觀的道長。 經(jīng)常有香客問我蜕径,道長两踏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任丧荐,我火速辦了婚禮缆瓣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虹统。我一直安慰自己弓坞,他們只是感情好隧甚,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著渡冻,像睡著了一般戚扳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上族吻,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天帽借,我揣著相機與錄音,去河邊找鬼超歌。 笑死砍艾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的巍举。 我是一名探鬼主播脆荷,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼懊悯!你這毒婦竟也來了蜓谋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤炭分,失蹤者是張志新(化名)和其女友劉穎桃焕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捧毛,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡观堂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了岖妄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片型将。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荐虐,靈堂內(nèi)的尸體忽然破棺而出七兜,到底是詐尸還是另有隱情,我是刑警寧澤福扬,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布腕铸,位于F島的核電站,受9級特大地震影響铛碑,放射性物質(zhì)發(fā)生泄漏狠裹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一汽烦、第九天 我趴在偏房一處隱蔽的房頂上張望涛菠。 院中可真熱鬧,春花似錦、人聲如沸俗冻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迄薄。三九已至琅关,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讥蔽,已是汗流浹背涣易。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留冶伞,地道東北人新症。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像碰缔,于是被迫代替她去往敵國和親账劲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345