python基礎學習文檔

python基礎學習文檔

—————–張源凱

Python簡介

Python簡介

Python是一門功能強大的編程語言。它具有高效的高級數據結構和簡單而有效的面向對象編程方法。Python優雅的語法和動態類型以及其解釋性的性質,成為編寫腳本和快速應用程序開發的理想語言。

Python優點

簡單易學

移植性好

支持面向過程的函數編程也支持面向對象的抽象編程

可拓展性和可嵌入性好

豐富的庫

代碼規范性高

Python的安裝

Python安裝

在官網上下載對應的python安裝程序,然後運行下載的安裝包:

註意勾選上Add Python 3.5 to PATH,然後點Install Now即可完成安裝

打開命令行窗口,輸入python回車,出現以下為成功:

python解釋器

當運行Python代碼時,得到的是一個包含Python代碼的以.py為擴展名的文本文件。要運行代碼就需要Python解釋器去執行.py文件。

整個python語言從規范到解釋器都是開源的,所以存在多種python解釋器。

  • CPython
  • IPython
  • PyPy
  • Jython
  • IronPython

Python基礎

Python語法采用縮進的方式

# 相關註釋

a=100

if a >= 0:

print(a)

else:

print(-a)

以#開頭的語句是註釋

以冒號:結尾時,縮進的語句視為代碼塊

Python程序對於大小寫敏感

應該堅持使用4個空格縮進

數據類型和變量

整數

Python可以處理任意大小的整數,包括負整數。

浮點數

浮點數就是小數。

字符串

字符串是以單引號’或雙引號”括起來的任意文本。

如果字符串內既包含’又包含”,可以用轉義字符來標識。

n表示換行

t表示制表符

\表示

Python允許用r’’表示’’內部的字符串默認不轉義

Python允許用’’’…’’’的格式表示多行內容

佈爾值

佈爾值和佈爾代數的表示完全一致,一個佈爾值隻有True,False兩種值,要麼是True,要麼是False。

佈爾值可以用and,or和not運算

  1. and運算是與運算,隻有所有都為true,and運算結果才是True。
  2. or運算是或運算,隻要其中有一個為true,or運算結果就是true。
  3. not是非運算,它是一個單目運算符。

空值

空值是Python裡一個特殊的值,用None表示。None不能理解為0,因為0是有意義的,而None是一個特殊的空值。

變量

變量在程序中就是用一個變量名表示,變量名必須是大小寫英文,數字和_組合,且不能用數字開頭。

在Python中,等號=是賦值語句。

這種變量本身類型不固定的語言稱之為動態語言,與之對應的是靜態語言。

靜態語言在定義變量時必須指定變量類型,如果賦值類型不匹配就會報錯。

當輸入a=’ABC’時,Python解釋器幹瞭兩件事:

  • 在內存中創建一個’ABC’字符串;
  • 在內存中創建一個名為a的變量,並把它指向’ABC’;

常量

所謂常量就是不能變的變量,在python中通常用全部大寫的變量名表示常量。

在python中有兩種除法,/和//。

  • /:要做精確的除法
  • //:地板除,結果永遠是整數

字符串和編碼

編碼

為瞭解決亂碼問題,Unicode把所有語言都統一到一套編碼裡。

ASCII編碼是一個字節,而Unicode編碼通常是兩個字節。

UTF-8編碼把一個Unicode字符根據不同的數字大小編碼成1-6個字節,常用的英文字母被編碼成1字節,漢字通常是3個字節,隻有很生僻的字符才會被編碼成4-6個字節。如果你要傳輸的文本包含大量英文字符,用UTF-8編碼就能節省空間。

字符串

在最新的Python3版本中,字符串是以Unicode編碼的,也就是說,Python的字符串支持多語言,例如:

>>>print(‘包含中文的str’)

包含中文的str

對於單個字符的編碼,python提供瞭ord()函數獲取字符的整數表示,chr()函數把編碼轉換為對應的字符:

>>>ord(‘A’)

65

>>>chr(‘66’)

‘B’

Python對bytes類型的數據用帶b前綴的單引號或雙引號表示:

