Python入門

本篇文章全部copy自廖雪峰老師的Python入門教程,僅供學習用
教程鏈接:Python入門

數據類型

整數

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

浮點數

1.23x109和12.3x108是相等的。浮點數可以用數學寫法尿这,如1.23,3.14,-9.01急凰,等等。但是對于很大或很小的浮點數猜年,就必須用科學計數法表示抡锈,把10用e替代,1.23x10^9就是1.23e9乔外,或者12.3e8床三,0.000012可以寫成1.2e-5,等等杨幼。

整數和浮點數在計算機內部存儲的方式是不同的撇簿,整數運算永遠是精確的(除法難道也是精確的聂渊?是的!)四瘫,而浮點數運算則可能會有四舍五入的誤差汉嗽。

字符串

是以''和""括起來的任意文本

布爾值

一個布爾值只有True和False,布爾值可以用and、or和not運算找蜜。

and運算是與運算饼暑,只有所有都為 True,and運算結果才是 True洗做。

or運算是或運算弓叛,只要其中有一個為 True,or 運算結果就是 True诚纸。

not運算是非運算撰筷,它是一個單目運算符,把 True 變成 False畦徘,False 變成 True毕籽。

空值

None表示

其它

py還提供了列表,字典等多種數據類型井辆,還允許自定義數據類型影钉。

Python2 里面print可以直接接字符串或者運算。

Python3 里面print變成了一個函數掘剪,上面的寫法不支持了,必須用一個括號括起來奈虾,否則會報告語法錯誤夺谁。

print語句

1.當我們在Python交互式環(huán)境下編寫代碼時,>>>是Python解釋器的提示符肉微,不是代碼的一部分匾鸥。

2.當我們在文本編輯器中編寫代碼時,千萬不要自己添加 >>>碉纳。

print語句也可以跟上多個字符串勿负,用逗號“,”隔開,就可以連成一串輸出:

>>> print 'The quick brown fox', 'jumps over', 'the lazy dog'
The quick brown fox jumps over the lazy dog

print會依次打印每個字符串劳曹,遇到逗號“,”會輸出一個空格奴愉,因此,輸出的字符串是這樣拼起來的:

print

print也可以打印整數铁孵,或者計算結果:

>>> print 300
300    #運行結果
>>> print 100 + 200
300    #運行結果

注釋

以#開頭锭硼,后面的文字直到行尾都算注釋

變量

在Python程序中,變量是用一個變量名表示蜕劝,變量名必須是大小寫英文檀头、數字和下劃線(_)的組合轰异,且不能用數字開頭,比如:

a = 1
變量a是一個整數暑始。

t_007 = 'T007'
變量t_007是一個字符串搭独。

在Python中,等號=是賦值語句廊镜,可以把任意數據類型賦值給變量牙肝,同一個變量可以反復賦值,而且可以是不同類型的變量期升,例如:

a = 123 # a是整數
print a
a = 'imooc' # a變?yōu)樽址?br> print a
這種變量本身類型不固定的語言稱之為動態(tài)語言惊奇,與之對應的是靜態(tài)語言。靜態(tài)語言在定義變量時必須指定變量類型播赁,如果賦值的時候類型不匹配颂郎,就會報錯。例如Java是靜態(tài)語言

最后容为,理解變量在計算機內存中的表示也非常重要乓序。當我們寫:a = 'ABC'時,Python解釋器干了兩件事情:

  1. 在內存中創(chuàng)建了一個'ABC'的字符串坎背;

  2. 在內存中創(chuàng)建了一個名為a的變量替劈,并把它指向'ABC'。

也可以把一個變量a賦值給另一個變量b得滤,這個操作實際上是把變量b指向變量a所指向的數據陨献,例如下面的代碼:

a = 'ABC'
b = a
a = 'XYZ'
print b

執(zhí)行過程

字符串

前面我們講解了什么是字符串。字符串可以用''或者""括起來表示懂更。

如果字符串本身包含'怎么辦眨业?比如我們要表示字符串 I'm OK ,這時沮协,可以用" "括起來表示:

"I'm OK"
類似的龄捡,如果字符串包含",我們就可以用' '括起來表示:

'Learn "Python" in imooc'

如果字符串既包含'又包含"怎么辦慷暂?

這個時候聘殖,就需要對字符串的某些特殊字符進行“轉義”,Python字符串用\進行轉義行瑞。

要表示字符串 Bob said "I'm OK".
由于 ' 和 " 會引起歧義奸腺,因此,我們在它前面插入一個\表示這是一個普通字符血久,不代表字符串的起始洋机,因此,這個字符串又可以表示為

'Bob said "I'm OK".'
注意:轉義字符 \ 不計入字符串的內容中洋魂。

