python3初探

官方網站:https://www.python.org/
類庫大全:https://pypi.python.org/pypi
基礎類庫:https://docs.python.org/3/library/index.html html

簡介

Python(英國發音:/ˈpaɪθən/ 美國發音:/ˈpaɪθɑːn/), 是一種面向對象、解釋型計算機程序設計語言,由Guido van Rossum於1989年發明,第一個公開發行版發行於1991年。python

Python是純粹的自由軟件, 源代碼和解釋器CPython遵循 GPL(GNU General Public License)協議[1] 。linux

Python的哲學是「作一件事情有且只有一種方法」(There should be one– and preferably only one –obvious way to do it.)。shell

Python是徹底面向對象的語言。函數、模塊、數字、字符串都是對象。而且徹底支持繼承、重載、派生、多繼承,有益於加強源代碼的複用性。Python支持重載運算符和動態類型。數據庫

Python具備豐富和強大的庫。它常被暱稱爲膠水語言,可以把用其餘語言製做的各類模塊(尤爲是C/C++)很輕鬆地聯結在一塊兒。常見的一種應用情形是,使用Python快速生成程序的原型(有時甚至是程序的最終界面),而後對其中有特別要求的部分,用更合適的語言改寫,好比3D遊戲中的圖形渲染模塊,性能要求特別高,就能夠用C/C++重寫,然後封裝爲Python能夠調用的擴展類庫。須要注意的是在您使用擴展類庫時可能須要考慮平臺問題,某些可能不提供跨平臺的實現。express

因爲Python語言的簡潔、易讀以及可擴展性,在國外用Python作科學計算的研究機構日益增多,一些知名大學已經採用Python教授程序設計課程。例如卡耐基梅隆大學的編程基礎、麻省理工學院的計算機科學及編程導論就使用Python語言講授。衆多開源的科學計算軟件包都提供了Python的調用接口,例如著名的計算機視覺庫OpenCV、三維可視化庫VTK、醫學圖像處理庫ITK。而Python專用的科學計算擴展庫就更多了,例如以下3個十分經典的科學計算擴展庫:NumPy、SciPy和matplotlib,它們分別爲Python提供了快速數組處理、數值運算以及繪圖功能。所以Python語言及其衆多的擴展庫所構成的開發環境十分適合工程技術、科研人員處理實驗數據、製做圖表,甚至開發科學計算應用程序。編程

Python開發人員儘可能避開不成熟或者不重要的優化。一些針對非重要部位的加快運行速度的補丁一般不會被合併到Python內。因此不少人認爲Python很慢。不過,根據二八定律,大多數程序對速度要求不高。在某些對運行速度要求很高的狀況,Python設計師傾向於使用JIT技術,或者用使用C/C++語言改寫這部分程序。bootstrap

安裝

curl -R -O https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz
tar zxf Python-3.5.1.tgz z表明gzip的壓縮包;x表明解壓;v表明顯示過程信息;f表明後面接的是文件
cd Python-3.5.1
./configure
make
make install數組

設置環境變量
export PATH=」$PATH:/usr/local/bin/python3」 app

安裝完成

leestar@leestar-ThinkPad-SL410:~$ python3
python3
Python 3.5.1 (default, Mar 14 2016, 22:23:55)
[GCC 5.2.1 20151010] on linux
Type 「help」, 「copyright」, 「credits」 or 「license」 for more information.
>>>

python包管理工具pypi
https://pip.pypa.io/en/latest/installing/

curl -R -O https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
pip -V
pip 8.1.0 from /usr/local/lib/python2.7/dist-packages (python 2.7)

解釋器

Linux/Unix的系統上,Python解釋器一般被安裝在 /usr/local/bin/python3.5 這樣的有效路徑(目錄)裏。
咱們能夠將路徑 /usr/local/bin 添加到您的Linux/Unix操做系統的環境變量中,這樣您就能夠經過 shell 終端輸入下面的命令來啓動 Python 。

交互式編程

咱們能夠在命令提示符中輸入」python3」命令來啓動Python解釋器:

leestar@leestar-ThinkPad-SL410:~$ python3
python3
Python 3.5.1 (default, Mar 14 2016, 22:23:55)
[GCC 5.2.1 20151010] on linux
Type 「help」, 「copyright」, 「credits」 or 「license」 for more information.
>>>

當鍵入一個多行結構時,續行是必須的。咱們能夠看下以下 if 語句:

>>> the_world_is_flat = True
>>> if the_world_is_flat:
… print(「Be careful not to fall off!」)

Be careful not to fall off!

腳本式編程

經過如下命令執行該腳本:

python hello.py

在Linux/Unix系統中,你能夠在腳本頂部添加如下命令讓Python腳本能夠像SHELL腳本同樣可直接執行:

#! /usr/bin/python3
而後修改腳本權限,使其有執行權限,命令以下:
$ chmod +x hello.py
執行./hello.py

基礎語法

編碼

默認狀況下,Python 3源碼文件以 UTF-8 編碼,全部字符串都是 unicode 字符串。 固然你也能夠爲源碼文件指定不一樣的編碼:

# -- coding: cp-1252 --

標識符

  • 第一個字符必須是字母表中字母或下劃線’_’。
  • 標識符的其餘的部分有字母、數字和下劃線組成。
  • 標識符對大小寫敏感。

關鍵字

Python的標準庫提供了一個keyword module,能夠輸出當前版本的全部關鍵字:

>>> import keyword
>>> keyword.kwlist [‘False’, ‘None’, ‘True’, ‘and’, ‘as’, ‘assert’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’, ‘except’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘nonlocal’, ‘not’, ‘or’, ‘pass’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’]

註釋

Python中單行註釋以#開頭,多行註釋用三個單引號(」’)或者三個雙引號(」「」)將註釋括起來。

  1. #!/usr/bin/python3
  2. '''
  3. 這是多行註釋,用三個單引號
  4. 這是多行註釋,用三個單引號
  5. 這是多行註釋,用三個單引號
  6. '''
  7. print("Hello, World!")

行與縮進

python最具特點的就是使用縮進來表示代碼塊。縮進的空格數是可變的,可是同一個代碼塊的語句必須包含相同的縮進空格數。

基本數據類型

Python中的變量不須要聲明。每一個變量在使用前都必須賦值,變量賦值之後該變量纔會被建立。
在Python中,變量就是變量,它沒有類型,咱們所說的」類型」是變量所指的內存中對象的類型。
Python 3中有六個標準的數據類型:
Numbers(數字)String(字符串)List(列表)Tuple(元組)Sets(集合)Dictionaries(字典)

Numbers(數字)

Python 3支持int、float、bool、complex(複數)。
數值類型的賦值和計算都是很直觀的,就像大多數語言同樣。內置的type()函數能夠用來查詢變量所指的對象類型。

2 / 4 # 除法,獲得一個浮點數 0.5
2 // 4 # 除法,獲得一個整數 0
2 ** 5 # 乘方 32

一、Python能夠同時爲多個變量賦值,如a, b = 1, 2。
二、一個變量能夠經過賦值指向不一樣類型的對象。
三、數值的除法(/)老是返回一個浮點數,要獲取整數使用//操做符。
四、在混合計算時,Python會把整型轉換成爲浮點數。

String(字符串)

Python中的字符串str用單引號(’ ‘)或雙引號(」 「)括起來,同時使用反斜槓()轉義特殊字符。
若是你不想讓反斜槓發生轉義,能夠在字符串前面添加一個r,表示原始字符串:

>>> print(r’C:\some\name’)
C:\some\name

另外,反斜槓能夠做爲續行符,表示下一行是上一行的延續。還可使用」「」…」「」或者」’…」’跨越多行。
字符串可使用 + 運算符串鏈接在一塊兒,或者用 * 運算符重複:

>>> print(‘str’+’ing’, ‘my’*3)
string mymymy

Python中的字符串有兩種索引方式,第一種是從左往右,從0開始依次增長;第二種是從右往左,從-1開始依次減小。
注意,沒有單獨的字符類型,一個字符就是長度爲1的字符串。

>>> word = ‘Python’
>>> print(word[0], word[5])
P n
>>> print(word[-1], word[-6])
n P