X=b’ABC’

區分’ABC’和b’ABC’,前者是str,後者雖然顯示得和前者一樣,但bytes的每個字符都隻占用一個字節。

以Unicode表示的str通過encode()方法可以編碼為指定的bytes。

反過來,如果我們從網絡或磁盤上讀取字節流,那麼讀到的數據就是bytes。

要把bytes變為str,就需要用decode()方法:

b’ABC’.decode(‘ascii’)

‘ABC’

B’xe4xb8xadxe6x96x87’.decode(‘utf-8’)

‘中文‘

要計算str包含多少個字符,用len()函數:

len(‘ABC’)

3

同樣的,如果換成bytes,len()函數就計算字節數:

len(b'ABC')

3

由於Python源代碼也是一個文本文件,所以,當你的源代碼中包含中文的時候,在保存源代碼時要指定保存為utf-8編碼。

#!/usr/bin/env python3

# _*_ coding:utf-8 _*_

第一行註釋是為瞭告訴Linux/OS X系統,這是一個python可執行程序。

第二行註釋是為瞭告訴python解釋器,按照UTF-8編碼讀取源代碼,否則可能出現亂碼。

格式化

在python中,采用的格式化方式和C語言是一致的,用%實現

'Hello, %s' % 'world'

'Hello, world'

'Hi, %s, you have $%d.' % ('Michael', 1000000)

'Hi, Michael, you have $1000000.'

%運算符就是用來格式化字符串的。%s表示用字符串替換,%d表示用整數替換,有幾個%?占位符,後面就跟幾個變量或者值,順序相互對應。

  • %d整數
  • %f浮點數
  • %s字符串
  • %x十六進制整數

有些時候,字符串裡面的%是一個普通字符的話用%%來表示一個%。

list和tuple

list

python內置有一種數據類型是列表:list。list一種有序的集合,可以隨時添加和刪除其中的元素。

列出班裡同學的名字,可以用一個list表示:

變量classmates就是一個list。用len()函數可以獲得list元素的個數:

用索引訪問list中每一個位置的元素:

還可以用-1做索引,直接獲取最後一個元素,依次類推可以獲取倒數第2第3。

追加元素:

classmates.append(‘kk’)

插入元素:

classmates.insert(1,’jack’)

刪除末尾的元素:

classmates.pop()

要刪除指定位置的元素,用pop(i)方法:

classmates.pop(1)

另外:

  1. 要把某個元素替換成別的元素,可以直接賦值給對應的索引位置。
  2. list裡面的元素的數據類型可以互不相同。
  3. list元素也可以是另外一個list。
  4. 如果一個list中一個元素也沒有,就是一個空的list,長度為0。

tuple

另一種有序列表叫元組:tuple。Tuple一旦初始化就不能修改。

classmates=(‘Michael’,’Bob’,’Tracy’)

沒有append(),insert()這樣的方法。其他獲取元素的方法和list一樣。

因為tuple不可變,所以代碼更安全。

註意:隻有1個元素的tuple定義時必須加一個逗號,,來消除歧義:

t = (1, )

t

(1, )

list和tuple是python內置的有序集合,一個可變,一個不可變。

條件判斷

條件判斷

在python程序中,用if語句實現。根據python的縮進規則,如果if語句判斷是True,就把縮進的兩行print語句執行瞭。也可以給if添加一個else語句,如果if判斷是False,不要執行if的內容,去執行else。

可以用elif做更細致的判斷:

age = 3

if age >= 18:

print('adult')

elif age >= 6:

print('teenager')

else:

print('kid')

input

input()可以用來讀取用戶的輸入。

循環

Python的循環有兩種,一種是for…in循環,依次把list和tuple中的每個元素迭代出來。

names= [‘Michael’,’Bob’,’Trace’]

for name in names:

print(name)

執行這段代碼,會依次打印names的每一個元素。

Python還提供瞭一個range()函數,可以生成一個整數序列,再通過list()函數可以轉換為list。

list(range(5))

[0,1,2,3,4]

另一種循環是while循環,隻要條件滿足,就不斷循環,條件不滿足時退出循環。

dict和set

dict