常用的轉義字符還有:

\n 表示換行
\t 表示一個制表符
\ 表示 \ 字符本身

raw字符串與多行字符串

如果一個字符串包含很多需要轉義的字符绷旗,對每一個字符都進行轉義會很麻煩喜鼓。為了避免這種情況,我們可以在字符串前面加個前綴 r 衔肢,表示這是一個 raw 字符串庄岖,里面的字符就不需要轉義了。例如:

r'(_)/ (_)/'

但是r'...'表示法不能表示多行字符串角骤,也不能表示包含'和 "的字符串(為什么隅忿?)

如果要表示多行字符串,可以用'''...'''表示:

'''Line 1
Line 2
Line 3'''

上面這個字符串的表示方法和下面的是完全一樣的:

'Line 1\nLine 2\nLine 3'
還可以在多行字符串前面添加 r 邦尊,把這個多行字符串也變成一個raw字符串:

r'''Python is created by "Guido".
It is free and easy to learn.
Let's start learn Python in imooc!'''

Unicode字符串

因為計算機只能處理數字背桐,如果要處理文本,就必須先把文本轉換為數字才能處理蝉揍。最早的計算機在設計時采用8個比特(bit)作為一個字節(jié)(byte)链峭,所以,一個字節(jié)能表示的最大的整數就是255(二進制11111111=十進制255)又沾,0 - 255被用來表示大小寫英文字母弊仪、數字和一些符號,這個編碼表被稱為ASCII編碼杖刷,比如大寫字母 A 的編碼是65励饵,小寫字母 z 的編碼是122。

如果要表示中文滑燃,顯然一個字節(jié)是不夠的役听,至少需要兩個字節(jié),而且還不能和ASCII編碼沖突表窘,所以典予,中國制定了GB2312編碼,用來把中文編進去蚊丐。

類似的,日文和韓文等其他語言也有這個問題艳吠。為了統(tǒng)一所有文字的編碼,Unicode應運而生。Unicode把所有語言都統(tǒng)一到一套編碼里搓彻,這樣就不會再有亂碼問題了峦甩。

Unicode通常用兩個字節(jié)表示一個字符,原有的英文編碼從單字節(jié)變成雙字節(jié)栏渺,只需要把高字節(jié)全部填為0就可以呛梆。

因為Python的誕生比Unicode標準發(fā)布的時間還要早,所以最早的Python只支持ASCII編碼磕诊,普通的字符串'ABC'在Python內部都是ASCII編碼的填物。

Python在后來添加了對Unicode的支持纹腌,以Unicode表示的字符串用u'...'表示,比如:

print u'中文'
中文
注意: 不加 u 滞磺,中文就不能正常顯示升薯。
Unicode字符串除了多了一個 u 之外,與普通字符串沒啥區(qū)別击困,轉義字符和多行表示法仍然有效:

轉義:

u'中文\n日文\n韓文'
多行:

u'''第一行
第二行'''
raw+多行:

ur'''Python的Unicode字符串支持"中文",
"日文",
"韓文"等多種語言'''
如果中文字符串在Python環(huán)境下遇到 UnicodeDecodeError涎劈,這是因為.py文件保存的格式有問題≡牟瑁可以在第一行添加注釋

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

目的是告訴Python解釋器蛛枚,用UTF-8編碼讀取源代碼。然后用Notepad++ 另存為... 并選擇UTF-8格式保存脸哀。

整數和浮點數

Python支持對整數和浮點數直接進行四則混合運算蹦浦,運算規(guī)則和數學上的四則運算規(guī)則完全一致。

基本的運算:

1 + 2 + 3 # ==> 6
4 * 5 - 6 # ==> 14
7.5 / 8 + 2.1 # ==> 3.0375
使用括號可以提升優(yōu)先級企蹭,這和數學運算完全一致白筹,注意只能使用小括號,但是括號可以嵌套很多層:

(1 + 2) * 3 # ==> 9
(2.2 + 3.3) / (1.5 * (9 - 0.3)) # ==> 0.42145593869731807
和數學運算不同的地方是谅摄,Python的整數運算結果仍然是整數徒河,浮點數運算結果仍然是浮點數:

1 + 2 # ==> 整數 3
1.0 + 2.0 # ==> 浮點數 3.0
但是整數和浮點數混合運算的結果就變成浮點數了:

1 + 2.0 # ==> 浮點數 3.0
為什么要區(qū)分整數運算和浮點數運算呢?這是因為整數運算的結果永遠是精確的送漠,而浮點數運算的結果不一定精確顽照,因為計算機內存再大,也無法精確表示出無限循環(huán)小數闽寡,比如 0.1 換成二進制表示就是無限循環(huán)小數代兵。