還能夠對字符串進行切片,獲取一段子串。用冒號分隔兩個索引,形式爲變量[頭下標:尾下標]。
截取的範圍是前閉後開的,而且兩個索引均可以省略:

>>> word = ‘ilovepython’
>>> word[1:5]
‘love’
>>> word[:]
‘ilovepython’
>>> word[5:]
‘python’
>>> word[-10:-6]
‘love’

與C字符串不一樣的是,Python字符串不能被改變。向一個索引位置賦值,好比word[0] = ‘m’會致使錯誤。
一、反斜槓能夠用來轉義,使用r可讓反斜槓不發生轉義。
二、字符串能夠用+運算符鏈接在一塊兒,用*運算符重複。
三、Python中的字符串有兩種索引方式,從左往右以0開始,從右往左以-1開始。
四、Python中的字符串不能改變。

List(列表)

列表是寫在方括號之間、用逗號分隔開的元素列表。列表中元素的類型能夠不相同
和字符串同樣,列表一樣能夠被索引和切片,列表被切片後返回一個包含所需元素的新列表。
列表還支持串聯操做,使用+操做符:

>>> a=[1,2,3,4]
>>> a+[5,6,7]
[1, 2, 3, 4, 5, 6, 7]

與Python字符串不同的是,列表中的元素是能夠改變的
一、List寫在方括號之間,元素用逗號隔開。
二、和字符串同樣,list能夠被索引和切片。
三、List可使用+操做符進行拼接。
四、List中的元素是能夠改變的。

Tuple(元組)

元組(tuple)與列表相似,不一樣之處在於元組的元素不能修改。元組寫在小括號裏,元素之間用逗號隔開。
元組中的元素類型也能夠不相同:

>>> a = (1991, 2014, ‘physics’, ‘math’)

元組與字符串相似,能夠被索引且下標索引從0開始,也能夠進行截取/切片。
其實,能夠把字符串看做一種特殊的元組。
雖然tuple的元素不可改變,但它能夠包含可變的對象,好比list列表。
構造包含0個或1個元素的tuple是個特殊的問題,因此有一些額外的語法規則:

  1. tup1 =()# 空元組
  2. tup2 =(20,)# 一個元素,須要在元素後添加逗號

元組也支持用+操做符,string、list和tuple都屬於sequence(序列)。
一、與字符串同樣,元組的元素不能修改。
二、元組也能夠被索引和切片,方法同樣。
三、注意構造包含0或1個元素的元組的特殊語法規則。
四、元組也可使用+操做符進行拼接。

Sets(集合)

集合(set)是一個無序不重複元素的集。
基本功能是進行成員關係測試和消除重複元素。重複的元素被自動去掉
可使用大括號 或者 set()函數建立set集合,注意:建立一個空集合必須用 set() 而不是 { },由於{ }是用來建立一個空字典。

>>> student = {‘Tom’, ‘Jim’, ‘Mary’, ‘Tom’, ‘Jack’, ‘Rose’}
>>> print(student) # 重複的元素被自動去掉
{‘Jim’, ‘Jack’, ‘Mary’, ‘Tom’, ‘Rose’}
>>> ‘Rose’ in student # membership testing(成員測試)
True
>>> # set能夠進行集合運算 …
>>> a = set(‘abracadabra’)
>>> b = set(‘alacazam’)
>>> a {‘a’, ‘b’, ‘c’, ‘d’, ‘r’}
>>> a - b # a和b的差集
{‘b’, ‘d’, ‘r’}
>>> a | b # a和b的並集
{‘l’, ‘m’, ‘a’, ‘b’, ‘c’, ‘d’, ‘z’, ‘r’}
>>> a & b # a和b的交集
{‘a’, ‘c’}
>>> a ^ b # a和b中不一樣時存在的元素
{‘l’, ‘m’, ‘b’, ‘d’, ‘z’, ‘r’}

Dictionaries(字典)

字典(dictionary)是Python中另外一個很是有用的內置數據類型。
字典是一種映射類型(mapping type),它是一個無序的鍵 : 值對集合。
關鍵字必須使用不可變類型,也就是說list和包含可變類型的tuple不能作關鍵字。
在同一個字典中,關鍵字還必須互不相同。