Python內置瞭字典:dict的支持,在其他語言中也稱為map,使用鍵值存儲,具有極快的查詢速度。

一個key隻能對應一個value,多次對一個key放入value,後面的值會把前面的值沖掉。

如果key不存在,dict就會報錯,可以通過in判斷key是否存著。

或者通過dict提供的get方法,如果不存在返回none。

要刪除一個key,用pop(key)方法,對應的value也會從dict中刪除:

d.pop(‘Bob’)

75

d

{‘Michael’:95,’Trace’:85}

與list比較,dict有以下幾個特點:

  • 查找和插入的速度極快,不會隨著key的增加而增加
  • 占用空間小,浪費內存少

set

set和dict類似,也是一組key的集合,但不存儲value。由於key不能重復,所以,在set中,沒有重復的key。

要創建一個set,需要提供一個list作為輸入集合。

註意:顯示的{1,2,3}隻是告訴你這個set內部有1,2,3這3個元素,顯示的順序也不表示set是有序的。

重復的元素在set中自動被過濾,通過add(key)方法可以添加元素到set中,可以重復添加,但不會有效果。

通過remove(key)方法可以刪除元素。

set和dict的唯一區別僅在於沒有存儲對應的value,但是set的原理和dict一樣,同樣不可以放入可變對象。

函數

調用函數

調用函數

Python內置瞭很多有用的函數,我們可以直接調用,要調用一個函數,需要知道函數的名稱和參數。

可以在交互式命令行通過help(abs)查看abs函數的幫助命令。

abs():求絕對值的函數

max():可以接收任意多個參數,並返回最大的那個

數據類型轉換

Python內置的常用函數還包括數據類型轉換函數,比如int()函數可以把其他數據類型轉換為整數。

定義函數

在python中定義一個函數要使用def語句,依次寫出函數名,括號,括號中的參數和冒號:,然後,在縮進塊中編寫函數體,函數的返回值用return語句返回。

空函數

如果想定義一個什麼事也不做的空函數,可以用pass語句:

缺少瞭pass,代碼運行就會有語法錯誤。

參數檢查

調用函數時,如果參數個數不對,python解釋器會自動檢查出來,並拋出TypeError。

但是如果參數類型不對,Python解釋器就無法幫我們檢查。

數據類型檢查可以用內置函數isinstance()實現:

返回多個值

函數可以同時返回多個值,但其實就是一個tuple。

函數的參數

位置參數

函數有兩個參數:x和n,這兩個參數都是位置參數,調用函數時,傳入的兩個值按照位置順序依次賦給參數x和n。

默認參數

默認參數必須指向不變對象。

可變參數

*nums 表示把 nums 這個list的所有元素作為可變參數傳進去。

關鍵字參數

可變參數允許你傳入0個或任意個參數,這些可變參數在函數調用時自動組裝為一個tuple。而關鍵字參數允許你傳入0個或任意個含參數名的參數,這些關鍵字參數在函數內部自動組裝為一個dict。

函數person除瞭必選參數name和age外,還接收關鍵字參數kw。在調用該函數時,可以隻傳入必選參數。

命名關鍵字參數

如果要限制關鍵字參數的名字,就可以用命名關鍵字參數,例如隻接收city和job作為關鍵字參數。這種方式定義的函數如下:

和關鍵字參數*kw不同,命名關鍵字參數需要一個特殊分隔符 ,*後面的參數被視為命名關鍵字參數。

在python中,這5種參數都可以組合使用,除瞭可變參數無法和命名關鍵字參數混合。參數定義的順序必須是:必選參數,默認參數,可變參數/命名關鍵字參數和關鍵字參數。

  • *args是可變參數,args接收的是一個tuple
  • **kw是關鍵字參數,kw接收的是一個dict

遞歸函數

在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。

計算階乘n!=1*2*3*…*n,用函數fact(n)表示:

fact(n) = n! = 1 x 2 x 3 x … x (n-1) x n = (n-1)! x n = fact(n-1) x n

所以,fact(n)可以表示為n*fact(n-1),隻有n=1時需要特殊處理。