那整數的除法運算遇到除不盡的時候,結果難道不是浮點數嗎爷狈?我們來試一下:

11 / 4 # ==> 2
令很多初學者驚訝的是植影,Python的整數除法,即使除不盡涎永,結果仍然是整數思币,余數直接被扔掉。不過羡微,Python提供了一個求余的運算 % 可以計算余數:

11 % 4 # ==> 3
如果我們要計算 11 / 4 的精確結果谷饿,按照“整數和浮點數混合運算的結果是浮點數”的法則,把兩個數中的一個變成浮點數再運算就沒問題了:

11.0 / 4 # ==> 2.75

布爾類型

布爾類型只有True和False兩種值妈倔,但是布爾類型有以下幾種運算:

與運算:只有兩個布爾值都為 True 時博投,計算結果才為 True。

True and True # ==> True
True and False # ==> False
False and True # ==> False
False and False # ==> False
或運算:只要有一個布爾值為 True盯蝴,計算結果就是 True毅哗。

True or True # ==> True
True or False # ==> True
False or True # ==> True
False or False # ==> False
非運算:把True變?yōu)镕alse听怕,或者把False變?yōu)門rue:

not True # ==> False
not False # ==> True
布爾運算在計算機中用來做條件判斷,根據計算結果為True或者False黎做,計算機可以自動執(zhí)行不同的后續(xù)代碼叉跛。

在Python中,布爾類型還可以與其他數據類型做 and蒸殿、or和not運算筷厘,請看下面的代碼:

a = True
print a and 'a=T' or 'a=F'
計算結果不是布爾類型,而是字符串 'a=T'宏所,這是為什么呢酥艳?

因為Python把0、空字符串''和None看成 False爬骤,其他數值和非空字符串都看成 True充石,所以:

True and 'a=T' 計算結果是 'a=T'
繼續(xù)計算 'a=T' or 'a=F' 計算結果還是 'a=T'
要解釋上述結果,又涉及到 and 和 or 運算的一條重要法則:短路計算霞玄。

  1. 在計算 a and b 時骤铃,如果 a 是 False,則根據與運算法則坷剧,整個結果必定為 False惰爬,因此返回 a;如果 a 是 True惫企,則整個計算結果必定取決與 b撕瞧,因此返回 b。

  2. 在計算 a or b 時狞尔,如果 a 是 True丛版,則根據或運算法則,整個計算結果必定為 True偏序,因此返回 a页畦;如果 a 是 False,則整個計算結果必定取決于 b研儒,因此返回 b豫缨。

所以Python解釋器在做布爾運算時,只要能提前確定計算結果殉摔,它就不會往后算了州胳,直接返回結果记焊。

創(chuàng)建List

list是數學意義上的有序集合逸月,也就是說,list中的元素是按照順序排列的遍膜。
構造list非常簡單碗硬,按照上面的代碼瓤湘,直接用 [ ] 把list的所有元素都括起來,就是一個list對象恩尾。通常弛说,我們會把list賦值給一個變量,這樣翰意,就可以通過變量來引用list:
由于Python是動態(tài)語言木人,所以list中包含的元素并不要求都必須是同一種數據類型,我們完全可以在list中包含各種數據:

>>> L = ['Michael', 100, True]
一個元素也沒有的list冀偶,就是空list:
>>> empty_list = []
  • 列表可以倒序訪問
  • append()可添加新元素到list的尾部
  • inser(0,"Paul")醒第,'Paul'將被添加到索引為 0 的位置上(也就是第一個),而原來索引為 0 的Adam同學进鸠,以及后面的所有同學稠曼,都自動向后移動一位。
  • pop()方法刪除最后一個客年,加索引可刪去索引對應的元素
  • 替換元素

創(chuàng)建tuple

tuple是另一種有序的列表霞幅,中文翻譯為“ 元組 ”。tuple 和 list 非常類似量瓜,但是司恳,tuple一旦創(chuàng)建完畢,就不能修改了榔至。

同樣是表示班里同學的名稱抵赢,用tuple表示如下:

>>> t = ('Adam', 'Lisa', 'Bart')

創(chuàng)建tuple和創(chuàng)建list唯一不同之處是用( )替代了[ ]。

現在唧取,這個 t 就不能改變了铅鲤,tuple沒有 append()方法,也沒有insert()和pop()方法枫弟。所以邢享,新同學沒法直接往 tuple 中添加,老同學想退出 tuple 也不行淡诗。

獲取 tuple 元素的方式和 list 是一模一樣的骇塘,我們可以正常使用 t[0],t[-1]等索引方式訪問元素韩容,但是不能賦值成別的元素

單元素tuple

tuple和list一樣款违,可以包含 0 個、1個和任意多個元素群凶。