>>> dic = {} # 建立空字典
>>> tel = {‘Jack’:1557, ‘Tom’:1320, ‘Rose’:1886}
>>> tel
{‘Tom’: 1320, ‘Jack’: 1557, ‘Rose’: 1886}
>>> tel[‘Jack’] # 主要的操做:經過key查詢
1557
>>> del tel[‘Rose’] # 刪除一個鍵值對
>>> tel[‘Mary’] = 4127 # 添加一個鍵值對
>>> tel
{‘Tom’: 1320, ‘Jack’: 1557, ‘Mary’: 4127}
>>> list(tel.keys()) # 返回全部key組成的list
[‘Tom’, ‘Jack’, ‘Mary’]
>>> sorted(tel.keys()) # 按key排序
[‘Jack’, ‘Mary’, ‘Tom’]
>>> ‘Tom’ in tel # 成員測試
True
>>> ‘Mary’ not in tel # 成員測試
False

構造函數 dict() 直接從鍵值對sequence中構建字典,固然也能夠進行推導

>>> dict([(‘sape’, 4139), (‘guido’, 4127), (‘jack’, 4098)])
{‘jack’: 4098, ‘sape’: 4139, ‘guido’: 4127}
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
>>> dict(sape=4139, guido=4127, jack=4098)
{‘jack’: 4098, ‘sape’: 4139, ‘guido’: 4127}

一、字典是一種映射類型,它的元素是鍵值對。
二、字典的關鍵字必須爲不可變類型,且不能重複。
三、建立空字典使用{ }。

條件控制

  1. if condition_1:
  2. statement_block_1
  3. elif condition_2:
  4. statement_block_2
  5. else:
  6. statement_block_3

一、每一個條件後面要使用冒號(:),表示接下來是知足條件後要執行的語句塊。
二、使用縮進來劃分語句塊,相同縮進數的語句在一塊兒組成一個語句塊。
三、在Python中沒有switch – case語句。

循環

while 循環

  1. while判斷條件:
  2. statements

一樣須要注意冒號和縮進。另外,在Python中沒有do..while循環。

for語句

Python for循環能夠遍歷任何序列的項目,如一個列表或者一個字符串。

  1. for<variable>in<sequence>:
  2. <statements>
  3. else:
  4. <statements>

break語句用於跳出當前循環體

range()函數

若是你須要遍歷數字序列,可使用內置range()函數。它會生成數列

>>> for i in range(5):
… print(i)

0
1
2
3
4
>>> for i in range(0, 10, 3) :
… print(i)

0
3
6
9

結合range()和len()函數以遍歷一個序列的索引

>>> a = [‘Mary’, ‘had’, ‘a’, ‘little’, ‘lamb’]>>> for i in range(len(a)):
… print(i, a[i])

0 Mary
1 had
2 a
3 little
4 lamb

break和continue語句及循環中的else子句

break語句能夠跳出for和while的循環體。若是你從for或while循環中終止,任何對應的循環else塊將不執行。
continue語句被用來告訴Python跳過當前循環塊中的剩餘語句,而後繼續進行下一輪循環。
循環語句能夠有else子句;它在窮盡列表(以for循環)或條件變爲假(以while循環)循環終止時被執行,但循環被break終止時不執行.以下查尋質數的循環例子:

pass語句

pass語句什麼都不作。它只在語法上須要一條語句但程序不須要任何操做時使用.例如:

>>> while True:
… pass # 等待鍵盤中斷 (Ctrl+C)

函數

Python 定義函數使用 def 關鍵字,通常格式以下:

  1. def area(width, height):
  2. return width * height
  3. def print_welcome(name):
  4. print("Welcome", name)
  5. print_welcome("Fred")
  6. w =4
  7. h =5
  8. print("width =", w," height =", h," area =", area(w, h))
  9. WelcomeFred
  10. width =4 height =5 area =20

變量做用域

定義在函數內部的變量擁有一個局部做用域,定義在函數外的擁有全局做用域。

  1. #!/usr/bin/env python3
  2. a =4# 全局變量
  3. def print_func1():
  4. a =17# 局部變量
  5. print("in print_func a = ", a)
  6. def print_func2():
  7. print("in print_func a = ", a)
  8. print_func1()
  9. print_func2()
  10. print("a = ", a)
  11. in print_func a =17
  12. in print_func a =4
  13. a =4

