Python語言特點及環境變量配置
Python語言特點:
- 1.易於學習:Python有相對較少的關鍵字,結構簡單,和一個明確定義的語法,學習起來更加簡單。
- 2.易於閱讀:Python代碼定義的更清晰。
- 3.易於維護:Python的成功在於它的原始碼是相當容易維護的。
- 4.一個廣泛的標準庫:Python的最大的優勢之一是豐富的庫,跨平台的,在UNIX,Windows和Macintosh兼容很好。
- 5.互動模式:互動模式的支持,您可以從終端輸入執行代碼並獲得結果的語言,互動的測試和調試代碼片斷。
- 6.可移植:基於其開放原始碼的特性,Python已經被移植(也就是使其工作)到許多平台。
- 7.可擴展:如果你需要一段運行很快的關鍵代碼,或者是想要編寫一些不願開放的算法,你可以使用C或C++完成那部分程序,然後從你的Python程序中調用。
- 8.資料庫:Python提供所有主要的商業資料庫的接口。
- 9.GUI編程:Python支持GUI可以創建和移植到許多系統調用。
- 10.可嵌入: 你可以將Python嵌入到C/C++程序,讓你的程序的用戶獲得"腳本化"的能力。
下載地址:https://www.python.org/
懶人模式,安裝提示里勾選上自動配置環境變量,pip等,安裝完成後,你連環境變量都不用配置了。
但是學習的人還是要謙虛一點,配環境變量也是基本功。
「Python.exe」 所在的文件夾C:\Python\Python36-32加入的環境變量的Path下面就好了
配置完成後cmd終端里檢查一下,如下圖沒有保錯,說明配置正確。
對縮進要求嚴格,四個空格,不建議用Tab,不同平台上縮進不一樣
要輸出中文在開頭寫上 # -*- coding: utf-8 -*-
我使用的IDE為Pycharm,注釋為ctrl + /
官方文檔 http://docs.python.org/2/
中文文檔 http://python.usyiyi.cn/
http://www.pythondoc.com/
一張圖概況Python學習(轉自W3Cschool)
目錄:
Python基礎語法:
(1)列印出hello world
(2)注釋
(3)數據類型
(4)運算
(5)輸入
(6)輸出
(7)序列
(8)相等比較
(9)選擇
(10)循環
(11)字典(dict)
(12)集合(set)(不常用)
(14)pass,del,exec,eval
(15)內建函數
Python進階語法:
(1)文件
(2)錯誤和異常
(3)模塊和包
(4)作用域
(5)高階函數
(6)裝飾器
(7)參數
(8)面向對象
(9)定製類(魔術方法)
(10)日期和時間
(11)數學與隨機數
(12)正則表達式
Python基礎語法:
(1)列印出hello world
# -*- coding: utf-8 -*-print "hello world"print "你好 世界"
(2)注釋
1、(單行注釋)以 # 開頭,後面的文字直到行尾都算注釋
2、(多行注釋)多行注釋是用三引號''' '''包含的(單引號和雙引號均可)
3、(中文注釋)要注釋中文必須程序開頭先寫上# -*- coding: utf-8 -*-,不然會報錯
(3)數據類型
1、變量不需要聲明,可以直接輸入,大小寫敏感
2、這裡的var = xxxx不叫變量賦值,而叫變量綁定,一個符號可以綁定任意類型的值。
3、內置函數type(), 用以查詢變量的類型
var = 1print var #1print type(var) #整數類型 # <type 'int'>var = 1.1print var # 1.1print type(var) #浮點數類型 # <type 'float'>var = 'hello'print var # helloprint type(var) #字符串 # <type 'str'>var = (1==1) print var # Trueprint type(var) #布爾型 # <type 'bool'>var = Noneprint var # Noneprint type(var) #空值 # <type 'NoneType'>var = 1+1j 或者complex(a,b)表示, 複數的實部a和虛部b都是浮點型print var # (1+1j)print type(var) #複數類型 # <type 'complex'>
4、字符串以''或" "括起來的任意文本
5、布爾型(True, False,可以用and, or, not運算,而不是C語言的&&和||)
6、多變量賦值
a = b = c = 1a, b, c = 1, 2, "john" #等號兩邊都是元組,建議加上括號,增加可讀性x,y = y,x #兩值交換,不需要temp,更加簡潔
7、賦值語句不可以返回值,對象是通過引用傳遞的
y = (x = x + 1) #這是非法的
(4)運算
1、加、減、乘、除、求余、乘方
2、乘方 ** 右結合
2**3=8 2**2**3=256(2**2)**3=64
3、整數運算結果仍然是整數,浮點數運算結果仍然是浮點數。
但是整數和浮點數混合運算的結果就變成浮點數了。
4、字符串與整數相乘
print 'abc' * 3 結果 abcabcabc
5、因為Python把0、空字符串''和None看成 False,其他數值和非空字符串都看成 True
True and 'a=T' 計算結果是 'a=T'
繼續計算 'a=T' or 'a=F' 計算結果還是 'a=T'
要解釋上述結果,又涉及到 and 和 or 運算的一條重要法則:短路計算。
①在計算 a and b 時,如果 a 是 False,則根據與運算法則,整個結果必定為 False,因此返回 a;如果 a 是 True,則整個計算結果必定取決與 b,因此返回 b。
②在計算 a or b 時,如果 a 是 True,則根據或運算法則,整個計算結果必定為 True,因此返回 a;如果 a 是 False,則整個計算結果必定取決於 b,因此返回 b。
所以Python解釋器在做布爾運算時,只要能提前確定計算結果,它就不會往後算了,直接返回結果。
6、不支持自加(i++)和自減(i--)
7、地板除(//)除法不管操作數何種數值類型,總是捨去小數部分,返回數字序列中比真正的商小的最接近的數字。
print 5//3 #1print 1.0//2.0 #0.0print -1/2 #-1
(5)輸入
x = input() #1+2print type(x) #<type 'int'>y = raw_input() #1+2print type(y) # <type 'str'>
1、由此可見, input() 在對待純數字輸入返回所輸入的數字的類型(int,float)
而raw_input() 將所有輸入作為字符串看待,返回字符串類型。
為了避免類型發生錯誤,一般情況下使用 raw_input() 來與用戶交互。
(6)輸出
1、Python2 裡面print可以直接接字符串或者運算。
2、Python3 裡面print變成了一個函數,上面的寫法不支持了,必須用一個括號括起來,否則會報告語法錯誤。
3、>>>是Python解釋器的提示符,不是代碼的一部分。
4、print語句也可以跟上多個字符串,用逗號「,」隔開,遇到逗號「,」會輸出一個空格:
print '1+2=',1+2 #1+2= 3
5、多行輸出使用三個引號和使用換行符\n一致
print '''哈哈哈'''print "哈\n哈\n哈"# 輸出結果# 哈# 哈# 哈# 哈# 哈# 哈
6、轉義
print r'C:\log.txt'print 'C:\\log.txt'# C:\log.txt# C:\log.txt
7、print 語句與字符串格式運算符( % )結合使用,可實現字符串替換功能
print "%s is number %d!" % ("Python", 1)
%s表示由一個字符串來替換,%d表示由一個整數來替換,%f表示由一個浮點數來替換。
Python 非常靈活,即使將數字傳遞給 %s,也不會像其他要求嚴格的語言一樣引發嚴重後果。
(7)序列
1、序列有兩種: list (可變列表) 和tuple(不可變元組)
2、定義:序列是一組有順序的元素的集合,可以包含一個或多個元素,也可以沒有任何元素。
list = [0,1,2,3,4,5] #列表用中括號,可改變,理解為數組tuple = (0,1,2,3,4,5) #元祖用小括號,不可改變
由於Python是動態語言,所以list中包含的元素並不要求都必須是同一種數據類型
2、序列的通用操作
seq = "0123456789"print seq[0] #序列元素的下標從0開始。注意不要越界print seq[-1] #倒序索引,-1代表倒數第一。print seq[1:5] #支持切片操作,seq[start:end],start包含在結果中,end不包含在結果中。print range(1,101)[0:10]#從第1個數元素開始取,到第11元素結束print seq[7:] #seq[start:end]中的end可以省略。print seq[-3:] #分片也支持負數。print seq[:3] #seq[start:end]中的start也可以省略。print seq[:] #全部省略會複製整個序列。print seq[::2] #支持步長。print seq[::-1] #逆序輸出。print seq[9:1:-1] #支持負步長。print range(1,101)[2::3]#從第三元素開始取,每隔2個取一個元素,即3的倍數print range(1,101)[4:50:5]#從第五個取,每隔4個取一個,50以內5的倍數 print [1, 2, 3] + [4, 5, 6] # 序列支持相加,這解釋了為什麼字符串可以相加。print [1, 2, 3] * 3 #序列支持相乘,這解釋了為什麼字符串可以相稱。print [None] * 10 #生成一個空序列。print 1 in [1, 2, 3] #成員判斷。print range(1,101)[4::5][-10:] #切片可以嵌套,最後10個5的倍數,先獲得5的倍數再取後10個
記住倒數第一個元素的索引是-1。倒序切片包含起始索引,不包含結束索引。
3、可變的列表(list)
list = [0,1,2,3,4,5]list.append(7) #append()總是把新元素添加到list的尾部print list # [0, 1, 2, 3, 4, 5, 7]list.insert(0,-1) #insert()接受兩個參數,第一個是索引,第二個是元素print list # [-1, 0, 1, 2, 3, 4, 5, 7]list.insert(-1,6) #insert(-1)是最後一個元素之前,即倒數第二個元素,因為insert()前插print list # [-1, 0, 1, 2, 3, 4, 5, 6, 7]list.pop() #pop()方法總是刪掉最後一個元素print list # [-1, 0, 1, 2, 3, 4, 5, 6]list.pop(0) #參數為索引print list # [0, 1, 2, 3, 4, 5, 6]list[6]=7 #對list中的某一個索引賦值,就可以直接用新的元素替換掉原來的元素print list # [0, 1, 2, 3, 4, 5, 7]list[0],list[-1]=list[-1],list[0] #第一與最後位置調換print list # [7, 1, 2, 3, 4, 5, 0]
在使用可變對象的方法如 sort(),extend()和 reverse()的時候要注意,這些操作會在列表
中原地執行操作,也就是說現有的列表內容會被改變,但是沒有返回值!
4、不可變的元組(tuple)
字符串是一種特殊的元組
沒有 append()方法,也沒有insert()和pop()方法,也不能賦值
Tuple 比 list 操作速度快.如果您定義了一個值的常量集,並且唯一要用它做的是不斷地遍歷它,請使用 tuple 代替 list.如月份,星期。
print (1,) #一個元素的元祖。
因為()既可以表示tuple,又可以作為括號表示運算時的優先級,結果 (1) 被Python解釋器計算出結果 1,導致我們得到的不是tuple,而是整數 1。正是因為用()定義單元素的tuple有歧義,所以 Python 規定,單元素 tuple 要多加一個逗號「,」,這樣就避免了歧義。
可變的元組:tuple的元素指向list,而list內的值可變
5、序列解包
x, y, z = 1, 2, 3print x, y, z(x, y, z) = (1, 2, 3)print x, y, z(x, y, z) = [1, 2, 3]print x, y, z
(8)相等比較
#== 和 is的差別,==比較的是值,is比較的是引用。x = [1, 2, 3]y = xz = [1, 2, 3]print(x == y) #Trueprint(x == z) #Trueprint(x is y) #Trueprint(x is z) #False
(9)選擇
1、Python代碼的縮進規則。具有相同縮進的代碼被視為代碼塊
2、縮進請嚴格按照Python的習慣寫法:4個空格,不要使用Tab,更不要混合Tab和空格
3、格式
if 條件1: statementelif 條件2: statementelif 條件3: statementelse: statement
If後面不需要括號,但是條件後面需要冒號
elif 即 else if
4、三元運算符
x, y = 4, 3if x < y: result = xelse: result = yprint result#等價於result = x if x < y else yprint result
(10)循環
1、for循環依次把list或tuple的每個元素疊代出來
格式
for 元素 in 序列: statement
name 這個變量是在 for 循環中定義的,意思是,依次取出list中的每一個元素,並把元素賦值給 name,然後執行for循環體(就是縮進的代碼塊)
L = ['Adam', 'Lisa', 'Bart']for name in L: print name
這樣一來,遍歷一個list或tuple就非常容易了。
2、while循環,不會疊代 list 或 tuple 的元素,而是根據表達式判斷循環是否結束。
while 條件: statement
3、中斷循環 break和continue
4、range()的用法
range(1,5) #代表從1到5(不包含5) [1, 2, 3, 4]range(1,5,2) #代表從1到5,間隔2(不包含5) [1, 3]range(5) #代表從0到5(不包含5) [0, 1, 2, 3, 4]
5、Python中,疊代永遠是取出元素本身,而非元素的索引。
對於有序集合,元素確實是有索引的。使用enumerate() 函數拿到索引
L = ['Adam', 'Lisa', 'Bart', 'Paul']for index, name in enumerate(L): print index, '-', name#結果# 0 - Adam# 1 - Lisa# 2 - Bart# 3 - Paul
使用 enumerate() 函數,我們可以在for循環中同時綁定索引index和元素name。但是,這不是 enumerate() 的特殊語法。實際上,enumerate() 函數把:
['Adam', 'Lisa', 'Bart', 'Paul']
變成了類似:
[(0, 'Adam'), (1, 'Lisa'), (2, 'Bart'), (3, 'Paul')]
因此,疊代的每一個元素實際上是一個tuple:
6、好用的zip()方法
for x, y in zip(range(1, 10), range(1, 10)): print(x, y)# 結果# (1, 1)# (2, 2)# (3, 3)# (4, 4)# (5, 5)# (6, 6)# (7, 7)# (8, 8)# (9, 9)
7、列表生成式,非常簡潔
要生成[1x1, 2x2, 3x3, ..., 10x10]
print [x * x for x in range(1, 11)]#[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
列表生成式的 for 循環後面還可以加上 if 判斷。例如:
print [x * x for x in range(1, 11) if x % 2 == 0]# [4, 16, 36, 64, 100]
8、疊代器
它為類序列對象提供了一個類序列的接口。
疊代非序列集合(例如映射和文件)時, 可以創建更簡潔可讀的代碼。
myTuple = (123, 'xyz', 45.67)i = iter(myTuple)print i.next() #123print i.next() #xyzprint i.next() #45.67i.next() #報錯
(11)字典(dict)
1、字典的元素沒有順序。你不能通過下標引用元素。字典是通過鍵來引用,用大括號
查找速度快,無論dict有10個元素還是10萬個元素,查找速度都一樣。而list的查找速度隨著元素增加而逐漸下降。
dict的缺點是占用內存大,還會浪費很多內容
dict是按 key 查找,所以,在一個dict中,key不能重複
作為 key 的元素必須不可變
2、已知兩個列表,一個是名字,一個是成績,要根據名字找到對應的成績用兩個list不方便,如果把名字和分數關聯起來,組成類似的查找表,即 Python中的dict
用 dict 表示「名字」-「成績」的查找表如下:
dic = {'tom':11, 'sam':57,'lily':100}print type(dic) #<type 'dict'>d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59}print d #{'Lisa': 85, 'Adam': 95, 'Bart': 59}
3、我們把名字稱為key,對應的成績稱為value,dict就是通過 key 來查找 value。
4、花括號 {} 表示這是一個dict,然後按照 key: value, 寫出來即可。最後一個 key: value 的逗號可以省略。
5、由於dict也是集合,len()函數可以計算任意集合的大小:
print len(d) #運算結果為3
一個 key-value 算一個,因此,dict大小為3。
6、可以簡單地使用 d[key] 的形式來查找對應的 value,這和 list 很像,不同之處是,list 必須使用索引返回對應的元素,而dict使用key:
print d['Adam'] #95
注意: 通過 key 訪問 dict 的value,只要 key 存在,dict就返回對應的value。如果key不存在,會直接報錯:KeyError。
要避免 KeyError 發生,有兩個辦法:
一是先判斷一下 key 是否存在,用 in 操作符:
二是使用dict本身提供的一個 get 方法,在Key不存在的時候,返回None:
print d.get('Bart') #59print d.get('Paul') #None
7、在字典中增添一個新元素的方法:
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59}print d #{'Lisa': 85, 'Adam': 95, 'Bart': 59}d['lilei'] = 99print d #{'lilei': 99, 'Lisa': 85, 'Adam': 95, 'Bart': 59}
8、循環調用
for key in d: #或for key in d.keys() print d[key]# 結果# 99# 85# 95# 59
9、字典的常用方法
print d.keys() # 返回d所有的鍵print d.values() # 返回d所有的值print d.items() # 返回d所有的元素(鍵值對)d.clear() # 清空d,dict變為{}del d[『xxx』] # 刪除 d 的『xxx』元素for key, value in d.items(): print key, ':', value
10、cmp()比較
(1)先比較字典長度
(2)再比較字典的鍵
(3)最後比較字典的值
(4)都一樣就相等
(12)集合(set)(不常用)
1、dict的作用是建立一組 key 和一組 value 的映射關係,dict的key是不能重複的。
有的時候,我們只想要 dict 的 key,不關心 key 對應的 value,目的就是保證這個集合的元素不會重複,這時,set就派上用場了。
2、set 持有一系列元素,這一點和 list 很像,但是set的元素沒有重複,而且是無序的,這點和 dict 的 key很像。
3、創建 set 的方式是調用 set() 並傳入一個 list,list的元素將作為set的元素:
s = set(['A', 'B', 'C'])print s #set(['A', 'C', 'B'])
4、添加、刪除
s.add('D')print s #set(['A', 'C', 'B', 'D'])s.add('D') #已存在不會報錯s.remove('D')print s #set(['A', 'C', 'B'])s.remove('D') #報錯,需要先判斷
(13)函數
1、定義一個函數要使用 def 語句,依次寫出函數名、括號、括號中的參數和冒號:,然後,在縮進塊中編寫函數體,函數的返回值用 return 語句返回。
def say_b(): print "b"say_b() #調用函數,列印出b
2、如果沒有return語句,函數執行完畢後也會返回結果,只是結果為 None。
3、函數返回多個值
import mathdef move(x, y, step, angle): nx = x + step * math.cos(angle) ny = y - step * math.sin(angle) return nx, nyx, y = move(100, 100, 60, math.pi / 6)print x, y #151.961524227 70.0r = move(100, 100, 60, math.pi / 6)print r #(151.96152422706632, 70.0)
其實這只是一種假象,Python函數返回的仍然是單一值,是一個tuple:
但是,在語法上,返回一個tuple可以省略括號,而多個變量可以同時接收一個tuple,按位置賦給對應的值,所以,Python的函數返回多值其實就是返回一個tuple,但寫起來更方便。
4、在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。
def fact(n): if n==1: return 1 return n * fact(n - 1)print fact(10) #計算10的階乘
5、定義函數的時候,還可以有默認參數。
def power(x, n=2): s = 1 while n > 0: n = n - 1 s = s * x return sprint power(2) #默認計算2的平方print power(2,3) #計算2的三次方
由於函數的參數按從左到右的順序匹配,所以默認參數只能定義在必需參數的後面:
6、一個函數能接受任意個參數,我們就可以定義一個可變參數:
def fn(*args): print argsfn('a') #('a',)fn('a', 'b') #('a', 'b')fn('a', 'b', 'c') #('a', 'b', 'c')
可變參數的名字前面有個 * 號,我們可以傳入0個、1個或多個參數給可變參數:
7、基本數據類型的參數:值傳遞
表作為參數:指針傳遞
(14)pass,del,exec,eval
1、pass語句
pass代表該語句什麼都不做,因為python中空代碼是非法的,比如一個if語句要求什麼內容都不做,我們就可以使用pass語句。
2、del語句
一般來說python會刪除那些不在使用的對象(因為使用者不會再通過任何變量或者數據結構引用它們)
3、exec語句(運行字符串中的程序)
exec "print 'hello world'" #hello world
4、eval函數(會計算python表達式(以字符串形式書寫),並且返回結果)
print eval('2+ 2') #4print eval(raw_input("please input number:")) #輸入2+2 得4
(15)內建函數
1、cmp(obj1, obj2) 比較 obj1 和 obj2, 根據比較結果返回整數 i:
if obj1 < obj2 返回i < 0 if obj1 > obj2 返回i > 0 if obj1 == obj2 返回i == 0
如果是用戶自定義對象, cmp()會調用該類的特殊方法__cmp__()
2、str() 強制轉換成字符串
3、type() :詳見(3)數據類型 - 3、
4、help():通過用函數名作為 help()的參數就能得到相應的幫助信息
5、isinstance(變量名,類型): 判斷是否是這個類型的元素,可以用if語句
6、abs():取絕對值
7、enumerate():詳見(10)循環 - 5、
8、len(seq):返回seq的長度
9、sorted(iter):排序,會調用cmp()
10、zip(a1,a2……):詳見(10)循環 - 6、
11、range():詳見(10)循環 - 4、
12、string.lower():轉換字符串中所有大寫字符為小寫
13、string.upper():轉換字符串中所有小寫字符為大寫
14、string.strip():刪去字符串開頭和結尾的空格
15、string.capitalize():把字符串第一個字符大寫
16、string.title():所有單詞都以大寫開頭
17、max()和min():找出最大和最小值
18、sum():求和
19、reversed():倒序輸出
Python進階語法:
(1)文件
1、文件也是一個對象。
2、打開文件
f = open(文件名,模式)
文件名可以是相對路徑或者絕對路徑
模式有:"r" 只讀、「w」 寫入、「a」 追加,「r+/w+」讀寫
使用 'r' 或 'U' 模式打開的文件必須是已經存在的。 使用 'w' 模式打開的文件若存在則首先清空, 然後(重新)創建。 以 'a' 模式打開的文件是為追加數據作準備的, 所有寫入的數據都將追加到文件的末尾。 即使你 seek 到了其它的地方。 如果文件不存在, 將被自動創建, 類似以 'w'模式打開文件。
test = open("test.txt", "w")
3、屬性
test = open("test.txt", "w")print "文件名: ", test.name #文件名: test.txtprint "是否已關閉 : ", test.closed #是否已關閉 : Falseprint "訪問模式 : ", test.mode #訪問模式 : w
4、關閉 close()
test = open("test.txt", "w")test.close()print "是否已關閉 : ", test.closed #是否已關閉 : True
5、寫入write()
write()方法可將任何字符串寫入一個打開的文件。
write()方法不在字符串的結尾不添加換行符('\n'):
test = open("test.txt", "w")test.write("this is a test\n this is a test again \n")test.close()#可以在文件中看到 # this is a test# this is a test again
主動調用close()寫緩存同步到磁碟,或者寫入數據量大於或等於寫緩存,寫緩存同步到磁碟
6、讀取 read()、readline()、readlines()
read(size)方法從一個打開的文件中讀取一個字符串。size若不填則為儘量多的字符串,若填了則為結束位置。
readline()讀取當前行,允許有參數readlines()讀取剩餘行,返回一個字符串列表test = open ("test.txt", "w")test.write("python is a language \npython is a great language ")test.close()test = open("test.txt", "r")str = test.read()print strtest.close()#python is a language #python is a great language
7、文件位置
tell()方法告訴你文件內的當前位置;即下一次的讀寫會發生在文件開頭這麼多字節之後:
seek(offset [,from])方法改變當前文件的位置。Offset變量表示要移動的字節數。From變量指定開始移動字節的參考位置。如果from被設為0,這代表著將文件的開頭作為移動字節的參考位置。如果設為1,則使用當前的位置作為參考位置。如果它被設為2,那麼該文件的末尾將作為參考位置。
test = open ("test.txt", "w")test.write("python is a language \npython is a great language ")test.close()test = open("test.txt", "r")str = test.read()print "the first input:\n",str#輸出# the first input:# python is a language# python is a great language# 查找當前位置position = test.tell()print position#50# 把指針再次重新定位到文件開頭position = test.seek(0, 0)str2 = test.read(10)print "the second input:\n", str2# the second input:# python istest.close()
8、重命名
Python的os模塊提供了幫你執行文件處理操作的方法,必須先導入它,才可以調用。
os.rename(當前文件名,新的文件名)
9、刪除文件
同樣需要導入os模塊,才可以調用。
os.remove(文件名)
(2)錯誤和異常
1、錯誤類型
OverflowError數值運算超出最大限制
ZeroDivisionError 除(或取模)零 (所有數據類型)
AttributeError對象沒有這個屬性
IOError 輸入/輸出操作失敗
IndexError 序列中沒有此索引(index)
NameError 未聲明/初始化對象 (沒有屬性)
SyntaxError Python 語法錯誤
TypeError 對類型無效的操作
ValueError 傳入無效的參數
2、try-except處理異常
try-except語句用來檢測try語句塊中的錯誤,從而讓except語句捕獲異常信息並處理。
try:<語句> #運行別的代碼except Exception1,e:#Exception是錯誤類型名,e是儲存錯誤,可以調用<語句> #如果在try部份引發了'名字'異常except Exception2,e:<語句> #如果引發了'名字'異常,獲得附加的數據else:<語句> #如果沒有異常發生
當try後的語句執行時發生異常,python就跳回到try並執行第一個匹配該異常的except子句,異常處理完畢,控制流就通過整個try語句(除非在處理異常時又引發新的異常)。如果在try子句執行時沒有發生異常,python將執行else語句後的語句(如果有else的話),然後控制流通過整個try語句。
try: fh = open("testfile", "w") fh.write("This is my test file for exception handling!!")except IOError: print "Error: can\'t find file or read data"else: print "Written content in the file successfully" #Written content in the file successfullytry: fh = open("testfile", "r") #只讀文件不能寫入 fh.write("This is my test file for exception handling!!")except IOError,e: print "Error: can\'t find file or read data" print "catch error:",eelse: print "Written content in the file successfully" #Error: can't find file or read data #atch error: File not open for writing
except若不帶任何異常類型,即捕獲所有發生的異常。但是不能捕獲語法錯誤異常,如if a,因為是運行前錯誤而不是運行時錯誤
也可帶多種類型except(Exception1[, Exception2[,...ExceptionN]]]):
錯誤類型後面跟著變量e,可以print錯誤提示
案例如下
import randomnum = random.randint(0,100)while 1: try: guess = int(raw_input("Enter 1-100:")) except ValueError,e: print "error ! please enter 1-100" continue if guess > num: print "guess bigger:",guess elif guess < num: print "guess smaller:",guess else: print "guess right,game over" break
3、try-finally語句
語句是否發生異常都將執行最後的代碼。將異常保留下來交給系統處理,本身不處理異常。
作用:為處理異常事件提供清理機制,用來關閉文件或者釋放系統資源。
try:<語句>finally:<語句> #退出try時總會執行raise
可以使用except語句或者finally語句,但是兩者不能同時使用。else語句也不能與finally語句同時使用。
4、try-except-finally
若try語句沒有捕獲異常,執行完try代碼段後,執行finally
若try捕獲異常,首先執行except處理異常,然後執行finally
5、try-except-else-finally
若try語句沒有捕獲異常,執行完try代碼段後,執行else代碼段,最後執行finally
若try捕獲異常,首先執行except處理錯誤,然後執行finally
6、try-finally-except
當在try塊中拋出一個異常,立即執行finally塊代碼。
finally塊中的所有語句執行後,異常被再次提出,並執行except塊代碼。
7、with語句
用來代替try-except-finally語句,使代碼更加簡潔
with context[as var]: with_suite
context表達式返回是一個對象
var用來保存context返回對象,單個返回值或元組
with_suite使用var變量對context返回對象進行操作
with open("1.text") as f: for line in f.readline(): print line
1、打開1.txt文件
2、f變量接收文件對象返回的對象
3、with中的代碼執行完成後,關閉文件
程序使用了上下文管理器 (with...as...)。上下文管理器有隸屬於它的程序塊。當隸屬的程序塊執行結束的時候(也就是不再縮進),上下文管理器自動關閉了文件
運用情況:①文件操作 ②進城之間互斥操作:例如互斥鎖 ③支持上下文的其他對象
8、raise主動拋出異常
#格式rasie [exception[,args]]#Exception 異常類#args 描述異常信息的元組raise TypeError,"Test Error" #TypeError: Test Error
9、assert語句
斷言語句:assert語句是用於檢測表達式是否為真,如果為假,引發AssertionError錯誤
#格式assert expression [,args]#expression 表達式#args 判斷條件的描述信息10、自定義異常通過創建一個新的異常類,程序可以命名它們自己的異常。異常應該是典型的繼承自Exception類,通過直接或間接的方式。自定義異常只能主動觸發。class FileError(IOError): passtry: raise FileError,"test error"except FileError,e: print e #test errorclass CustomError(Exception): def __init__(self,info): Exception.__init__(self) self.errorinfo = info def __str__(self): return "CustomError:%s" %self.errorinfotry: raise CustomError("test CustomError")except CustomError,e: print "ErrorInfo:",e #ErrorInfo: CustomError:test CustomError
(3)模塊和包
1、概念介紹
#test.py 自身模塊名test
import p1.util 引用p1包的模塊util
print p1.util.f(2) 調用p1.util的函數f()
如何區分包和普通目錄 包下面有個__inti__.py文件
2、如果我們只希望導入用到的math模塊的某幾個函數,而不是所有函數,可以用下面的語句:
from math import pow, sin, log
3、可以給函數起個「別名」來避免衝突:as
from math import logfrom logging import log as logger # logging的log現在變成了loggerprint log(10) # 調用的是math的loglogger(10, 'import from logging') # 調用的是logging的log
4、如果導入的模塊不存在,Python解釋器會報 ImportError 錯誤:
5、第三方模塊管理系統
-easy_install
-pip(推薦,已內置到Python2.7.9)
(4)作用域
1、函數作用域LEGB L>E>G>B
L:local 函數內部作用域
E:enclosing 函數內部與內嵌函數之間,即閉包
G:global全局作用域
B:bulid-in 內置作用域 list,tuple之類
passline = 60 #全局def func(val): passline = 90 #函數內部 if val >= passline: print "pass" else: print "failed" def in_func(): print val #函數內部與內嵌函數之間 in_func()func(69) #failed#69
(5)高階函數
1、由於參數 x, y和 f 都可以任意傳入,如果 f 傳入其他函數,就可以得到不同的返回值。
def add(x, y, f): return f(x) + f(y)print add(-5, 9, abs) #abs(-5) + abs(9) = 14
2、map() 映射
map()是 Python 內置的高階函數,它接收一個函數f和一個list,並通過把函數f依次作用在 list的每個元素上,得到一個新的 list 並返回。
def f(x): return x*xprint map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) #[1, 4, 9, 16, 25, 36, 49, 64, 81]
利用map()函數,可以把一個 list 轉換為另一個 list,只需要傳入轉換函數。
由於list包含的元素可以是任何類型,因此,map()不僅僅可以處理只包含數值的 list,事實上它可以處理包含任意類型的 list,只要傳入的函數f可以處理這種數據類型。
3、reduce()摺疊
reduce()函數接收的參數和 map()類似,一個函數f,一個list,但reduce()傳入的函數f必須接收兩個參數,reduce()對list的每個元素反覆調用函數f,並返回最終結果值。
def f(x, y): return x + yprint reduce(f, [1, 3, 5, 7, 9]) #25#先計算頭兩個元素:f(1, 3),結果為4;#再把結果和第3個元素計算:f(4, 5),結果為9;#再把結果和第4個元素計算:f(9, 7),結果為16;#再把結果和第5個元素計算:f(16, 9),結果為25;#由於沒有更多的元素了,計算結束,返回結果25。#初始值100print reduce(f, [1, 3, 5, 7, 9], 100) #125
reduce()還可以接收第3個可選參數,作為計算的初始值。
4、filter() 過濾
filter()函數接收一個函數f和一個list,這個函數 f 的作用是對每個元素進行判斷,返回 True或 False,filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。
def is_odd(x): #是奇數 return x % 2 == 1print filter(is_odd, [1, 4, 6, 7, 9, 12, 17]) #[1, 7, 9, 17]
利用filter(),可以完成很多有用的功能,例如,刪除 None 或者空字符串:
def is_not_empty(s): return s and len(s.strip()) > 0print filter(is_not_empty, ['test', None, '', 'str', ' ', 'END']) #['test', 'str', 'END']
5、sorted():對list進行排序
print sorted([36, 5, 12, 9, 21]) #[5, 9, 12, 21, 36]
但sorted()也是一個高階函數,它可以接收一個比較函數來實現自定義排序,比較函數的定義是,傳入兩個待比較的元素x, y,如果x應該排在y的前面,返回-1,如果x應該排在y的後面,返回1。如果x和y相等,返回0。
#倒序排序def reversed_cmp(x, y): if x > y: return -1 if x < y: return 1 return 0print sorted([36, 5, 12, 9, 21], reversed_cmp) #[36, 21, 12, 9, 5]
6、Python的函數不但可以返回int、str、list、dict等數據類型,還可以返回函數!
def f(): print 'call f()...' # 定義函數g: def g(): print 'call g()...' # 返回函數g: return gx = f() # 調用f() call f()...x # 變量x是f()返回的函數: #<function g at 0x00000000022CDA58>x() # x指向函數,因此可以調用 call g()...x=f(),x()=g()
請注意區分返回函數和返回值:
def myabs(): return abs # 返回函數def myabs2(x): return abs(x) # 返回函數調用的結果,返回值是一個數值
在函數內部定義的函數和外部定義的函數是一樣的,只是他們無法被外部訪問:
7、閉包(closure)
內部函數中引用了外層函數的變量(enclosing作用域的變量),然後返回內層函數的情況。
閉包的作用是封裝和代碼復用。
傳遞的是參數
#如果要實現兩個功能,可以定義兩個函數。def func_150(val): passline = 90 #150 if val >= passline: print ("pass") else: print "failed"def func_100(val): passline = 60 #150 if val >= passline: print ("pass") else: print "failed"func_100(69)#passfunc_150(69)#failed#如果用閉包的話只需要定義一個函數def set_passline(passline):#passline def cmp(val): if val >= passline: print "pass" else: print "failed" return cmp #返回值是一個函數f_100 = set_passline(60) #f_100就是cmp,f_100()就是cmp(),而且內置一個passline=60f_150 = set_passline(90)f_100(69)#passf_150(69)#failed
傳遞的是函數
#不用閉包def my_sum(*arg): if len(arg)==0: return 0 for val in arg: if not isinstance(val,int): return 0 return sum(arg)def my_average(*arg): if len(arg)==0: return 0 for val in arg: if not isinstance(val,int): return 0 return sum(arg)/len(arg)print my_sum(1,2,3,4,5) #15print my_sum(1,2,3,4,5,'6')#0print my_average(1,2,3,4,5)#3print my_average()#0#使用閉包def my_sum(*arg): print "in my_sum" return sum(arg)def my_average(*arg): return sum(arg)/len(arg)def dec(func): def in_dec(*arg): print "in_dec()=",arg if len(arg) == 0: return 0 for val in arg: if not isinstance(val, int): return 0 return func(*arg) return in_dec #別加括號#dec return in_dec -> my_sum#my_sum = in_dec(*arg)my_sum = dec(my_sum)my_average = dec(my_average)#同理print my_sum(1,2,3,4,5)print my_sum(1,2,3,4,5,'6')# 結果# in_dec()= (1, 2, 3, 4, 5)# in my_sum# 15# in_dec()= (1, 2, 3, 4, 5, '6')# 0
正確使用閉包,就要確保引用的局部變量在函數返回後不能變。
返回函數不要引用任何循環變量,或者後續會發生變化的變量。
# 希望一次返回3個函數,分別計算1x1,2x2,3x3:def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fsf1, f2, f3 = count()print f1(),f2(),f3() #9 9 9#當count()函數返回了3個函數時,這3個函數所引用的變量 i 的值已經變成了3。由於f1、f2、f3並沒有被調用,所以,此時他們並未計算 i*i,當 f1 被調用時,才計算i*i,但現在i的值已經變為3#正確如下def count(): fs = [] for i in range(1, 4): def f(j): def g(): return j*j return g r = f(i) fs.append(r) return fsf1, f2, f3 = count()print f1(), f2(), f3() #1 4 9
8、匿名函數lambda
def f(x): return x*xprint map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) #[1, 4, 9, 16, 25, 36, 49, 64, 81]print map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]) #[1, 4, 9, 16, 25, 36, 49, 64, 81]
通過對比可以看出,匿名函數 lambda x: x * x 實際上就是:
def f(x):
return x * x
關鍵字lambda表示匿名函數,冒號前面的x 表示函數參數。
匿名函數有個限制,就是只能有一個表達式,不寫return,返回值就是該表達式的結果。
使用匿名函數,可以不必定義函數名,直接創建一個函數對象,很多時候可以簡化代碼:
print sorted([1, 3, 9, 5, 0], lambda x,y: -cmp(x,y)) #[9, 5, 3, 1, 0]
返回函數的時候,也可以返回匿名函數:
myabs = lambda x: -x if x < 0 else xprint myabs(-1) #1print myabs(1) #1
(6)裝飾器
1、decorator本質上就是一個高階函數,它接收一個函數作為參數,然後,返回一個新函數。
使用 decorator 用Python提供的@語法,這樣可以避免手動編寫f=decorate(f)這樣的代碼。
2、裝飾器用來裝飾函數,返回一個函數對象
被裝飾函數標識符指向返回的函數對象
def dec(func): print "call dec" def in_dec(*arg): print "in_dec()=",arg if len(arg) == 0: return 0 for val in arg: if not isinstance(val, int): return 0 return func(*arg) return in_dec #別加括號@dec # 代替了my_sum = dec(my_sum)def my_sum(*arg): #my_sum = in_dec print "in my_sum" return sum(arg)print my_sum(1,2,3,4,5)# call dec# in_dec()= (1, 2, 3, 4, 5)# in my_sum# 15
3、傳入函數,含有兩個參數
def deco(func): def in_deco(x,y): print "in deco" func(x,y) print "call deco" return in_deco@deco #代替 bar = deco(bar) = in_deco #bar()-> in_deco()->bar()def bar(x,y): print "in bar",x+ybar(1,2)# call deco# in deco# in bar
4、@log的定義
def log(f): def fn(x): print 'call ' + f.__name__ + '()...' return f(x) return fn@logdef factorial(n): return reduce(lambda x,y: x*y, range(1, n+1))print factorial(10)# call factorial()...# 3628800
但是,對於參數不是一個的函數,調用將報錯。@log寫死了只含一個參數的返回函數。
5、要讓@log自適應任何參數定義的函數,可以利用Python的*args和**kw,保證任意個數的參數總是能正常調用:
可變參數*args表示任何多個無名參數,它是一個tuple;**kwargs表示關鍵字參數,它是一個dict。並且同時使用*args和**kwargs時,必須*args參數列要在**kwargs前。
def log(f): def fn(*args, **kw): print 'call ' + f.__name__ + '()...' return f(*args, **kw) return fn@logdef add(x, y): return x + yprint add(1, 2)# call add()...# 3
6、@performance,它可以列印出函數調用的時間。
計算函數調用的時間可以記錄調用前後的當前時間戳,然後計算兩個時間戳的差。
import timedef performance(f): def fn(*args, **kw): t1 = time.time() r = f(*args, **kw) t2 = time.time() print 'call %s() in %fs' % (f.__name__, (t2 - t1)) return r return fn@performancedef factorial(n): return reduce(lambda x,y: x*y, range(1, n+1))print factorial(5)# call factorial() in 0.000000s# 120
7、對於被裝飾的函數,log列印的語句是不能變的(除了函數名)。
如果有的函數非常重要,希望列印出'[INFO] call xxx()...',有的函數不太重要,希望列印出'[DEBUG] call xxx()...',這時,log函數本身就需要傳入'INFO'或'DEBUG'這樣的參數:
@log('DEBUG')def my_func(): pass#把上面的定義翻譯成高階函數的調用,就是:my_func = log('DEBUG')(my_func)#上面的語句看上去還是比較繞,再展開一下:log_decorator = log('DEBUG')my_func = log_decorator(my_func)#上面的語句又相當於:log_decorator = log('DEBUG')@log_decoratordef my_func(): pass
所以,帶參數的log函數首先返回一個decorator函數,再讓這個decorator函數接收my_func並返回新函數:
而且wrapper(*args, **kw)要調用外層參數prefix,所以無法拆開
def log(prefix): def log_decorator(f): def wrapper(*args, **kw): print '[%s] %s()...' % (prefix, f.__name__) return f(*args, **kw) return wrapper return log_decorator@log('DEBUG')def test(): passprint test()# [DEBUG] test()...# None
8、分別
#在沒有decorator的情況下,列印函數名:def f1(x): passprint f1.__name__ #f1#有decorator的情況下,再列印函數名:def log(f): def wrapper(*args, **kw): print 'call...' return f(*args, **kw) return wrapper@logdef f2(x): passprint f2.__name__ #wrapper
可見,由於decorator返回的新函數函數名已經不是'f2',而是@log內部定義的'wrapper'。這對於那些依賴函數名的代碼就會失效。decorator還改變了函數的__doc__等其它屬性。如果要讓調用者看不出一個函數經過了@decorator的「改造」,就需要把原函數的一些屬性複製到新函數中:
def log(f): def wrapper(*args, **kw): print 'call...' return f(*args, **kw) wrapper.__name__ = f.__name__ wrapper.__doc__ = f.__doc__ return wrapper
這樣寫decorator很不方便,因為我們也很難把原函數的所有必要屬性都一個一個複製到新函數上,所以Python內置的functools可以用來自動化完成這個「複製」的任務:
import functoolsdef log(f): @functools.wraps(f) def wrapper(*args, **kw): print 'call...' return f(*args, **kw) return wrapper@logdef f2(x): passprint f2.__name__ #f2
9、當一個函數有很多參數時,調用者就需要提供多個參數。如果減少參數個數,就可以簡化調用者的負擔。
比如,int()函數可以把字符串轉換為整數,當僅傳入字符串時,int()函數默認按十進位轉換:
但int()函數也提供額外的base參數,默認為10。如果傳入base參數,就可以做N進位轉換:
print int("10") #10print int('10', 8) #8print int('A', 16) #10
假設要轉換大量的二進位字符串,每次都傳入int(x, base=2)非常麻煩,於是,我們想到,可以定義一個int2()的函數,默認把base=2傳進去:
def int2(x, base=2): return int(x, base)print int2('1000000') #64print int2('1010101') #85
functools.partial就是幫助我們創建一個偏函數的,不需要我們自己定義int2(),可以直接使用下面的代碼創建一個新的函數int2:
import functoolsint2 = functools.partial(int, base=2)print int2('1000000') #64print int2('1010101') #85
所以,functools.partial可以把一個參數多的函數變成一個參數少的新函數,少的參數需要在創建時指定默認值,這樣,新函數調用的難度就降低了。
(7)參數
1、位置參數必須以在被調用函數中定義的準確順序來傳遞,參數數目必須一致。
2、所有必需的參數都要在默認參數之前。
# 位置參數def func_with_parameters(x, y): print(x, y)func_with_parameters(1, 2)#默認值參數def func_with_default_value_parameters(x, y, z = 3): print(x, y, z)func_with_default_value_parameters(y = 2, x = 1)
3、如果命名了參數,這裡可以不按順序給出參數。
#命名參數def func_with_named_parameters(x, y, z): print(x, y, z)func_with_named_parameters(z = 1, y = 2, x = 3)
4、變長的參數在函數聲明中不是顯式命名的,因為參數的數目在運行時之前是未知的(甚至在運行的期間,每次函數調用的參數的數目也可能是不同的),這和常規參數(位置和默認)明顯不同,常規參數都是在函數聲明中命名的。由於函數調用提供了關鍵字以及非關鍵字兩種參數類型,python 用兩種方法來支持變長參數。
func(*tuple_grp_nonkw_args, **dict_grp_kw_args)
其中的 tuple_grp_nonkw_args 是以元組形式體現的非關鍵字參數組, dict_grp_kw_args 是裝有關鍵字參數的字典。
5、可變長的參數元組必須在位置和默認參數之後。
# 收集多餘的位置參數def func_with_collection_rest_parameters(x, y=0, *rest): print(x, y) print(rest)func_with_collection_rest_parameters(1, 2, 3, 4, 5)
星號操作符之後的形參將作為元組傳遞給函數,元組保存了所有傳遞給函數的"額外"的參數(匹配了所有位置和具名參數後剩餘的)。如果沒有給出額外的參數,元組為空。
6、關鍵字變量參數(Dictionary)
在我們有不定數目的或者額外集合的關鍵字的情況中, 參數被放入一個字典中,字典中鍵為參數名,值為相應的參數值。
#收集命名參數
def func_with_collection_rest_naned_parameters(*args, **kw):
print(args)
print(kw)
func_with_collection_rest_naned_parameters(1, 2, 3, x = 4, y = 5, z = 6)
func_with_collection_rest_naned_parameters([1, 2, 3], {"x": 4, "y": 4, "z": 6})
#這會導致args[0]指向第一個實參,args[1]指向第二個實參。
#([1, 2, 3], {'y': 4, 'x': 4, 'z': 6})
#{}
func_with_collection_rest_naned_parameters(*[1, 2, 3], **{"x": 4, "y": 4, "z": 6})
#這裡的執行相當於func_with_collection_rest_naned_parameters(1, 2, 3, x = 4, y = 5, z = 6)。
(8)面向對象
1、類通過class關鍵字定義。類名以大寫字母開頭,緊接著是(object),表示該類是從哪個類繼承下來的。
類也要細緻命名,像「AddrBookEntry」,「RepairShop」等等就是很好的名字
Python 並不支持純虛函數(像 C++)或者抽象方法(如在 JAVA 中)
class Person(object):
pass
2、有了Person類的定義,就可以創建出具體的xiaoming、xiaohong等實例。創建實例使用類名+(),類似函數調用的形式創建:
Python 規範推薦使用駱駝記法的下劃線方式,比如,「update_phone」「update_email」。
xiaoming = Person()
xiaohong = Person()
3、由於Python是動態語言,對每一個實例,都可以直接給他們的屬性賦值:
xiaoming = Person()
xiaoming.name = 'Xiao Ming'
xiaoming.gender = 'Male'
xiaoming.birth = '1990-1-1'
4、構造函數__init__()方法
class Person(object):
def __init__(self, name, gender, birth):
self.name = name
self.gender = gender
self.birth = birth
__init__()方法的第一個參數必須是self(也可以用別的名字,但建議使用習慣用法),後續參數則可以自由指定,和定義函數沒有任何分別。
相應地,創建實例時,就必須要提供除self以外的參數:
xiaoming = Person('Xiao Ming', 'Male', '1991-1-1')
xiaohong = Person('Xiao Hong', 'Female', '1992-2-2')
print xiaoming.name # 輸出 'Xiao Ming'
print xiaohong.birth # 輸出 '1992-2-2'
定義Person類的__init__方法,除了接受 name、gender 和 birth 外,還可接受任意關鍵字參數,並把他們都作為屬性賦值給實例。
要定義關鍵字參數,使用 **kw;
除了可以直接使用self.name = 'xxx'設置一個屬性外,還可以通過 setattr(self, 'name', 'xxx') 設置屬性。
class Person(object): def __init__(self, name, gender, birth, **kw): self.name = name self.gender = gender self.birth = birth for k, v in kw.iteritems(): setattr(self, k, v)xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')print xiaoming.name #輸出Xiao Mingprint xiaoming.job #輸出Student
5、析構函數
由於 Python 具有垃圾對象回收機制(靠引用計數),這個函數要直到該實例對象所有的引用都被清除掉後才會執行。所以很少用到。
class Person(object):
def __init__(self, ……):
6、Python對屬性權限的控制是通過屬性名來實現的,如果一個屬性由雙下劃線開頭(__),該屬性就無法被外部訪問。
class Person(object): def __init__(self, name): self.name = name self._title = 'Mr' self.__job = 'Student'p = Person('Bob')print p.name # => Bobprint p._title # => Mrprint p._Person__job # => Student #所以實際上並不是嚴格的私有成員print p.__job # => Error
但是,如果一個屬性以"__xxx__"的形式定義,那它又可以被外部訪問了,以"__xxx__"定義的屬性在Python的類中被稱為特殊屬性,有很多預定義的特殊屬性可以使用,通常我們不要把普通屬性用"__xxx__"定義。
以單下劃線開頭的屬性"_xxx"可以在子類中使用,不應該被外部訪問,理解為保護成員。
"__xxx"可以理解為私有成員,但實質並不是,不建議訪問。
7、類屬性是直接綁定在類上的,所以,訪問類屬性不需要創建實例,就可以直接訪問:
class Person(object): address = 'Earth' def __init__(self, name): self.name = namep1=Person(xiaoming)print Person.address # => Earthprint p1.address # => Earth# 由於Python是動態語言,類屬性也是可以動態添加和修改的:Person.address = 'China'print p1.address # => 'China'
8、在實例變量上修改類屬性
當實例屬性和類屬性重名時,實例屬性優先級高,它將屏蔽掉對類屬性的訪問。而其他不變
9、訪問類的屬性
有兩種方法。最簡單的是使用 dir()內建函數。另外是通過訪問類的字典屬性__dict__,這是所有類都具備的特殊屬性之一。
10、實例的方法。
實例的方法就是在類中定義的函數,它的第一個參數永遠是self,指向調用該方法的實例本身,其他參數和一個普通函數是完全一樣的:在其他語言中,self就是this.
class Person(object):