包含多個元素的 tuple插爹,前面我們已經創(chuàng)建過了。

包含 0 個元素的 tuple,也就是空tuple赠尾,直接用 ()表示:

>>> t = ()
>>> print t
()

創(chuàng)建包含1個元素的 tuple 呢力穗?來試試:

>>> t = (1)
>>> print t
1

好像哪里不對!t 不是 tuple 气嫁,而是整數1当窗。為什么呢?

因為()既可以表示tuple寸宵,又可以作為括號表示運算時的優(yōu)先級崖面,結果 (1) 被Python解釋器計算出結果 1,導致我們得到的不是tuple梯影,而是整數 1嘶朱。

正是因為用()定義單元素的tuple有歧義,所以 Python 規(guī)定光酣,單元素 tuple 要多加一個逗號“,”疏遏,這樣就避免了歧義:

>>> t = (1,)
>>> print t
(1,)

Python在打印單元素tuple時,也自動添加了一個“,”救军,為了更明確地告訴你這是一個tuple财异。

多元素 tuple 加不加這個額外的“,”效果是一樣的:

>>> t = (1, 2, 3,)
>>> print t
(1, 2, 3)

if語句

age = 20
if age >= 18:
    print 'your age is', age
    print 'adult'
print 'END'

注意: Python代碼的縮進規(guī)則。具有相同縮進的代碼被視為代碼塊唱遭,上面的3戳寸,4行 print 語句就構成一個代碼塊(但不包括第5行的print)。如果 if 語句判斷為 True拷泽,就會執(zhí)行這個代碼塊疫鹊。

縮進請嚴格按照Python的習慣寫法:4個空格,不要使用Tab司致,更不要混合Tab和空格拆吆,否則很容易造成因為縮進引起的語法錯誤。

注意: if 語句后接表達式脂矫,然后用:表示代碼塊開始枣耀。

如果你在Python交互環(huán)境下敲代碼,還要特別留意縮進庭再,并且退出縮進需要多敲一行回車:

>>> age = 20
>>> if age >= 18:
...     print 'your age is', age
...     print 'adult'
...
your age is 20
adult

if else

if age >= 18:
    print 'adult'
else:
    print 'teenager'

利用 if ... else ... 語句捞奕,我們可以根據條件表達式的值為 True 或者 False ,分別執(zhí)行 if 代碼塊或者 else 代碼塊拄轻。

if ...else if...

if age >= 18:
    print 'adult'
elif age >= 6:
    print 'teenager'
elif age >= 3:
    print 'kid'
else:
    print 'baby'

for 循環(huán)

L = ['Adam', 'Lisa', 'Bart']
for name in L:
    print name

while 循環(huán)

N = 10
x = 0
while x < N:
    print x
    x = x + 1

break 退出循環(huán)

sum = 0
x = 1
while True:
    sum = sum + x
    x = x + 1
    if x > 100:
        break
print sum

繼續(xù)循環(huán)

for x in L:
    if x < 60:
        continue
    sum = sum + x
    n = n + 1

多重循環(huán)

for x in ['A', 'B', 'C']:
    for y in ['1', '2', '3']:
        print x + y

dict

這個應該是字典的意思颅围,就是鍵值對集合

d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}

可以簡單地使用 d[key] 的形式來查找對應的 value,這和 list 很像恨搓,不同之處是院促,list 必須使用索引返回對應的元素,而dict使用key:

>>> print d['Adam']
95
>>> print d['Paul']
Traceback (most recent call last):
  File "index.py", line 11, in <module>
    print d['Paul']
KeyError: 'Paul'

注意: 通過 key 訪問 dict 的value,只要 key 存在一疯,dict就返回對應的value。如果key不存在夺姑,會直接報錯:KeyError墩邀。

要避免 KeyError 發(fā)生,有兩個辦法:

一是先判斷一下 key 是否存在盏浙,用 in 操作符:

if 'Paul' in d:
    print d['Paul']

如果 'Paul' 不存在眉睹,if語句判斷為False,自然不會執(zhí)行 print d['Paul'] 废膘,從而避免了錯誤竹海。
二是使用dict本身提供的一個 get 方法,在Key不存在的時候丐黄,返回None:

>>> print d.get('Bart')
59
>>> print d.get('Paul')
None

dict的特點

dict的第一個特點是查找速度快斋配,無論dict有10個元素還是10萬個元素,查找速度都一樣灌闺。而list的查找速度隨著元素增加而逐漸下降艰争。
不過dict的查找速度快不是沒有代價的,dict的缺點是占用內存大桂对,還會浪費很多內容甩卓,list正好相反,占用內存小蕉斜,但是查找速度慢逾柿。

由于dict是按 key 查找,所以宅此,在一個dict中机错,key不能重復。