缺省參數

函數也可使用 kwarg=value 的關鍵字參數形式被調用

  1. def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
  2. print("-- This parrot wouldn't", action, end=' ')
  3. print("if you put", voltage,"volts through it.")
  4. print("-- Lovely plumage, the", type)
  5. print("-- It's", state,"!")
  6. parrot(1000)# 1 positional argument
  7. parrot(voltage=1000)# 1 keyword argument
  8. parrot(voltage=1000000, action='VOOOOOM')# 2 keyword arguments
  9. parrot(action='VOOOOOM', voltage=1000000)# 2 keyword arguments
  10. parrot('a million','bereft of life','jump')# 3 positional arguments
  11. parrot('a thousand', state='pushing up the daisies')# 1 positional, 1 keyword

返回值

  1. def return_sum(x,y):
  2. c = x + y
  3. return c
  4. res = return_sum(4,5)
  5. print(res)

可變參數

  1. def arithmetic_mean(*args):
  2. sum =0
  3. for x in args:
  4. sum += x
  5. return sum
  6. print(arithmetic_mean(45,32,89,78))
  7. print(arithmetic_mean(8989.8,78787.78,3453,78778.73))
  8. print(arithmetic_mean(45,32))
  9. print(arithmetic_mean(45))
  10. print(arithmetic_mean())
  11. 244
  12. 170009.31
  13. 77
  14. 45
  15. 0

匿名函數

匿名函數lambda x: x * x實際上就是:

  1. def f(x):
  2. return x * x

關鍵字lambda表示匿名函數,冒號前面的x表示函數參數。
匿名函數有個限制,就是隻能有一個表達式,不用寫return,返回值就是該表達式的結果。
用匿名函數有個好處,由於函數沒有名字,沒必要擔憂函數名衝突。此外,匿名函數也是一個函數對象,也能夠把匿名函數賦值給一個變量,再利用變量來調用該函數

>>> f = lambda x: x * x
>>> f
<function at 0x101c6ef28>
>>> f(5)
25

map/reduce

Python內建了map()和reduce()函數。
咱們先看map。map()函數接收兩個參數,一個是函數,一個是Iterable,map將傳入的函數依次做用到序列的每一個元素,並把結果做爲新的Iterator返回。
舉例說明,好比咱們有一個函數f(x)=x2,要把這個函數做用在一個list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就能夠用map()實現以下:
map

  1. >>>def f(x):
  2. ...return x * x
  3. ...
  4. >>> r = map(f,[1,2,3,4,5,6,7,8,9])
  5. >>> list(r)
  6. [1,4,9,16,25,36,49,64,81]

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

  1. >>>from functools import reduce
  2. >>>def add(x, y):
  3. ...return x + y
  4. ...
  5. >>> reduce(add,[1,3,5,7,9])
  6. 25

和其它編程語言相比,Python 在儘量不增長新的語法和語義的狀況下加入了類機制。
Python中的類提供了面向對象編程的全部基本功能:類的繼承機制容許多個基類,派生類能夠覆蓋基類中的任何方法,方法中能夠調用基類中的同名方法。
對象能夠包含任意數量和類型的數據。

類定義了 init() 方法的話,類的實例化操做會自動調用 init() 方法。

  1. class people:
  2. #定義基本屬性
  3. name =''
  4. age =0
  5. #定義私有屬性,私有屬性在類外部沒法直接進行訪問
  6. __weight =0
  7. #定義構造方法
  8. def __init__(self,n,a,w):
  9. self.name = n
  10. self.age = a
  11. self.__weight = w
  12. #在類地內部,使用def關鍵字能夠爲類定義一個方法,與通常函數定義不一樣,類方法必須包含參數self,且爲第一個參數
  13. def speak(self):
  14. print("%s is speaking: I am %d years old"%(self.name,self.age))
  15. p = people('tom',10,30)
  16. p.speak()

