零基礎入門Python:基本命令、函數、數據結構

導讀:本文對Python的基本使用做一個簡單的介紹。限於篇幅,本文不可能詳細講解Python的使用,只是針對本書涉及的數據挖掘案例所用到的代碼進行基本講解。如果讀者是初步接觸Python,並且使用Python的目的就是數據挖掘,那麼相信本文的介紹對你來說是比較充足的了。

作者:張良均 譚立雲 劉名軍 江建明

零基礎入門Python:基本命令、函數、數據結構

01 運行方式

本文示例代碼使用的Python版本為Python 3.6。運行Python代碼有兩種方式:

  • 一種方式是啟動Python,然後在命令窗口下直接輸入相應的命令;
  • 另一種方式就是將完整的代碼寫成.py腳本,如hello.py,然後在對應的路徑下通過python hello.py執行。

hello.py腳本中的代碼如下:

<code># hello.py
print('Hello World!')/<code>

腳本的執行結果如圖所示。

零基礎入門Python:基本命令、函數、數據結構

▲Hello.py腳本執行結果

在編寫腳本的時候,可以添加適當的註釋。在每一行中,可以用井號“#”來添加註釋,添加單行註釋的方法如下:

<code>a = 2 + 3 # 這句命令的意思是將2+3的結果賦值給a/<code>