dict的第二個特點就是存儲的key-value序對是沒有順序的父腕!這和list不一樣

dict的第三個特點是作為 key 的元素必須不可變毡熏,Python的基本類型如字符串、整數侣诵、浮點數都是不可變的痢法,都可以作為 key。但是list是可變的杜顺,就不能作為 key财搁。

dict更新

dict是可變的,也就是說躬络,我們可以隨時往dict中添加新的 key-value尖奔。

>>> d['Paul'] = 72

遍歷dict

由于dict也是一個集合,所以,遍歷dict和遍歷list類似提茁,都可以通過 for 循環(huán)實現淹禾。

>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>> for key in d:
...     print key
... 
Lisa
Adam
Bart

Set

dict的作用是建立一組 key 和一組 value 的映射關系,dict的key是不能重復的茴扁。

有的時候铃岔,我們只想要 dict 的 key,不關心 key 對應的 value峭火,目的就是保證這個集合的元素不會重復毁习,這時,set就派上用場了卖丸。

set 持有一系列元素纺且,這一點和 list 很像,但是set的元素沒有重復稍浆,而且是無序的载碌,這點和 dict 的 key很像。

創(chuàng)建 set 的方式是調用 set() 并傳入一個 list衅枫,list的元素將作為set的元素:

>>> s = set(['A', 'B', 'C'])

可以查看 set 的內容:

>>> print s
set(['A', 'C', 'B'])

訪問set

由于set存儲的是無序集合恐仑,所以我們沒法通過索引來訪問。
訪問 set中的某個元素實際上就是判斷一個元素是否在set中为鳄。

>>> 'Bart' in s
True

set的特點

set的內部結構和dict很像裳仆,唯一區(qū)別是不存儲value,因此孤钦,判斷一個元素是否在set中速度很快歧斟。

set存儲的元素和dict的key類似,必須是不變對象偏形,因此静袖,任何可變對象是不能放入set中的。

最后俊扭,set存儲的元素也是沒有順序的队橙。

set的這些特點,可以應用在哪些地方呢萨惑?

星期一到星期日可以用字符串'MON', 'TUE', ... 'SUN'表示捐康。

假設我們讓用戶輸入星期一至星期日的某天,如何判斷用戶的輸入是否是一個有效的星期呢庸蔼?
如果事先創(chuàng)建好一個set解总,包含'MON' ~ 'SUN':

weekdays = set(['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'])

再判斷輸入是否有效,只需要判斷該字符串是否在set中:

x = '???' # 用戶輸入的字符串
if x in weekdays:
    print 'input ok'
else:
    print 'input error'

遍歷Set

由于 set 也是一個集合姐仅,所以花枫,遍歷 set 和遍歷 list 類似刻盐,都可以通過 for 循環(huán)實現。

>>> s = set(['Adam', 'Lisa', 'Bart'])
>>> for name in s:
...     print name
... 
Lisa
Adam
Bart

更新Set

由于set存儲的是一組不重復的無序元素劳翰,因此敦锌,更新set主要做兩件事:

一是把新的元素添加到set中,二是把已有元素從set中刪除佳簸。

添加元素時乙墙,用set的add()方法:

>>> s = set([1, 2, 3])
>>> s.add(4)
>>> print s
set([1, 2, 3, 4])

如果添加的元素已經存在于set中,add()不會報錯溺蕉,但是不會加進去了:

>>> s = set([1, 2, 3])
>>> s.add(3)
>>> print s
set([1, 2, 3])

刪除set中的元素時,用set的remove()方法:

>>> s = set([1, 2, 3, 4])
>>> s.remove(4)
>>> print s
set([1, 2, 3])

如果要刪除的元素不存在悼做,remove()會報錯