fact(n)用遞歸的方式寫出來就是:

遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。

使用遞歸函數需要註意防止棧溢出。在計算機中,函數調用是通過棧這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。

解決遞歸調用棧溢出的方法是通過尾遞歸優化,事實上尾遞歸和循環的效果是一樣的,所以,把循環看成是一種特殊的尾遞歸函數也是可以的。

高級特性

切片

取一個list或tuple的部分元素是非常常見的操作。

L[0:3]表示,從索引0開始取,直到索引3為止,但不包括索引3。即索引0,1,2,正好是3個元素。

迭代

如果給定一個list或tuple,我們可以通過for循環來遍歷這個list或tuple,這種遍歷我們稱為迭代。

在python中,迭代是通過for…in來完成的。

默認情況下,dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同時迭代key和value,可以用for k,v in d.items()。

任何可迭代對象都可以作用於for循環,包括我們自定義的數據類型,隻要符合迭代條件,就可以使用for循環。

列表生成式

列表生成式可以用一行語句代替循環生成list:

[x*x for x in range(1,11)]

[1,4,9,16,25,36,49,64,81,100]

寫列表生成式時,把要生成的元素x*x放在前面,後面跟for循環,就可以把list創建出來。

還可以使用兩層循環,可以生成全排列:

m+n for m in ‘ABC’ for n in ‘xyz’]