繼承

  1. #單繼承示例
  2. class student(people):
  3. grade =''
  4. def __init__(self,n,a,w,g):
  5. #調用父類的構函
  6. people.__init__(self,n,a,w)
  7. self.grade = g
  8. #覆寫父類的方法
  9. def speak(self):
  10. print("%s is speaking: I am %d years old,and I am in grade %d"%(self.name,self.age,self.grade))
  11. s = student('ken',20,60,3)
  12. s.speak()

Python有限的支持多繼承形式。
須要注意圓括號中父類的順序,如果父類中有相同的方法名,而在子類使用時未指定,python從左至右搜索 即方法在子類中未找到時,從左到右查找父類中是否包含方法。

  1. #另外一個類,多重繼承以前的準備
  2. class speaker():
  3. topic =''
  4. name =''
  5. def __init__(self,n,t):
  6. self.name = n
  7. self.topic = t
  8. def speak(self):
  9. print("I am %s,I am a speaker!My topic is %s"%(self.name,self.topic))
  10. #多重繼承
  11. class sample(speaker,student):
  12. a =''
  13. def __init__(self,n,a,w,g,t):
  14. student.__init__(self,n,a,w,g)
  15. speaker.__init__(self,n,t)
  16. test = sample("Tim",25,80,4,"Python")
  17. test.speak()#方法名同,默認調用的是在括號中排前地父類的方法

私有屬性與方法

__private_attrs:兩個下劃線開頭,聲明該屬性爲私有,不能在類地外部被使用或直接訪問。在類內部的方法中使用時 self.__private_attrs。
__private_method:兩個下劃線開頭,聲明該方法爲私有方法,不能在類地外部調用。在類的內部調用 slef.__private_methods。

內置方法以下:
init 構造函數,在生成對象時調用
del 析構函數,釋放對象時使用
repr 打印,轉換
__setitem__按照索引賦值
__getitem__按照索引獲取值
__len__得到長度
__cmp__比較運算
__call__函數調用
__add__加運算
__sub__減運算
__mul__乘運算
__div__除運算
__mod__求餘運算
__pow__稱方

元類type

type()函數能夠查看一個類型或變量的類型,Hello是一個class,它的類型就是type,而h是一個實例,它的類型就是class Hello。
咱們說class的定義是運行時動態建立的,而建立class的方法就是使用type()函數。
type()函數既能夠返回一個對象的類型,又能夠建立出新的類型,好比,咱們能夠經過type()函數建立出Hello類,而無需經過class Hello(object)…的定義

  1. >>>def fn(self, name='world'):# 先定義函數
  2. ...print('Hello, %s.'% name)
  3. ...
  4. >>>Hello= type('Hello',(object,), dict(hello=fn))# 建立Hello class
  5. >>> h =Hello()
  6. >>> h.hello()
  7. Hello, world.
  8. >>>print(type(Hello))
  9. <class'type'>
  10. >>>print(type(h))
  11. <class'__main__.Hello'>

要建立一個class對象,type()函數依次傳入3個參數:

  1. class的名稱;
  2. 繼承的父類集合,注意Python支持多重繼承,若是隻有一個父類,別忘了tuple的單元素寫法;
  3. class的方法名稱與函數綁定,這裏咱們把函數fn綁定到方法名hello上。
    經過type()函數建立的類和直接寫class是徹底同樣的,由於Python解釋器遇到class定義時,僅僅是掃描一下class定義的語法,而後調用type()函數建立出class。

正常狀況下,咱們都用class Xxx…來定義類,可是,type()函數也容許咱們動態建立出類來,也就是說,動態語言自己支持運行期動態建立類,這和靜態語言有很是大的不一樣,要在靜態語言運行期建立類,必須構造源代碼字符串再調用編譯器,或者藉助一些工具生成字節碼實現,本質上都是動態編譯,會很是複雜。

metaclass
除了使用type()動態建立類之外,要控制類的建立行爲,還可使用metaclass。
metaclass,直譯爲元類,簡單的解釋就是:
當咱們定義了類之後,就能夠根據這個類建立出實例,因此:先定義類,而後建立實例。
可是若是咱們想建立出類呢?那就必須根據metaclass建立出類,因此:先定義metaclass,而後建立類。
鏈接起來就是:先定義metaclass,就能夠建立類,最後建立實例。
因此,metaclass容許你建立類或者修改類。換句話說,你能夠把類當作是metaclass建立出來的「實例」。

定義ListMetaclass,按照默認習慣,metaclass的類名老是以Metaclass結尾,以便清楚地表示這是一個metaclass

  1. # metaclass是類的模板,因此必須從`type`類型派生:
  2. classListMetaclass(type):
  3. def __new__(cls, name, bases, attrs):
  4. attrs['add']=lambda self, value: self.append(value)
  5. return type.__new__(cls, name, bases, attrs)
  6. classMyList(list, metaclass=ListMetaclass):
  7. pass
  8. >>> L =MyList()
  9. >>> L.add(1)
  10. >> L
  11. [1]

動態修改有什麼意義?直接在MyList定義中寫上add()方法不是更簡單嗎?正常狀況下,確實應該直接寫,經過metaclass修改純屬變態。
可是,總會遇到須要經過metaclass修改類定義的。ORM就是一個典型的例子。
ORM全稱「Object Relational Mapping」,即對象-關係映射,就是把關係數據庫的一行映射爲一個對象,也就是一個類對應一個表,這樣,寫代碼更簡單,不用直接操做SQL語句。
要編寫一個ORM框架,全部的類都只能動態定義,由於只有使用者才能根據表的結構定義出對應的類來。

@property

Python內置的@property裝飾器就是負責把一個方法變成屬性調用

  1. classStudent(object):
  2. @property
  3. def score(self):
  4. return self._score
  5. @score.setter
  6. def score(self, value):
  7. ifnot isinstance(value, int):
  8. raiseValueError('score must be an integer!')
  9. if value <0or value >100:
  10. raiseValueError('score must between 0 ~ 100!')
  11. self._score = value
  12. >>> s =Student()
  13. >>> s.score =60# OK,實際轉化爲s.set_score(60)
  14. >>> s.score # OK,實際轉化爲s.get_score()
  15. 60
  16. >>> s.score =9999
  17. Traceback(most recent call last):
  18. ...
  19. ValueError: score must between 0~100!

注意到這個神奇的@property,咱們在對實例屬性操做的時候,就知道該屬性極可能不是直接暴露的,而是經過getter和setter方法來實現的
還能夠定義只讀屬性,只定義getter方法,不定義setter方法就是一個只讀屬性:

  1. classStudent(object):
  2. @property
  3. def birth(self):
  4. return self._birth
  5. @birth.setter
  6. def birth(self, value):
  7. self._birth = value
  8. @property
  9. def age(self):
  10. return2015- self._birth

異常處理

讓用戶輸入一個合法的整數,可是容許用戶中斷這個程序(使用 Control-C 或者操做系統提供的方法)。用戶中斷的信息會引起一個 KeyboardInterrupt 異常。

  1. whileTrue:
  2. try:
  3. x = int(input("Please enter a number: "))
  4. break
  5. exceptValueError:
  6. print("Oops! That was no valid number. Try again ")

try語句按照以下方式工做;

  1. 首先,執行try子句(在關鍵字try和關鍵字except之間的語句)
  2. 若是沒有異常發生,忽略except子句,try子句執行後結束。
  3. 若是在執行try子句的過程當中發生了異常,那麼try子句餘下的部分將被忽略。若是異常的類型和 except 以後的名稱相符,那麼對應的except子句將被執行。最後執行 try 語句以後的代碼。
  4. 若是一個異常沒有與任何的except匹配,那麼這個異常將會傳遞給上層的try中。
    一個 try 語句可能包含多個except子句,分別來處理不一樣的特定的異常。最多隻有一個分支會被執行。
    處理程序將只針對對應的try子句中的異常進行處理,而不是其餘的 try 的處理程序中的異常。

一個except子句能夠同時處理多個異常,這些異常將被放在一個括號裏成爲一個元組,例如:

  1. except(RuntimeError,TypeError,NameError):
  2. pass