>>> s = set([1, 2, 3])
>>> s.remove(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 4

所以用add()可以直接添加疯特,而remove()前需要判斷。

函數

調用函數

Python內置了很多有用的函數肛走,我們可以直接調用漓雅。

要調用一個函數,需要知道函數的名稱和參數朽色,比如求絕對值的函數 abs邻吞,它接收一個參數。

可以直接從Python的官方網站查看文檔:
http://docs.python.org/2/library/functions.html#abs
也可以在交互式命令行通過 help(abs) 查看abs函數的幫助信息葫男。

編寫函數

在Python中抱冷,定義一個函數要使用 def 語句,依次寫出函數名梢褐、括號旺遮、括號中的參數和冒號:,然后盈咳,在縮進塊中編寫函數體耿眉,函數的返回值用 return 語句返回。

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x

請注意鱼响,函數體內部的語句在執(zhí)行時鸣剪,一旦執(zhí)行到return時,函數就執(zhí)行完畢丈积,并將結果返回筐骇。因此,函數內部通過條件判斷和循環(huán)可以實現非常復雜的邏輯江滨。
如果沒有return語句拥褂,函數執(zhí)行完畢后也會返回結果,只是結果為 None牙寞。

return None可以簡寫為return饺鹃。

返回多值

函數可以返回多個值嗎莫秆?答案是肯定的。

比如在游戲中經常需要從一個點移動到另一個點悔详,給出坐標镊屎、位移和角度,就可以計算出新的坐標:

math包提供了sin()和 cos()函數茄螃,我們先用import引用它:

import math
def move(x, y, step, angle):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny

這樣我們就可以同時獲得返回值:

>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print x, y
151.961524227 70.0

但其實這只是一種假象缝驳,Python函數返回的仍然是單一值:

>>> r = move(100, 100, 60, math.pi / 6)
>>> print r
(151.96152422706632, 70.0)

用print打印返回結果,原來返回值是一個tuple归苍!

但是用狱,在語法上,返回一個tuple可以省略括號拼弃,而多個變量可以同時接收一個tuple夏伊,按位置賦給對應的值,所以吻氧,Python的函數返回多值其實就是返回一個tuple河哑,但寫起來更方便他炊。

遞歸函數

在函數內部笛辟,可以調用其他函數噪馏。如果一個函數在內部調用自身本身,這個函數就是遞歸函數振惰。
舉個例子歌溉,我們來計算階乘 n! = 1 * 2 * 3 * ... * n,用函數 fact(n)表示骑晶,可以看出:

fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n
def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)

遞歸函數的優(yōu)點是定義簡單研底,邏輯清晰。理論上透罢,所有的遞歸函數都可以寫成循環(huán)的方式榜晦,但循環(huán)的邏輯不如遞歸清晰。

使用遞歸函數需要注意防止棧溢出羽圃。在計算機中乾胶,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用朽寞,棧就會加一層棧幀识窿,每當函數返回,棧就會減一層棧幀脑融。由于棧的大小不是無限的喻频,所以,遞歸調用的次數過多肘迎,會導致棧溢出甥温《突停可以試試計算 fact(10000)。

定義默認參數

定義函數的時候姻蚓,還可以有默認參數宋梧。
例如Python自帶的 int() 函數,其實就有兩個參數狰挡,我們既可以傳一個參數捂龄,又可以傳兩個參數:

>>> int('123')
123
>>> int('123', 8)
83

int()函數的第二個參數是轉換進制,如果不傳加叁,默認是十進制 (base=10)倦沧,如果傳了,就用傳入的參數它匕。

可見展融,函數的默認參數的作用是簡化調用,你只需要把必須的參數傳進去超凳。但是在需要的時候愈污,又可以傳入額外的參數來覆蓋默認參數值耀态。

由于函數的參數按從左到右的順序匹配轮傍,所以默認參數只能定義在必需參數的后面

定義可變參數

如果想讓一個函數能接受任意個參數,我們就可以定義一個可變參數:

def fn(*args):
    print args

可變參數的名字前面有個 * 號首装,我們可以傳入0個创夜、1個或多個參數給可變參數:

>>> fn()
()
>>> fn('a')
('a',)
>>> fn('a', 'b')
('a', 'b')
>>> fn('a', 'b', 'c')
('a', 'b', 'c')

切片

對list進行切片

取一個list的部分元素是非常常見的操作。比如仙逻,一個list如下:

>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']

取前3個元素驰吓,應該怎么做?
笨辦法

>>> [L[0], L[1], L[2]]
['Adam', 'Lisa', 'Bart']

之所以是笨辦法是因為擴展一下系奉,取前N個元素就沒轍了檬贰。

取前N個元素,也就是索引為0-(N-1)的元素缺亮,可以用循環(huán):

>>> r = []
>>> n = 3
>>> for i in range(n):
...     r.append(L[i])
... 
>>> r
['Adam', 'Lisa', 'Bart']

對這種經常取指定索引范圍的操作翁涤,用循環(huán)十分繁瑣,因此萌踱,Python提供了切片(Slice)操作符葵礼,能大大簡化這種操作。

對應上面的問題并鸵,取前3個元素鸳粉,用一行代碼就可以完成切片:

>>> L[0:3]
['Adam', 'Lisa', 'Bart']

L[0:3]表示,從索引0開始取园担,直到索引3為止届谈,但不包括索引3枯夜。即索引0,1疼约,2卤档,正好是3個元素。
如果第一個索引是0程剥,還可以省略:

>>> L[:3]
['Adam', 'Lisa', 'Bart']

只用一個 : 劝枣,表示從頭到尾:

>>> L[:]
['Adam', 'Lisa', 'Bart', 'Paul']

因此,L[:]實際上復制出了一個新list织鲸。
切片操作還可以指定第三個參數:

>>> L[::2]
['Adam', 'Bart']

第三個參數表示每N個取一個舔腾,上面的 L[::2] 會每兩個元素取出一個來,也就是隔一個取一個搂擦。

把list換成tuple稳诚,切片操作完全相同,只是切片的結果也變成了tuple瀑踢。
例:
range()函數可以創(chuàng)建一個數列:

>>> range(1, 101)
[1, 2, 3, ..., 100]

利用切片扳还,取出:

  1. 前10個數;
  2. 3的倍數橱夭;
  3. 不大于50的5的倍數氨距。
    代碼:
L = range(1, 101)

print L[:10]
print L[2::3]
print L[4:50:5]

結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]
[5, 10, 15, 20, 25, 30, 35, 40, 45, 50]

倒序切片

對于list,既然Python支持L[-1]取倒數第一個元素棘劣,那么它同樣支持倒數切片俏让,試試:

>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']

>>> L[-2:]
['Bart', 'Paul']
## -2為起始索引到最后
>>> L[:-2]
['Adam', 'Lisa']
## -2為起始索引到最后的基礎上,個數-2
>>> L[-3:-1]
['Lisa', 'Bart']
## -3為起始索引到最后的基礎上茬暇,個數-1
>>> L[-4:-1:2]
['Adam', 'Bart']
## -3為起始索引到最后的基礎上首昔,個數-1,并每間隔一個數糙俗,過濾一個

記住倒數第一個元素的索引是-1勒奇。倒序切片包含起始索引,不包含結束索引巧骚。

對字符串切片

字符串 'xxx'和 Unicode字符串 u'xxx'也可以看成是一種list赊颠,每個元素就是一個字符。因此网缝,字符串也可以用切片操作巨税,只是操作結果仍是字符串:

>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[-3:]
'EFG'
>>> 'ABCDEFG'[::2]
'ACEG'

在很多編程語言中,針對字符串提供了很多各種截取函數粉臊,其實目的就是對字符串切片草添。Python沒有針對字符串的截取函數,只需要切片一個操作就可以完成扼仲,非常簡單远寸。
字符串有個upper()方法可以吧字符變?yōu)榇髮懽帜?/p>

迭代

在Python中抄淑,如果給定一個list或tuple,我們可以通過for循環(huán)來遍歷這個list或tuple驰后,這種遍歷我們成為迭代(Iteration)肆资。
在Python中,迭代是通過 for ... in 來完成的灶芝,而很多語言比如C或者Java郑原,迭代list是通過下標完成的,比如Java代碼:

for (i=0; i<list.length; i++) {
    n = list[i];
}

因為 Python 的 for循環(huán)不僅可以用在list或tuple上夜涕,還可以作用在其他任何可迭代對象上犯犁。
因此,迭代操作就是對于一個集合女器,無論該集合是有序還是無序酸役,我們用 for 循環(huán)總是可以依次取出集合的每一個元素。

注意: 集合是指包含一組元素的數據結構驾胆,我們已經介紹的包括:

  1. 有序集合:list涣澡,tuple,str和unicode丧诺;
  2. 無序集合:set
  3. 無序集合并且具有 key-value 對:dict
    而迭代是一個動詞入桂,它指的是一種操作,在Python中锅必,就是 for 循環(huán)事格。

迭代與按下標訪問數組最大的不同是惕艳,后者是一種具體的迭代實現方式搞隐,而前者只關心迭代結果,根本不關心迭代內部是如何實現的远搪。

索引迭代

Python中劣纲,迭代永遠是取出元素本身,而非元素的索引谁鳍。
對于有序集合癞季,元素確實是有索引的。有的時候倘潜,我們確實想在 for 循環(huán)中拿到索引绷柒,怎么辦?
方法是使用 enumerate() 函數:

>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> for index, name in enumerate(L):
...     print index, '-', name
... 
0 - Adam
1 - Lisa
2 - Bart
3 - Paul

實際上涮因,enumerate() 函數把:['Adam', 'Lisa', 'Bart', 'Paul'] 變成了類似[(0, 'Adam'), (1, 'Lisa'), (2, 'Bart'), (3, 'Paul')] 因此废睦,迭代的每一個元素實際上是一個tuple:

for t in enumerate(L):
    index = t[0]
    name = t[1]
    print index, '-', name

如果我們知道每個tuple元素都包含兩個元素,for循環(huán)又可以進一步簡寫為:

for index, name in enumerate(L):
    print index, '-', name

可見养泡,索引迭代也不是真的按索引訪問嗜湃,而是由 enumerate() 函數自動把每個元素變成 (index, element) 這樣的tuple奈应,再迭代,就同時獲得了索引和元素本身购披。
zip()函數可以把兩個 list 變成一個 list:

>>> zip([10, 20, 30], ['A', 'B', 'C'])
[(10, 'A'), (20, 'B'), (30, 'C')]

List

生成list

可以用range(1,11)生成List[1,2,3,4,5,6,7,8,10]

>>> range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

但如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做杖挣?方法一是循環(huán):

>>> L = []
>>> for x in range(1, 11):
...    L.append(x * x)
... 
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
``
但是循環(huán)太繁瑣,而列表生成式則可以用一行語句代替循環(huán)生成上面的list:
```python
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

這種寫法就是Python特有的列表生成式刚陡。利用列表生成式惩妇,可以以非常簡潔的代碼生成 list。
寫列表生成式時筐乳,把要生成的元素 x * x 放到前面屿附,后面跟 for 循環(huán),就可以把list創(chuàng)建出來哥童,十分有用挺份,多寫幾次,很快就可以熟悉這種語法贮懈。

復雜表達式

使用for循環(huán)的迭代不僅可以迭代普通的list匀泊,還可以迭代dict。
假設有如下的dict:

d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }

完全可以通過一個復雜的列表生成式把它變成一個 HTML 表格:

tds = ['<tr><td>%s</td><td>%s</td></tr>' % (name, score) for name, score in d.iteritems()]
print '<table>'
print '<tr><th>Name</th><th>Score</th><tr>'
print '\n'.join(tds)
print '</table>'

注:字符串可以通過 % 進行格式化朵你,用指定的參數替代 %s各聘。字符串的join()方法可以把一個 list 拼接成一個字符串。
把打印出來的結果保存為一個html文件抡医,就可以在瀏覽器中看到效果了:
<table border="1">
<tr><th>Name</th><th>Score</th><tr>
<tr><td>Lisa</td><td>85</td></tr>
<tr><td>Adam</td><td>95</td></tr>
<tr><td>Bart</td><td>59</td></tr>
</table>

條件過濾

列表生成式的 for 循環(huán)后面還可以加上 if 判斷躲因。例如:

>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

如果我們只想要偶數的平方,不改動 range()的情況下忌傻,可以加上 if 來篩選:

>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

有了 if 條件大脉,只有 if 判斷為 True 的時候,才把循環(huán)的當前元素添加到列表中水孩。

  1. isinstance(x, str) 可以判斷變量 x 是否是字符串镰矿;
  2. 字符串的 upper() 方法可以返回大寫的字母。

多層表達式

for循環(huán)可以嵌套俘种,因此秤标,在列表生成式中,也可以用多層 for 循環(huán)來生成列表宙刘。
對于字符串 'ABC' 和 '123'苍姜,可以使用兩層循環(huán),生成全排列:

>>> [m + n for m in 'ABC' for n in '123']
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

翻譯成循環(huán)代碼就像下面這樣:

L = []
for m in 'ABC':
    for n in '123':
        L.append(m + n)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末悬包,一起剝皮案震驚了整個濱河市衙猪,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖屈嗤,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件潘拨,死亡現場離奇詭異,居然都是意外死亡饶号,警方通過查閱死者的電腦和手機铁追,發(fā)現死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茫船,“玉大人琅束,你說我怎么就攤上這事∷闾福” “怎么了涩禀?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長然眼。 經常有香客問我艾船,道長,這世上最難降的妖魔是什么高每? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任屿岂,我火速辦了婚禮,結果婚禮上鲸匿,老公的妹妹穿的比我還像新娘爷怀。我一直安慰自己,他們只是感情好带欢,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布运授。 她就那樣靜靜地躺著,像睡著了一般乔煞。 火紅的嫁衣襯著肌膚如雪吁朦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天瘤缩,我揣著相機與錄音喇完,去河邊找鬼伦泥。 笑死剥啤,一個胖子當著我的面吹牛,可吹牛的內容都是我干的不脯。 我是一名探鬼主播府怯,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼防楷!你這毒婦竟也來了牺丙?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冲簿,沒想到半個月后粟判,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡峦剔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年档礁,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吝沫。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡呻澜,死狀恐怖,靈堂內的尸體忽然破棺而出惨险,到底是詐尸還是另有隱情羹幸,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布辫愉,位于F島的核電站栅受,受9級特大地震影響,放射性物質發(fā)生泄漏恭朗。R本人自食惡果不足惜窘疮,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望冀墨。 院中可真熱鬧闸衫,春花似錦、人聲如沸诽嘉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虫腋。三九已至骄酗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悦冀,已是汗流浹背趋翻。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盒蟆,地道東北人踏烙。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像历等,于是被迫代替她去往敵國和親讨惩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345