['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

生成器

要創建一個生成器generator,有很多種方法。第一種方法很簡單,隻要把一個列表生成式的[]改成(),就創建瞭一個generator:

創建L和g的區別僅在於最外層的[]和(),L是一個list,而g是一個generator。

如果要一個一個打印出來,可以通過next()函數獲得generator的下一個返回值。

迭代器

凡是可作用於for循環的對象都是Iterable類型;

凡是可作用於next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列;

集合數據類型如list,dict,str等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象。

Python的for循環本質上就是通過不斷調用next()函數實現的。

函數式編程

高階函數

  • 變量可以指向函數
  • 函數名也是變量
  • 傳入函數

map/reduce

map()函數接收兩個參數,一個是函數,一個是Iterable,map將傳入的函數依次作用到序列的每個元素,並把結果 作為新的Iterator返回。

map()傳入的第一個參數是f,即函數對象本身。由於結果r是一個Iterator,Iterator是惰性序列,因此通過list()函數讓它把整個序列都計算出來並返回一個list。

reduce把一個函數作用在一個序列[x1,x2,x3,…]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:

reduce(f,[x1,x2,x3,x4])=f(f(f(x1,x2),x3),x4)

把序列[1,3,5,7,9]變換成整數13579,reduce就可以派上用場:

filter

python內建的filter()函數用於過濾序列。

和map()類似,filter()也接收一個函數和一個序列。和map()不同的是,filter()把傳入的函數依次作用於每個函數,然後根據返回值是true還是false決定保留還是丟棄元素。

例:在一個list中,刪掉偶數,隻保留奇數,可以這麼寫:

def is_odd(n):

return n%2 ==1

list(filter(is_odd,[1,2,4,5,6,9,10,15]))

filter()的作用是從一個序列中篩選出符合條件的元素。由於filter()使用瞭惰性計算,所以隻有在取filter()結果的時候,才會真正篩選並返回下一個曬出的元素。

sorted

排序是程序中經常用到的算法。

Python內置的sorted()函數就可以對list進行排序:

sorted([36,5,-12,9,-21])

[-21,-12,5,9,36]

返回函數

一個函數可以返回一個計算結果,也可以返回一個函數。

返回一個函數時,牢記該函數並未執行,返回函數中不要引用任何可能會變化的變量。

匿名函數

當傳入函數時,有些時候不需要顯示的定義函數,直接傳入匿名函數更方便。

以map函數為例,除瞭定義一個f(x)的函數外,還可以直接傳入匿名函數:

通過對比可以看出,匿名函數lambda x: x*x實際上就是:

def f(x)

return x*x

關鍵字lambda表示匿名函數,冒號前面的x表示函數參數。

匿名函數有個限制,就是隻能有一個表達式,不用寫return,返回值就是該表達式的結果。

用匿名函數的好處是不用擔心函數名起沖突。

裝飾器

假設我們要增強函數的功能,又不希望修改函數的定義,這種在代碼允許期間動態增加功能的方式,稱之為”裝飾物”(Decorator)。

例:

上面的log,因為它是一個decorator,所以接受一個函數作為參數,並返回一個函數。我們要借助Python的@語法,將decorator置於函數的定義處。

偏函數

functools.partial就是幫助我們創建一個偏函數的,不需要我們自己定義int2(),可以直接使用下面的代碼創建一個新的函數int2:

def int2(x,base=2):

return int(x,base)

functools.partial的作用就是,把一個函數的某些參數給固定住,返回一個新的函數,調用這個新函數會更簡單。

模塊

使用模塊

以內建的sys模塊為例,編寫一個hello模塊:

#! /usr/bin/env python3

# -*- coding: utf-8 -*-

‘a test module’

_author_=’Michael Liao’

import sys

def test():

args=sys.argv

if len(args)==1:

print(‘Hello,world!’)

elif len(args)==2:

print(‘Hello,%s!’ % args[1])

else:

print(‘Too many arguments!’)

if_name_==’_main_’:

test()

第1行註釋可以讓這個hello.py文件直接在Unix/Linux/Mac上運行

第2行註釋表示.py文件本身使用標準的UTF-8編碼

第4行是一個字符串,表示模塊的文檔註釋,任何模塊的第一個字符串都被視為模塊的文檔註釋

第6行是authhor變量把作者寫進去

後面開始是真正的代碼部分。

使用sys模塊的第一步,就是導入該模塊:

import sys

sys模塊有一個argv變量,用list存儲瞭命令行的所有參數。Argv至少有一個元素,因為第一個參數永遠是該.py文件的名稱。

if __name__=='__main__':

test()

最後這兩行代碼用於運行測試。

作用域

正常的函數和變量名是公開的,可以直接被引用。

類似_xxx和xxx這樣的函數是非公開的,不應該被直接使用,比如_abc等。

面向對象編程

類和實例

類和實例

類是抽象的模板,而實例是根據類創建出來的一個個具體的對象,每個對象有擁有相同的方法,但各自的數據可能不同。

在python中,定義類是通過class關鍵字:

class後面緊接著是類名,即Student,類名通常是大寫開頭的單詞,緊接著是(object),表示該類是從哪個類繼承下來的。

創建實例是通過類名+()實現的:

bart = Student()

可以自由地給一個實例變量綁定屬性,比如給實例bart綁定一個name屬性:

bart.name=’Bart Simpson’

通過定義一個特殊地init方法,在創建實例的時候,就把name,score綁定上去:

class Student(object):

def _init_(self,name,score):

self.name=name

self.score=score

init方法的第一個參數永遠是self,表示創建的實例本身,因此,在init方法內部,就可以把各種屬性綁定到self,因為self就指向創建的實例本身。

有瞭init方法,在創建實例的時候,就不能傳入空的參數瞭,必須傳入與init方法匹配的參數,但self不需要傳,因為self就指向創建的實例本身。

數據封裝

Student實例本身就擁有這些數據,要訪問這些數據,就沒有必要從外面的函數去訪問,可以直接在Student類的內部定義訪問數據的函數,這樣就把數據封裝起來瞭。

要調用一個方法,隻需要在實例變量上直接調用。

bart.print_score()

訪問限制

如果要讓內部屬性不被外部訪問,可以把屬性的名稱前加上兩個下劃線__,在python中,實例的變量名如果以__開頭,就變成瞭一個私有變量,隻有內部可以訪問,外部不能訪問。

改完後,已經無法從外部訪問實例變量.name和實例變量.score瞭。

如果外部要獲取name和score,可以給student類增加get_name和get_score:

如果外部代碼要修改score,可以給Student類增加set_score方法:

繼承和多態

當我們定義一個class的時候,可以從某個現有的class繼承,新的class稱為子類,而被繼承的class稱為基類,父類或超類。

例:編寫一個名為Animal的class,有一個run方法可以直接打印:

class Animal(object):

def run(self):

print(‘Animal is running…’)

當我們需要編寫Dog和Cat時,就可以直接從Animal類繼承:

class Dog(Animal):

pass

class Cat(Animal):

pass

子類也可以在其中增加一些方法。

當子類和父類都存在相同的run()方法時,子類的run會覆蓋父類的run(),代碼運行的時候,總是會調用子類的run()。這樣我們就獲得瞭繼承的另一個好處:多態。

獲取對象信息

使用type()

我們來判斷對象的類型可以使用type()函數。

基本類型都可以用type()判斷

如果一個變量指向函數或者類,也可以用type()判斷

使用isinstance()

對於class繼承關系來說,使用type()就很不方便。我們要判斷class類型,可以使用isinstance()函數。

如果繼承關系時:

object ->Animal ->Dog->Husky

先創建3種類型的對象:

a=Animal()

d=Dog()

h=Husty()

然後判斷:

isinstance(h,Husky)

True

再判斷:

isinstance(h,Dog)

True

h雖然自身是Husky類型,但由於Husky是從Dog繼承下來的,所以,h也還是Dog類型。

實例屬性和類屬性

給實例綁定屬性的方法是通過實例變量,或者通過self變量:

也可以直接在class中定義屬性,這種屬性是類屬性,歸Student類所有:

面向對象高級編程

使用slots

如果我們要限制實例的屬性,隻允許對student實例添加name和age屬性,為瞭達到限制的目的,允許在定義class的時候,定義一個特殊的slots變量,來限制該class實例能添加的屬性:

Class Student(object):

__slots__=(‘name’,’age’)

如果此時綁定score屬性,那麼就會報錯。

使用slots要註意,slots定義的屬性僅對當前類實例起作用,對繼承的子類是不起作用的。

使用@property

把一個getter方法變成屬性,隻需要加上@property就可以瞭。

多重繼承

多重繼承

在給動物加上Runnable和Flyable的功能,隻需要先定義好Runnable和Flyable類:

class Runnable(object):

def run(self):

print(‘Running…’)

class Flyable(object):

def fly(self):

print(‘Flying…’)

對於需要Runnable功能的動物,就多繼承一個Runnable,例如Dog:

class Dog(Mammal,Runnable):

pass

定制類

str

返回可讓用戶看到的字符串。

iter

如果一個類想被用於for…in循環,類似list或tuple那樣,就必須實現一個iter()方法,該方法返回一個迭代對象,然後python的for循環就會不斷調用該迭代對象的next方法拿到循環的下一個值,直到遇到stopIteration錯誤時退出循環。

getattr

當我們調用類的方法或屬性時,如果不存在,就會報錯。要避免這個錯誤,除瞭可以加上一個score屬性外,那就是寫一個getattr()方法,動態返回一個屬性。

call

一個對象實例可以有自己的屬性和方法,當我們調用實例方法時,我們用instance.method()來調用。在python中,任何類,也可以隻需要定義一個call()方法,就可以直接對實例進行調用。

def __call__(self):

print(‘My name is %s.’ % self.name)

使用枚舉類

Python提供瞭枚舉類型Enum類來實現這個功能:

From enum import Enum

Month=Enum(‘Month’,(‘Jan’,’Feb’,’Mar’,’Apr’,’May’,’Jun’,’Jul’,’Aug’,’Sep’,’Oct’,’Nov’,’Dec’))

這樣我們就獲得瞭Month類型的枚舉類,可以直接使用Month.Jan來引用一個常量,或者枚舉它的所有成員:

for name,member in Month.__members__.items():

print(name, ’=>’ , member, ‘,’ ,member.value)

value屬性則是自動賦給成員的int常量,默認從1開始計數。

如果需要更精確地控制枚舉類型,可以從Enum派生出自定義類:

from enum import Enum,unique

@unique

Class Weekday(Enum):

Sun=0

Mon=1

Tue=2

Wed=3

Thu=4

Fri=5

Sat=6

@unique裝飾物可以幫助我們檢查保證沒有重復值。

Tips:本文由作者親自學習整理,若有問題歡迎互相學習交流。

赞(0)