如果註釋有多行,可以在兩個“'''”(三個英文狀態單引號)之間添加註釋內容,添加多行註釋的方法如下:

<code>a = 2 + 3
'''
這裡是Python的多行註釋。
這裡是Python的多行註釋。
'''/<code>

如果腳本中帶有中文(中文註釋或者中文字符串,中文字符串要在前面加u),那麼需要在文件頭註明編碼,並且還要將腳本保存為utf-8編碼格式,註明編碼的方法如下:

02 基本命令

1. 基本運算

初步認識Python時,可以把它當作一個方便的計算器來看待。讀者可以打開Python,試著輸入代碼清單1所示的命令。

  • 代碼清單1:Python基本運算
<code>a = 2
a * 2
a ** 2/<code>

代碼清單1所示的命令是Python幾個基本運算,第一個命令是賦值運算,第二個命令是乘法運算,最後一個命令是冪運算(即a2),這些基本上是所有編程語言通用的。不過Python支持多重賦值,方法如下:

<code>a, b, c = 2, 3, 4/<code>

這句多重賦值命令相當於如下命令:

<code>a = 2
b = 3
c = 4/<code>

Python支持對字符串的靈活操作,如代碼清單2所示。

  • 代碼清單2:Python字符串操作
<code>s = 'I like python'
s + ' very much'  # 將s與' very much'拼接,得到'I like python very much'
s.split(' ') # 將s以空格分割,得到列表['I', 'like', 'python']/<code>

2. 判斷與循環

判斷和循環是所有編程語言的基本命令,Python的判斷語句格式如下:

<code>if 條件1:
    語句2
elif 條件3:
    語句4
else:
    語句5/<code>

需要特別指出的是,Python一般不用花括號{},也沒有end語句,它用縮進對齊作為語句的層次標記。同一層次的縮進量要一一對應,否則會報錯。下面是一個錯誤的縮進示例,如代碼清單3所示。

  • 代碼清單3:錯誤的縮進
<code>if a==1:
    print(a)# 縮進兩個空格
else:
        print('a不等於1')# 縮進三個空格/<code>

不管是哪種語言,正確的縮進都是一個優雅的編程習慣。

相應地,Python的循環有while循環和for循環,while循環如代碼清單4所示。

  • 代碼清單4:while循環
<code>s,k = 0,0
while k     k = k + 1
    s = s + k
print(s)/<code>

for循環如代碼清單5所示。

  • 代碼清單5:for循環
<code>s = 0
for k in range(101): # 該循環過程也是求1+2+3+...+100
    s = s + k
print(s)/<code>

這裡我們看到了in和range語法。in是一個非常方便而且非常直觀的語法,用來判斷一個元素是否在列表/元組中;range用來生成連續的序列,一般語法為range(a, b, c),表示以a為首項、c為公差且不超過b-1的等差數列,如代碼清單6所示。

  • 代碼清單6:使用range生成等差數列
<code>s = 0
if s in range(4):
    print('s在0, 1, 2, 3中')
if s not in range(1, 4, 1):
    print('s不在1, 2, 3中')/<code>

3. 函數

Python用def來自定義函數,如代碼清單7所示。

  • 代碼清單7:自定義函數
<code>def add2(x):
    return x+2
print(add2(1)) # 輸出結果為3/<code>

與一般編程語言不同的是,Python的函數返回值可以是各種形式,可以返回列表,甚至返回多個值,如代碼清單8所示。

  • 代碼清單8:返回列表和返回多個值的自定義函數
<code>def add2(x = 0, y = 0):  # 定義函數,同時定義參數的默認值
    return [x+2, y+2]  # 返回值是一個列表
def add3(x, y):
    return x+3, y+3  # 雙重返回
a, b = add3(1,2) # 此時a=4,b=5/<code>

有時候,像定義add2()這類簡單的函數,用def來正式地寫個命名、計算和返回顯得稍有點麻煩,Python支持用lambda對簡單的功能定義“行內函數”,這有點像MATLAB中的“匿名函數”,如代碼清單9所示。

  • 代碼清單9:使用lambda定義函數
<code>f = lambda x : x + 2  # 定義函數f(x)=x+2
g = lambda x, y: x + y # 定義函數g(x,y)=x+y/<code>

03 數據結構

Python有4個內建的數據結構—List(列表)、Tuple(元組)、Dictionary(字典)以及Set(集合),它們可以統稱為容器(Container),因為它們實際上是一些“東西”組合而成的結構,而這些“東西”可以是數字、字符、列表或者是它們之間幾種的組合。

通俗來說,容器裡邊是什麼都行,而且容器裡邊的元素類型不要求相同。

1. 列表/元組

列表和元組都是序列結構,它們本身很相似,但又有一些不同的地方。

從外形上看,列表與元組存在一些區別是。列表是用方括號標記的,如a = [1, 2, 3],而元組是用圓括號標記的,如b = (4, 5, 6),訪問列表和元組中的元素的方式都是一樣的,如a[0]等於1,b[2]等於6,等等。剛剛已經談到,容器裡邊是什麼都行,因此,以下定義也是成立的:

<code>c = [1, 'abc', [1, 2]]
'''
c是一個列表,列表的第一個元素是整型1,第二個是字符串'abc',第三個是列表[1, 2]
'''/<code>

從功能上看,列表與元組的區別在於:列表可以被修改,而元組不可以。比如,對於a = [1, 2, 3],那麼語句a[0] = 0,就會將列表a修改為[0, 2, 3],而對於元組b = (4, 5, 6),語句b[0] = 1就會報錯。

要注意的是,如果已經有了一個列表a,同時想複製a,並命名為變量b,那麼b = a是無效的,這時候b僅僅是a的別名(或者說引用),修改b也會修改a。正確的複製方法應該是b = a[:]。

跟列表有關的函數是list,跟元組有關的函數是tuple,它們的用法和功能幾乎一樣,都是將某個對象轉換為列表/元組,如list('ab')的結果是['a', 'b'],tuple([1, 2])的結果是(1, 2)。一些常見的與列表/元組相關的函數如下所示。

  • cmp(a, b):比較兩個列表/元組的元素
  • len(a):列表/元組元素個數
  • max(a):
    返回列表/元組元素最大值
  • min(a):返回列表/元組元素最小值
  • sum(a):將列表/元組中的元素求和
  • sorted(a):對列表的元素進行升序排序

此外,作為對象來說,列表本身自帶了很多實用的方法(元組不允許修改,因此方法很少),如下所示。

  • a.append(1):將1添加到列表a末尾
  • a.count(1):統計列表a中元素1出現的次數
  • a.extend([1, 2]):將列表[1, 2]的內容追加到列表a的末尾
  • a.index(1):從列表a中找出第一個1的索引位置
  • a.insert(2, 1):
    將1插入列表a中索引為2的位置
  • a.pop(1):移除列表a中索引為1的元素

最後,不能不提的是“列表解析”這一功能,它能夠簡化我們對列表內元素逐一進行操作的代碼。使用append函數對列表元素進行操作,如代碼清單10所示。

  • 代碼清單10:使用append函數對列表元素進行操作
<code>a = [1, 2, 3]
b = []
for i in a:
    b.append(i + 2)/<code>

使用列表解析進行簡化,如代碼清單11所示。

  • 代碼清單11:使用列表解析進行簡化
<code>a = [1, 2, 3]
b = [i+2 for i in a]/<code>

這樣的語法不僅方便,而且直觀。這充分體現了Python語法的人性化。在本書中,我們將會較多地用到這樣簡潔的代碼。

2. 字典

Python引入了“自編”這一方便的概念。從數學上來講,它實際上是一個映射。通俗來講,它也相當於一個列表,然而它的“下標”不再是以0開頭的數字,而是自己定義的“鍵”(Key)。

創建一個字典的基本方法如下:

<code>d = {'today':20, 'tomorrow':30}/<code>

這裡的today、tomorrow就是字典的“鍵”,它在整個字典中必須是唯一的,而20、30就是“鍵”對應的值。訪問字典中元素的方法也很直觀,如代碼清單12所示。

  • 代碼清單12:訪問字典中的元素
<code>d['today']    # 該值為20
d['tomorrow'] # 該值為30/<code>

要創建一個字典,還有其他一些比較方便的方法來,如通過dict()函數轉換,或者通過dict.fromkeys來創建,如代碼清單13所示。

  • 代碼清單13:通過dict或者dict.fromkeys創建字典
<code>dict([['today', 20], ['tomorrow', 30]])  # 也相當於{'today':20, 'tomorrow':30}
dict.fromkeys(['today', 'tomorrow'], 20) # 相當於{'today':20, 'tomorrow':20}/<code>

很多字典相關的函數和方法與列表相同,在這裡就不再贅述了。

3. 集合

Python內置了集合這一數據結構,這一概念跟數學上的集合的概念基本上是一致的,它跟列表的區別在於:①它的元素是不重複的,而且是無序的;②它不支持索引。一般我們通過花括號{}或者set()函數來創建一個集合,如代碼清單14所示。

  • 代碼清單14:創建集合
<code>s = {1, 2, 2, 3}  # 注意2會自動去重,得到{1, 2, 3}
s = set([1, 2, 2, 3]) # 同樣地,它將列表轉換為集合,得到{1, 2, 3}/<code>

集合具有一定的特殊性(特別是無序性),因此集合有一些特別的運算,如代碼清單15所示。

  • 代碼清單15:集合運算
<code>a = t | s  # t和s的並集
b = t & s  # t和s的交集
c = t – s  # 求差集(項在t中,但不在s中)
d = t ^ s  # 對稱差集(項在t或s中,但不會同時出現在二者中)/<code>

4. 函數式編程

函數式編程(Functional programming)或者函數程序設計又稱泛函編程,是一種編程範型,它將計算機運算視為數學上的函數計算,並且避免使用程序狀態以及易變對象。

簡單來講,函數式編程是一種“廣播式”編程,通常是結合前面提到的lambda定義函數用於科學計算中,會顯得簡潔方便。

在Python中,函數式編程主要由幾個函數的使用構成:lambda、map、reduce、filter,其中lambda前面已經介紹過,主要用來自定義“行內函數”,所以現在我們逐一介紹後面3個。

(1)map函數

假設有一個列表a = [1, 2, 3],要給列表中的每個元素都加2得到一個新列表,利用前面已經談及的列表解析,我們可以這樣寫,如代碼清單16所示。

  • 代碼清單16:使用列表解析操作列表元素
<code>b = [i+2 for i in a]/<code>

而利用map函數我們可以這樣寫,如代碼清單17所示。

  • 代碼清單17:使用map函數操作列表元素
<code>b = map(lambda x: x+2, a)
b = list(b)  # 結果是[3, 4, 5]/<code>

也就是說,我們首先要定義一個函數,然後再用map命令將函數逐一應用到(map)列表中的每個元素,最後返回一個數組。map命令也接受多參數的函數,如map(lambda x,y: x*y, a, b)表示將a、b兩個列表的元素對應相乘,把結果返回新列表。

也許有的讀者會有疑問:有了列表解析,為什麼還要有map命令呢?其實列表解析雖然代碼簡短,但是本質上還是for命令,而Python的for命令效率並不高,而map函數實現了相同的功能,並且效率更高,原則上來說,它的循環命令是C語言速度的。

(2)reduce函數

reduce有點像map,但map用於逐一遍歷,而reduce用於遞歸計算。在Python 3.x中,reduce函數已經被移出了全局命名空間,被置於fuctools庫中,使用時需要通過from fuctools import reduce引入reduce。先給出一個例子,這個例子可以算出n的階乘,如代碼清單18所示。

  • 代碼清單18:使用reduce計算n的階乘
<code>from fuctools import reduce# 導入reduce函數
reduce(lambda x,y: x*y, range(1, n+1))/<code>

其中range(1, n+1)相當於給出了一個列表,元素是1~n這n個整數。lambda x,y: x*y構造了一個二元函數,返回兩個參數的乘積。

reduce命令首先將列表的頭兩個元素作為函數的參數進行運算,然後將運算結果與第三個數字作為函數的參數,然後再將運算結果與第四個數字作為函數的參數……依此遞推,直到列表結束,返回最終結果。如果用循環命令,那就要寫成代碼清單19所示的形式。

  • 代碼清單19:使用循環命令計算n的階乘
<code>s = 1 

for i in range(1, n+1):
    s = s * i/<code>

(3)filter

顧名思義,它是一個過濾器,用來篩選列表中符合條件的元素,如代碼清單20所示。

  • 代碼清單20:使用filter篩選列表元素
<code>b = filter(lambda x: x > 5 and x b = list(b)  # 結果是[6, 7]/<code>

使用filter首先需要一個返回值為bool型的函數,如上述“lambda x: x > 5 and x < 8”定義了一個函數,判斷x是否大於5且小於8,然後將這個函數作用到range(10)的每個元素中,如果為True,則“挑出”那個元素,最後將滿足條件的所有元素組成一個列表返回。

當然,上述filter語句,也可以使用列表解析,如代碼清單21所示。

  • 代碼清單21:使用列表解析篩選
<code>b = [i for i in range(10) if i > 5 and i /<code>

它並不比filter語句複雜。但是要注意,我們使用map、reduce或filter,最終目的是兼顧簡潔和效率,因為map、reduce或filter的循環速度比Python內置的for循環或while循環要快得多。

04 庫的導入與添加

前面我們已經講述了Python基本平臺的搭建和使用,然而僅在默認情況下它並不會將所有的功能加載進來。我們需要把更多的庫(或者叫作模塊、包等)加載進來,甚至需要安裝第三方擴展庫,以豐富Python的功能,實現我們的目的。

1. 庫的導入

Python本身內置了很多強大的庫,如數學相關的math庫,可以為我們提供更加豐富且複雜的數學運算,如代碼清單22所示。

  • 代碼清單22:使用math庫進行數學運算
<code>import math
math.sin(1)  # 計算正弦
math.exp(1)  # 計算指數
math.pi  # 內置的圓周率常數/<code>

導入庫的方法,除了直接“import庫名”之外,還可以為庫起一個別名,如代碼清單23所示。

  • 代碼清單23:使用別名導入庫
<code>import math as m
m.sin(1) # 計算正弦/<code>

此外,如果並不需要導入庫中的所有函數,可以特別指定導入函數的名稱,如代碼清單24所示。

  • 代碼清單24:通過名稱導入指定函數
<code>from math import exp as e # 只導入math庫中的exp函數,並起別名e
e(1)  # 計算指數
sin(1)  # 此時sin(1)和math.sin(1)都會出錯,因為沒被導入/<code>

若直接導入庫中的所有函數,如代碼清單25所示。

  • 代碼清單25:導入庫中所有函數
<code># 直接導入math庫,也就是去掉math.,但如果大量地這樣引入第三庫,就容易引起命名衝突
from math import *
exp(1)
sin(1)/<code>

我們可以通過help('modules')命令來獲得已經安裝的所有模塊名。

2. 導入future特徵(For 2.x)

Python 2.x與Python 3.x之間的差別不僅是在內核上,也部分地表現在代碼的實現中。比如,在Python 2.x中,print是作為一個語句出現的,用法為print a;但是在Python 3.x中,它是作為函數出現的,用法為print(a)。

為了保證兼容性,本文的基本代碼是基於Python 3.x的語法編寫的,而使用Python 2.x的讀者,可以通過引入future特徵的方式兼容代碼,如代碼清單26所示。

  • 代碼清單26:導入future特徵
<code># 將print變成函數形式,即用print(a)格式輸出
from __future__ import print_function

# 3.x的3/2=1.5,3//2才等於1;2.x中3/2=1
from __future__ import division/<code>

3. 添加第三方庫

Python自帶了很多庫,但不一定可以滿足我們的需求。就數據分析和數據挖掘而言,還需要添加一些第三方庫來拓展它的功能。這裡簡單介紹一下第三方庫的安裝。

安裝第三方庫有多種方法,如下所示。

  • 下載源代碼自行安裝:安裝靈活,但需要自行解決上級依賴問題
  • 用pip命令安裝:比較方便,自動解決上級依賴問題
  • 用easy_install命令安裝:比較方便,自動解決上級依賴問題,比pip稍弱
  • 下載編譯好的文件包:一般是Windows系統才提供現成的可執行文件包
  • 系統自帶的安裝方式:Linux系統或Mac系統的軟件管理器自帶了某些庫的安裝方式

這些安裝方式已在《 》中詳細介紹。

關於作者:張良均,資深大數據挖掘與分析專家、模式識別專家、AI技術專家。有10餘年大數據挖掘與分析經驗,擅長Python、R、Hadoop、Matlab等技術實現的數據挖掘與分析,對機器學習等AI技術驅動的數據分析也有深入研究。

本文摘編自《Python數據分析與挖掘實戰》(第2版),經出版方授權發佈。

零基礎入門Python:基本命令、函數、數據結構

延伸閱讀《Python數據分析與挖掘實戰》

推薦語:暢銷書全新升級,第1版銷售超過10萬冊,被國內100餘所高等院校採用為教材,同時被廣大數據科學工作者奉為經典,是該領域公認的事實標準。作者在大數據挖掘與分析等領域有10餘年的工程實踐、教學和創辦企業的經驗,不僅掌握行業的最新技術和實踐方法,而且洞悉學生和老師的需求與痛點。


分享到:


相關文章: