Author:ProZoom
Hobby:愛折騰、愛思考,想靜靜的ProZoom
Github --- 簡書 --- CSDN --- 關于我
由于Python官網說2.幾版本的到2020年將停止更新,所以本教程只基于Mac平臺的Python3以上的版本進行編寫,Window平臺暫未編寫,不過大同小異,敬請諒解!---ProZoom
Python程序是大小寫敏感的
#開頭的語句是注釋,注釋是給人看的
每一行都是一個語句,當語句以冒號:結尾時,縮進的語句視為代碼塊
數據類型和變量
數據類型
在Python中,能夠直接處理的數據類型有以下幾種:
整數
Python可以處理任意大小的整數,當然包括負整數,在程序中的表示方法和數學上的寫法一模一樣,例如:1,100,-8080,0,等等。
計算機由于使用二進制,所以,有時候用十六進制表示整數比較方便,十六進制用0x前綴和0-9,a-f表示,例如:0xff00,0xa5b4c3d2,等等。
浮點數
浮點數也就是小數,之所以稱為浮點數,是因為按照科學記數法表示時,一個浮點數的小數點位置是可變的,比如,1.23x109和12.3x108是完全相等的。浮點數可以用數學寫法,如1.23,3.14,-9.01,等等。但是對于很大或很小的浮點數,就必須用科學計數法表示,把10用e替代,1.23x109就是1.23e9,或者12.3e8,0.000012可以寫成1.2e-5,等等。
整數和浮點數在計算機內部存儲的方式是不同的,整數運算永遠是精確的(除法難道也是精確的?是的!),而浮點數運算則可能會有四舍五入的誤差。
字符串
字符串是以單引號'或雙引號"括起來的任意文本,比如'abc',"xyz"等等。請注意,''或""本身只是一種表示方式,不是字符串的一部分,因此,字符串'abc'只有a,b,c這3個字符。如果'本身也是一個字符,那就可以用""括起來,比如"I'm OK"包含的字符是I,',m,空格,O,K這6個字符。
如果字符串內部既包含'又包含"怎么辦?可以用轉義字符\來標識,比如:
'I\'m \"OK\"!'
表示的字符串內容是:
I'm "OK"!
轉義字符\可以轉義很多字符,如下圖所示:
轉義字符 | 解釋 |
---|---|
\n | 換行 |
\t | 制表符 |
\\ | \ |
r'' | ''內部的字符串默認不轉義 |
'''...''' | 多行內容 |
r'''...''' | r無效 |
測試:
布爾值
布爾值和布爾代數的表示完全一致,一個布爾值只有True、False兩種值,要么是True,要么是False,在Python中,可以直接用True、False表示布爾值(請注意大小寫),也可以通過布爾運算計算出來:
>>> True
True
>>> not True
False
>>> False
False
>>> not False
True
>>> 3>2
True
>>> 2>3
False
>>>
布爾值可以用and、or和not運算。
and運算是與運算,只有所有都為True,and運算結果才是True:
>>> True and True
True
>>> True and False
False
>>> False and False
False
>>> 3>2 and 2>3
False
or運算是或運算,只要其中有一個為True,or運算結果就是True:
>>> True or False
True
>>> True or True
True
>>> False or False
False
not運算是非運算,它是一個單目運算符,把True變成False,False變成True:
>>> not True
False
>>> not False
True
>>> not 1 > 2
True
布爾值經常用在條件判斷中,比如:
if age >= 18:
print('adult')
else:
print('teenager')
空值
空值是Python里一個特殊的值,用None表示。None不能理解為0,因為0是有意義的,而None是一個特殊的空值。
此外,Python還提供了列表、字典等多種數據類型,還允許創建自定義數據類型,我們后面會繼續講到。
變量
變量的概念基本上和初中代數的方程變量是一致的,只是在計算機程序中,變量不僅可以是數字,還可以是任意數據類型。
變量在程序中就是用一個變量名表示了,變量名必須是大小寫英文、數字和_的組合,且不能用數字開頭,比如:
a = 2 #變量a是一個整數。
t_007 = 'T007' #變量t_007是一個字符串。
Answer = True #變量Answer是一個布爾值True。
在Python中,等號=是賦值語句(和其他語言不同),可以把任意數據類型賦值給變量,同一個變量可以反復賦值,而且可以是不同類型的變量,例如:
a = 123 # a是整數
print(a)
a = 'ABC' # a變為字符串
print(a)
這種變量本身類型不固定的語言稱之為動態語言,與之對應的是靜態語言。靜態語言在定義變量時必須指定變量類型,如果賦值的時候類型不匹配,就會報錯。例如Java是靜態語言。
和靜態語言相比,動態語言更靈活,就是這個原因。
請不要把賦值語句的等號等同于數學的等號。比如下面的代碼:
x = 8
x = x + 2
如果從數學上理解x = x + 2那無論如何是不成立的,在程序中,賦值語句先計算右側的表達式x + 2,得到結果12,再賦給變量x。由于x之前的值是8,重新賦值后,x的值變成10。
最后,理解變量在計算機內存中的表示也非常重要。當我們寫:
a = 'ABC'
Python解釋器干了兩件事情:
1.在內存中創建了一個'ABC'的字符串;
2.在內存中創建了一個名為a的變量,并把它指向'ABC'。
也可以把一個變量a賦值給另一個變量b,這個操作實際上是把變量b指向變量a所指向的數據,例如下面的代碼:
a = 'ABC' #解釋器創建了字符串'ABC'和變量a,并把a指向'ABC'
b = a #解釋器創建了字符串'XYZ',并把a的指向改為'XYZ',但b并沒有更改:
a = 'XYZ' #解釋器創建了變量b,并把b指向a指向的字符串'ABC'
print(b)
b的值是'ABC'
常量
所謂常量就是不能變的變量,比如常用的數學常數π就是一個常量。在Python中,通常用全部大寫的變量名表示常量:
PI = 3.14159265359
但事實上PI仍然是一個變量,Python根本沒有任何機制保證PI不會被改變,所以,用全部大寫的變量名表示常量只是一個習慣上的用法,如果你一定要改變變量PI的值,也沒人能攔住你。
最后解釋一下整數的除法為什么也是精確的。在Python中,有兩種除法,一種除法是/:
>>> 10 / 3
3.3333333333333335
#除法計算結果是浮點數,即使是兩個整數恰好整除,結果也是浮點數
>>> 9 / 3
3.0
還有一種除法是//,稱為地板除(就是數學里的取整函數),兩個整數的除法仍然是整數:
>>> 10 // 3
3
>>> 14//3
4
你沒有看錯,整數的地板除//永遠是整數,即使除不盡。要做精確的除法,使用/就可以。
因為//除法只取結果的整數部分,所以Python還提供一個余數運算,可以得到兩個整數相除的余數:
>>> 10 % 3
1
無論整數做//除法還是取余數,結果永遠是整數,所以,整數運算結果永遠是精確的。
字符串和編碼
Python的字符串
在最新的Python 3版本中,字符串是以Unicode編碼的,也就是說,Python的字符串支持多語言,例如:
>>> print('中文字符串')
對于單個字符的編碼,Python提供了ord()函數獲取字符的整數表示,chr()函數把編碼轉換為對應的字符:
>>> ord('A')
65
>>> ord('中')
20013
>>> chr(66)
'B'
>>> chr(25991)
'文'
如果知道字符的整數編碼,還可以用十六進制這么寫str:
>>> '\u4e2d\u6587'
'中文'
兩種寫法完全是等價的。
由于Python的字符串類型是str,在內存中以Unicode表示,一個字符對應若干個字節。如果要在網絡上傳輸,或者保存到磁盤上,就需要把str變為以字節為單位的bytes。
Python對bytes類型的數據用帶b前綴的單引號或雙引號表示:
x = b'ABC'
要注意區分'ABC'和b'ABC',前者是str,后者雖然內容顯示得和前者一樣,但bytes的每個字符都只占用一個字節。
使用list和tuple
list
Python內置的一種數據類型是列表:list。list是一種有序的集合,可以隨時添加和刪除其中的元素。
比如,列出班里所有同學的名字,就可以用一個list表示:
>>> class = ['one', 'two', 'three']
>>> class
['one', 'two', 'three']
變量class就是一個list。用len()函數可以獲得list元素的個數:
>>> len(class)
3
用索引來訪問list中每一個位置的元素,記得索引是從0開始的:
>>> class[0]
'one'
>>> class[1]
'two'
>>> class[2]
'three'
>>> class[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
當索引超出了范圍時,Python會報一個IndexError錯誤,所以,要確保索引不要越界,記得最后一個元素的索引是len(class) - 1。
如果要取最后一個元素,除了計算索引位置外,還可以用-1做索引,直接獲取最后一個元素:
>>> class[-1]
'three'
以此類推,可以獲取倒數第2個、倒數第3個:
>>> class[-2]
'two'
>>> class[-3]
'one'
>>> class[-4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
當然,倒數第4個就越界了。
list是一個可變的有序表,所以,可以往list中追加元素到末尾:
>>> class.append('for')
>>> class
['one', 'two', 'three', 'for']
也可以把元素插入到指定的位置,比如索引號為1的位置:
>>> class.insert(1, 'five')
>>> class
['one', 'five', 'two', 'three', 'for']
要刪除list末尾的元素,用pop()方法:
>>> class.pop()
'for'
>>> class
['one', 'five', 'two', 'three']
要刪除指定位置的元素,用pop(i)方法,其中i是索引位置:
>>> class.pop(1)
'Jack'
>>> class
['one', 'three','for']
要把某個元素替換成別的元素,可以直接賦值給對應的索引位置:
>>> class[1] = 'five'
>>> class
['one', 'five', 'three']
list里面的元素的數據類型也可以不同,比如:
>>> L = ['Apple', 123, True]
list元素也可以是另一個list,比如:
>>> s = ['python', 'java', ['asp', 'php'], 'scheme']
>>> len(s)
4
要注意s只有4個元素,其中s[2]又是一個list,如果拆開寫就更容易理解了:
>>> p = ['asp', 'php']
>>> s = ['python', 'java', p, 'scheme']
要拿到'php'可以寫p[1]或者s[2][1],因此s可以看成是一個二維數組,類似的還有三維、四維……數組,不過很少用到。
如果一個list中一個元素也沒有,就是一個空的list,它的長度為0:
>>> L = []
>>> len(L)
0
tuple
另一種有序列表叫元組:tuple。tuple和list非常類似,但是tuple一旦初始化就不能修改,比如同樣是列出同學的名字:
>>> class = ('one', 'two', 'three')
現在,class這個tuple不能變了,它也沒有append(),insert()這樣的方法。其他獲取元素的方法和list是一樣的,你可以正常地使用class[0],class[-1],但不能賦值成另外的元素。
不可變的tuple有什么意義?因為tuple不可變,所以代碼更安全。如果可能,能用tuple代替list就盡量用tuple。
tuple的陷阱:當你定義一個tuple時,在定義的時候,tuple的元素就必須被確定下來,比如:
>>> t = (1, 2)
>>> t
(1, 2)
如果要定義一個空的tuple,可以寫成():
>>> t = ()
>>> t
()
但是,要定義一個只有1個元素的tuple,如果你這么定義:
>>> t = (1)
>>> t
1
定義的不是tuple,是1這個數!這是因為括號()既可以表示tuple,又可以表示數學公式中的小括號,這就產生了歧義,因此,Python規定,這種情況下,按小括號進行計算,計算結果自然是1。
所以,只有1個元素的tuple定義時必須加一個逗號,,來消除歧義:
>>> t = (1,)
>>> t
(1,)
Python在顯示只有1個元素的tuple時,也會加一個逗號,,以免你誤解成數學計算意義上的括號。
最后來看一個“可變的”tuple:
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
表面上看,tuple的元素確實變了,但其實變的不是tuple的元素,而是list的元素。tuple一開始指向的list并沒有改成別的list,所以,tuple所謂的“不變”是說,tuple的每個元素,指向永遠不變。即指向'a',就不能改成指向'b',指向一個list,就不能改成指向其他對象,但指向的這個list本身是可變的!
理解了“指向不變”后,要創建一個內容也不變的tuple怎么做?那就必須保證tuple的每一個元素本身也不能變。
條件判斷
if語句
age = 20
if age >= 18:
print('your age is', age)
print('adult')
if--else語句
age = 13
if age >= 18:
print('your age is', age)
print('adult')
else:
print('your age is', age)
print('teenager')
if-elif-else語句
age = 3
if age >= 18:
print('adult')
elif age >= 6:
print('teenager')
else:
print('kid')
總結
if <條件判斷1>:
<執行1>
elif <條件判斷2>:
<執行2>
elif <條件判斷3>:
<執行3>
else:
<執行4>
循環
for...in循環
依次把list或tuple中的每個元素迭代出來
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
while循環
只要條件滿足,就不斷循環,條件不滿足時退出循環。比如我們要計算100以內所有奇數之和,可以用while循環實現
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)
在循環內部變量n不斷自減,直到變為-1時,不再滿足while條件,循環退出
break
在循環中,break語句可以提前退出循環
continue
在循環過程中,也可以通過continue語句,跳過當前的這次循環,直接開始下一次循環
使用dict和set
dict
Python內置了字典:dict的支持,dict全稱dictionary,在其他語言中也稱為map,使用鍵-值(key-value)存儲,具有極快的查找速度。
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95
為什么dict查找速度這么快?因為dict的實現原理和查字典是一樣的。假設字典包含了1萬個漢字,我們要查某一個字,一個辦法是把字典從第一頁往后翻,直到找到我們想要的字為止,這種方法就是在list中查找元素的方法,list越大,查找越慢。
第二種方法是先在字典的索引表里(比如部首表)查這個字對應的頁碼,然后直接翻到該頁,找到這個字。無論找哪個字,這種查找速度都非常快,不會隨著字典大小的增加而變慢。
dict就是第二種實現方式,給定一個名字,比如'Michael',dict在內部就可以直接計算出Michael對應的存放成績的“頁碼”,也就是95這個數字存放的內存地址,直接取出來,所以速度非常快。
你可以猜到,這種key-value存儲方式,在放進去的時候,必須根據key算出value的存放位置,這樣,取的時候才能根據key直接拿到value。
要避免key不存在的錯誤,有兩種辦法,
一是通過in判斷key是否存在:
>>> 'Thomas' in d
False
二是通過dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value:
>>> d.get('Thomas')
>>> d.get('Thomas', -1)
-1
注意:返回None的時候Python的交互式命令行不顯示結果。
要刪除一個key,用pop(key)方法,對應的value也會從dict中刪除:
>>> d.pop('Bob')
75
>>> d
{'Michael': 95, 'Tracy': 85}
和list比較,dict有以下幾個特點:
查找和插入的速度極快,不會隨著key的增加而變慢;
需要占用大量的內存,內存浪費多。
而list相反:
查找和插入的時間隨著元素的增加而增加;
占用空間小,浪費內存很少。
所以,dict是用空間來換取時間的一種方法。
set
set和dict類似,也是一組key的集合,但不存儲value。由于key不能重復,所以,在set中,沒有重復的key。
要創建一個set,需要提供一個list作為輸入集合:
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}
注意,傳入的參數[1, 2, 3]是一個list,而顯示的{1, 2, 3}只是告訴你這個set內部有1,2,3這3個元素,顯示的順序也不表示set是有序的。。
重復元素在set中自動被過濾:
>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
{1, 2, 3}
通過add(key)方法可以添加元素到set中,可以重復添加,但不會有效果:
>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.add(4)
>>> s
{1, 2, 3, 4}
通過remove(key)方法可以刪除元素:
>>> s.remove(4)
>>> s
{1, 2, 3}
set可以看成數學意義上的無序和無重復元素的集合,因此,兩個set可以做數學意義上的交集、并集等操作:
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}