最後一個except子句能夠忽略異常的名稱,它將被看成通配符使用。你可使用這種方法打印一個錯誤信息,而後再次把異常拋出。

  1. import sys
  2. try:
  3. f = open('myfile.txt')
  4. s = f.readline()
  5. i = int(s.strip())
  6. exceptOSErroras err:
  7. print("OS error: {0}".format(err))
  8. exceptValueError:
  9. print("Could not convert data to an integer.")
  10. except:
  11. print("Unexpected error:", sys.exc_info()[0])
  12. raise

try except 語句還有一個可選的else子句,若是使用這個子句,那麼必須放在全部的except子句以後。這個子句將在try子句沒有發生任何異常的時候執行。

  1. for arg in sys.argv[1:]:
  2. try:
  3. f = open(arg,'r')
  4. exceptIOError:
  5. print('cannot open', arg)
  6. else:
  7. print(arg,'has', len(f.readlines()),'lines')
  8. f.close()

拋出異常

Python 使用 raise 語句拋出一個指定的異常。
raise 惟一的一個參數指定了要被拋出的異常。它必須是一個異常的實例或者是異常的類(也就是 Exception 的子類)。

  1. try:
  2. raiseNameError('HiThere')
  3. exceptNameError:
  4. print('An exception flew by!')
  5. raise

自定義異常

  1. classError(Exception):
  2. """Base class for exceptions in this module."""
  3. pass
  4. classInputError(Error):
  5. """Exception raised for errors in the input.
  6. Attributes:
  7. expression -- input expression in which the error occurred
  8. message -- explanation of the error
  9. """
  10. def __init__(self, expression, message):
  11. self.expression = expression
  12. self.message = message
  13. classTransitionError(Error):
  14. """Raised when an operation attempts a state transition that's not
  15. allowed.
  16. Attributes:
  17. previous -- state at beginning of transition
  18. next -- attempted new state
  19. message -- explanation of why the specific transition is not allowed
  20. """
  21. def __init__(self, previous, next, message):
  22. self.previous = previous
  23. self.next = next
  24. self.message = message

finally與with

無論try子句裏面有沒有發生異常,finally子句都會執行。
若是一個異常在 try 子句裏(或者在 except 和 else 子句裏)被拋出,而又沒有任何的 except 把它截住,那麼這個異常會在 finally 子句執行後再次被拋出。

  1. >>>def divide(x, y):
  2. try:
  3. result = x / y
  4. exceptZeroDivisionError:
  5. print("division by zero!")
  6. else:
  7. print("result is", result)
  8. finally:
  9. print("executing finally clause")
  10. >>> divide(2,1)
  11. result is2.0
  12. executing finally clause
  13. >>> divide(2,0)
  14. division by zero!
  15. executing finally clause
  16. >>> divide("2","1")
  17. executing finally clause
  18. Traceback(most recent call last):
  19. File"<stdin>", line 1,in?
  20. File"<stdin>", line 3,in divide
  21. TypeError: unsupported operand type(s)for/:'str'and'str'

一些對象定義了標準的清理行爲,不管系統是否成功的使用了它,一旦不須要它了,那麼這個標準的清理行爲就會執行。
當執行完畢後,文件會保持打開狀態,並無被關閉。
關鍵詞 with 語句就能夠保證諸如文件之類的對象在使用完以後必定會正確的執行他的清理方法(相似C#中的using)

  1. with open("myfile.txt")as f:
  2. for line in f:
  3. print(line, end="")

自定義模塊

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ' a test module '
  4. __author__ ='Michael Liao'
  5. import sys
  6. def test():
  7. args = sys.argv
  8. if len(args)==1:
  9. print('Hello, world!')
  10. elif len(args)==2:
  11. print('Hello, %s!'% args[1])
  12. else:
  13. print('Too many arguments!')
  14. if __name__=='__main__':
  15. test()

以上就是Python模塊的標準文件模板,固然也能夠所有刪掉不寫,可是,按標準辦事確定沒錯。
sys模塊有一個argv變量,用list存儲了命令行的全部參數。argv至少有一個元素,由於第一個參數永遠是該.py文件的名稱,例如:
運行python3 hello.py得到的sys.argv就是[‘hello.py’];
運行python3 hello.py Michael得到的sys.argv就是[‘hello.py’, ‘Michael]。

參考

http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
http://www.runoob.com/python/python-tutorial.html



相關文章
相關標籤/搜索