# :-: python初識
[TOC]
## **數據類型**
1.整數
2.浮點數
3.字符串
4.布爾型
5.空值
注釋使用 #
## **變量**
變量名必須是大小寫英文、數字和下劃線的組合,且不能用數字開頭
## **字符串**
字符串可以用`''`或者`""`括起來表示。
如果字符串本身包含`'`怎么辦?比如我們要表示字符串`?I'm OK?`,這時,可以用`" "`括起來表示:
~~~
"I'm OK"
~~~
如果字符串既包含`'`又包含`"`
這個時候,就需要對字符串的某些特殊字符進行“轉義”,Python字符串用`\`進行轉義。
要表示字符串?`Bob said "I'm OK".`
~~~
'Bob said \"I\'m OK\".'
~~~
常用的轉義字符還有:
~~~
\n 表示換行
\t 表示一個制表符
\\ 表示 \ 字符本身
~~~
## **Python中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!'''
~~~
## **Python中Unicode字符串**
Python在后來添加了對Unicode的支持,以Unicode表示的字符串用u'...'表示,比如:
~~~
print u'中文'
中文
~~~
Unicode字符串除了多了一個`u`之外,與普通字符串沒啥區別,轉義字符和多行表示法仍然有效
**多行:**
~~~
u'''第一行
第二行'''
~~~
**raw+多行:**
~~~
ur'''Python的Unicode字符串支持"中文",
"日文",
"韓文"等多種語言'''
~~~
如果中文字符串在Python環境下遇到 UnicodeDecodeError,這是因為.py文件保存的格式有問題。可以在第一行添加注釋
~~~
# -*- coding: utf-8 -*-
~~~
## **Python中整數和浮點數**
Python支持對整數和浮點數直接進行四則混合運算,運算規則和數學上的四則運算規則完全一致。
基本的運算:
~~~
1 + 2 + 3 # ==> 6
4 * 5 - 6 # ==> 14
7.5 / 8 + 2.1 # ==> 3.0375
~~~
使用括號可以提升優先級,這和數學運算完全一致,注意只能使用小括號,但是括號可以嵌套很多層:
~~~
(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
~~~
> 為什么要區分整數運算和浮點數運算呢?這是因為整數運算的結果永遠是精確的,而浮點數運算的結果不一定精確,因為計算機內存再大,也無法精確表示出無限循環小數,比如`0.1`換成二進制表示就是無限循環小數。
那整數的除法運算遇到除不盡的時候,結果難道不是浮點數嗎?我們來試一下:
~~~
11 / 4 # ==> 2
~~~
令很多初學者驚訝的是,Python的整數除法,即使除不盡,結果仍然是整數,余數直接被扔掉。不過,Python提供了一個求余的運算 % 可以計算余數:
~~~
11 % 4 # ==> 3
~~~
如果我們要計算 11 / 4 的精確結果,按照“整數和浮點數混合運算的結果是浮點數”的法則,把兩個數中的一個變成浮點數再運算就沒問題了:
~~~
11.0 / 4 # ==> 2.75
~~~
## **Python中布爾類型**
**與運算**:只有兩個布爾值都為 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變為False,或者把False變為True:
~~~
not True # ==> False
not False # ==> True
~~~
Python把`0`、`空字符串''`和`None`看成?False,其他數值和非空字符串都看成True
~~~
a = True
print a and 'a=T' or 'a=F'
~~~
計算結果不是布爾類型,而是字符串 'a=T'
## **Python創建list**
Python內置的一種數據類型是列表:`list`。list是一種有序的集合,可以隨時添加和刪除其中的元素。
~~~
>>> ['Michael', 'Bob', 'Tracy']
['Michael', 'Bob', 'Tracy']
~~~
list是數學意義上的有序集合,也就是說,list中的元素是按照順序排列的。
構造list非常簡單,按照上面的代碼,直接用`[ ]`把list的所有元素都括起來,就是一個list對象。通常,我們會把list賦值給一個變量,這樣,就可以通過變量來引用list:
~~~
>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates # 打印classmates變量的內容
['Michael', 'Bob', 'Tracy']
~~~
由于Python是動態語言,所以list中包含的元素并不要求都必須是同一種數據類型,我們完全可以在list中包含各種數據:
~~~
>>> L = ['Michael', 100, True]
~~~
一個元素也沒有的list,就是空list:
~~~
>>> empty_list = []
~~~
## **Python之倒序訪問list**
~~~
>>> L = ['Adam', 'Lisa', 'Bart']
~~~
~~~
>>> print L[-1]
Bart
~~~
倒數第二用 -2 表示,倒數第三用 -3 表示,倒數第四用 -4 表示
~~~
>>> print L[-2]
Lisa
>>> print L[-3]
Adam
>>> print L[-4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
~~~
## **Python之添加新元素**
**append()**總是把新的元素添加到 list 的尾部。
~~~
>>> L = ['Adam', 'Lisa', 'Bart']
>>> L.append('Paul')
>>> print L
['Adam', 'Lisa', 'Bart', 'Paul']
~~~
用list的`insert()`方法,它接受兩個參數,第一個參數是索引號,第二個參數是待添加的新元素:
~~~
>>> L = ['Adam', 'Lisa', 'Bart']
>>> L.insert(0, 'Paul')
>>> print L
['Paul', 'Adam', 'Lisa', 'Bart']
~~~
**L.insert(0, 'Paul')**的意思是,'Paul'將被添加到索引為 0 的位置上(也就是第一個),而原來索引為 0 的Adam同學,以及后面的所有同學,都自動向后移動一位。
## **Python從list刪除元素**
~~~
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> L.pop()
'Paul'
>>> print L
['Adam', 'Lisa', 'Bart']
~~~
**pop()**方法總是刪掉list的最后一個元素,并且它還返回這個元素,所以我們執行 L.pop() 后,會打印出 'Paul'。
要把Paul踢出list,我們就必須先定位Paul的位置。由于Paul的索引是2,因此,用`pop(2)`把Paul刪掉:
~~~
>>> L.pop(2)
'Paul'
>>> print L
['Adam', 'Lisa', 'Bart']
~~~
## **Python之創建tuple**
tuple是另一種有序的列表,中文翻譯為“?元組?”。tuple 和 list 非常類似,但是,tuple一旦創建完畢,就不能修改了。
~~~
>>> t = ('Adam', 'Lisa', 'Bart')
~~~
創建tuple和創建list唯一不同之處是用`( )`替代了`[ ]`。
現在,這個`t`就不能改變了,tuple沒有 append()方法,也沒有insert()和pop()方法。所以,新同學沒法直接往 tuple 中添加,老同學想退出 tuple 也不行。
獲取 tuple 元素的方式和 list 是一模一樣的,我們可以正常使用 t\[0\],t\[-1\]等索引方式訪問元素,但是不能賦值成別的元素
## **Python之創建單元素tuple**
正是因為用()定義單元素的tuple有歧義,所以 Python 規定,單元素 tuple 要多加一個逗號“,”
~~~
>>> t = (1,)
>>> print t
(1,)
~~~
多元素 tuple 加不加這個額外的“,”效果是一樣的
~~~
>>> t = (1, 2, 3,)
>>> print t
(1, 2, 3)
~~~
## **Python之“可變”的tuple**
前面我們看到了tuple一旦創建就不能修改。現在,我們來看一個“可變”的tuple:
~~~
>>> t = ('a', 'b', ['A', 'B'])
~~~
**注意**到 t 有 3 個元素:**'a','b'**和一個list:**\['A', 'B'\]**。list作為一個整體是tuple的第3個元素。list對象可以通過 t\[2\] 拿到:
~~~
>>> L = t[2]
~~~
## **Python之if語句**
~~~
age = 20
if age >= 18:
print 'your age is', age
print 'adult'
print 'END'
~~~
> **注意:** Python代碼的縮進規則。具有相同縮進的代碼被視為代碼塊,上面的3,4行 print 語句就構成一個代碼塊(但不包括第5行的print)。如果 if 語句判斷為 True,就會執行這個代碼塊。
> 縮進請嚴格按照Python的習慣寫法:4個空格,不要使用Tab,更不要混合Tab和空格,否則很容易造成因為縮進引起的語法錯誤。
> **注意**: if 語句后接表達式,然后用`:`表示代碼塊開始。
> 如果你在Python交互環境下敲代碼,還要特別留意縮進,并且退出縮進需要多敲一行回車:
## **Python之 if-else**
當?if?語句判斷表達式的結果為True時,就會執行 if 包含的代碼塊:
~~~
if age >= 18:
print 'adult'
~~~
~~~
if not age >= 18:
print 'teenager'
~~~
~~~
if age >= 18:
print 'adult'
else:
print 'teenager'
~~~
## **Python之 if-elif-else**
~~~
if age >= 18:
print 'adult'
else:
if age >= 6:
print 'teenager'
else:
if age >= 3:
print 'kid'
else:
print 'baby'
~~~
## **Python之 for循環**
list或tuple可以表示一個有序集合。如果我們想依次訪問一個list中的每一個元素呢?比如 list:
~~~
L = ['Adam', 'Lisa', 'Bart']
for name in L:
print name
~~~
> **注意:?**?name 這個變量是在 for 循環中定義的,意思是,依次取出list中的每一個元素,并把元素賦值給 name,然后執行for循環體(就是縮進的代碼塊)。
## **Python之 while循環**
和 for 循環不同的另一種循環是while循環,while 循環不會迭代 list 或 tuple 的元素,而是根據表達式判斷循環是否結束。
比如要從 0 開始打印不大于 N 的整數:
~~~
N = 10
x = 0
while x < N:
print x
x = x + 1
~~~
while循環每次先判斷 x < N,如果為True,則執行循環體的代碼塊,否則,退出循環。
在循環體內,x = x + 1會讓x不斷增加,最終因為x < N不成立而退出循環。
如果沒有這一個語句,**while循環在判斷 x < N 時總是為True**,就會無限循環下去,變成死循環,所以要特別留意while循環的退出條件
## **Python之 break退出循環**
用 for 循環或者 while 循環時,如果要在循環體內直接退出循環,可以使用?break?語句。
比如計算1至100的整數和,我們用while來實現:
~~~
sum = 0
x = 1
while True:
sum = sum + x
x = x + 1
if x > 100:
break
print sum
~~~
## **Python之 continue繼續循環**
在循環過程中,可以用break退出當前循環,還可以用continue跳過后續循環代碼,繼續下一次循環。
假設我們已經寫好了利用for循環計算平均分的代碼:
~~~
L = [75, 98, 59, 81, 66, 43, 69, 85]
sum = 0.0
n = 0
for x in L:
sum = sum + x
n = n + 1
print sum / n
~~~
現在老師只想統計及格分數的平均分,就要把 x < 60 的分數剔除掉,這時,利用 continue,可以做到當 x < 60的時候,不繼續執行循環體的后續代碼,直接進入下一次循環:
~~~
for x in L:
if x < 60:
continue
sum = sum + x
n = n + 1
~~~
## **Python之 多重循環**
~~~
for x in ['A', 'B', 'C']:
for y in ['1', '2', '3']:
print x + y
~~~
## **Python之什么是dict**
Python的 dict 就是專門干這件事的。用?**dict?**表示**“名字”-“成績”**的查找表如下:
~~~
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
~~~
我們把**名字稱為key**,對應的**成績稱為value**,dict就是通過**key**來查找**value**。
花括號{}表示這是一個dict,然后按照**key: value**, 寫出來即可。最后一個 key: value 的逗號可以省略。
由于dict也是集合,len()?函數可以計算任意集合的大小:
~~~
>>> len(d)
3
~~~
## **Python之訪問dict**
可以簡單地使用d\[key\]的形式來查找對應的 value,這和 list 很像,不同之處是,**list 必須使用索引返回對應的元素,而dict使用key:**
**注意:**通過 key 訪問 dict 的value,只要 key 存在,dict就返回對應的value。如果key不存在,會直接報錯:KeyError。
要避免 KeyError 發生,有兩個辦法:
**一是先判斷一下 key 是否存在,用 in 操作符:**
~~~
if 'Paul' in d:
print d['Paul']
~~~
**二是使用dict本身提供的一個 get 方法,在Key不存在的時候,返回None:**
~~~
>>> print d.get('Bart')
59
>>> print d.get('Paul')
None
~~~
## **Python中dict的特點**
**dict的第一個特點是查找速度快,無論dict有10個元素還是10萬個元素,查找速度都一樣**。而list的查找速度隨著元素增加而逐漸下降。
不過dict的查找速度快不是沒有代價的,**dict的缺點是占用內存大,還會浪費很多內容**,list正好相反,占用內存小,但是查找速度慢。
由于dict是按 key 查找,所以,在一個dict中,key不能重復。
**dict的第二個特點就是存儲的key-value序對是沒有順序的**
**dict的第三個特點是作為 key 的元素必須不可變**
## **Python更新dict**
dict是可變的,也就是說,我們可以隨時往dict中添加新的 key-value。比如已有dict:
~~~
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
~~~
要把新同學'Paul'的成績 72 加進去,用賦值語句:
~~~
>>> d['Paul'] = 72
~~~
如果 key 已經存在,則賦值會用新的 value 替換掉原來的 value:
## **Python之 遍歷dict**
由于dict也是一個集合,所以,遍歷dict和遍歷list類似,都可以通過 for 循環實現。
直接使用for循環可以遍歷 dict 的 key:
~~~
>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>> for key in d:
... print key
...
Lisa
Adam
Bart
~~~
## **Python中什么是set**
**dict的作用是建立一組 key 和一組 value 的映射關系,dict的key是不能重復的。**
有的時候,我們只想要 dict 的 key,不關心 key 對應的 value,目的就是保證這個集合的元素不會重復,這時,set就派上用場了。
**set 持有一系列元素,這一點和 list 很像,但是set的元素沒有重復,而且是無序的,這點和 dict 的 key很像。**
創建 set 的方式是調用 set() 并傳入一個 list,list的元素將作為set的元素:
~~~
>>> s = set(['A', 'B', 'C'])
~~~
~~~
>>> print s
set(['A', 'C', 'B'])
~~~
**請注意**,上述打印的形式類似 list, 但它不是 list,仔細看還可以發現,打印的順序和原始 list 的順序有可能是不同的,因為set內部存儲的元素是**無序**的。
因為set不能包含重復的元素,所以,當我們傳入包含重復元素的 list 會怎么樣呢?
~~~
>>> s = set(['A', 'B', 'C', 'C'])
>>> print s
set(['A', 'C', 'B'])
>>> len(s)
3
~~~
## **Python之 訪問set**
由于**set存儲的是無序集合**,所以我們沒法通過索引來訪問。
訪問 set中的某個元素實際上就是判斷一個元素是否在set中。
~~~
>>> s = set(['Adam', 'Lisa', 'Bart', 'Paul'])
~~~
我們可以用 in 操作符判斷
~~~
>>> 'Bart' in s
True
~~~
~~~
>>> 'Bill' in s
False
~~~
~~~
>>> 'bart' in s
False
~~~
看來大小寫很重要,'Bart' 和 'bart'被認為是兩個不同的元素
## **Python之 set的特點**
**set的內部結構和dict很像,唯一區別是不存儲value**,因此,判斷一個元素是否在set中速度很快。
**set存儲的元素和dict的key類似,必須是不變對象**,因此,任何可變對象是不能放入set中的。
最后,set存儲的元素也是沒有順序的。
set的這些特點,可以應用在哪些地方呢?
星期一到星期日可以用字符串'MON', 'TUE', ... 'SUN'表示。
假設我們讓用戶輸入星期一至星期日的某天,如何判斷用戶的輸入是否是一個有效的星期呢?
可以用**if 語句**判斷,但這樣做非常繁瑣:
~~~
x = '???' # 用戶輸入的字符串
if x!= 'MON' and x!= 'TUE' and x!= 'WED' ... and x!= 'SUN':
print 'input error'
else:
print 'input ok'
~~~
**注意:**if 語句中的...表示沒有列出的其它星期名稱,測試時,請輸入完整。
如果事先創建好一個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'
~~~
## **Python之 遍歷set**
由于 set 也是一個集合,所以,遍歷 set 和遍歷 list 類似,都可以通過 for 循環實現。
直接使用 for 循環可以遍歷 set 的元素:
~~~
>>> s = set(['Adam', 'Lisa', 'Bart'])
>>> for name in s:
... print name
...
Lisa
Adam
Bart
~~~
**注意:?**觀察 for 循環在遍歷set時,元素的順序和list的順序很可能是不同的,而且不同的機器上運行的結果也可能不同。
## **Python之 更新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])
~~~
如果刪除的元素不存在set中,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之調用函數**
Python內置了很多有用的函數,我們可以直接調用。
要調用一個函數,需要知道**函數**的**名稱**和**參數**,比如求絕對值的函數 abs,它接收一個參數。
~~~
可以直接從Python的官方網站查看文檔:
http://docs.python.org/2/library/functions.html#abs
~~~
也可以在交互式命令行通過help(abs)?查看abs函數的幫助信息。
調用?**abs?**函數:
~~~
>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
~~~
調用函數的時候,如果傳入的參數數量不對,會報**TypeError**的錯誤,并且Python會明確地告訴你:abs()有且僅有1個參數,但給出了兩個:
~~~
>>> abs(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: abs() takes exactly one argument (2 given)
~~~
如果傳入的參數數量是對的,但參數類型不能被函數所接受,也會報**TypeError**的錯誤,并且給出錯誤信息:str是錯誤的參數類型:
~~~
>>> abs('a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bad operand type for abs(): 'str'
~~~
而比較函數?cmp(x, y)?就需要兩個參數,如果**xy**,返回**1**:
~~~
>>> cmp(1, 2)
-1
>>> cmp(2, 1)
1
>>> cmp(3, 3)
0
~~~
Python內置的常用函數還包括數據類型轉換函數,比如? ?int()函數可以把其他數據類型轉換為整數:
~~~
>>> int('123')
123
>>> int(12.34)
12
~~~
str()函數把其他類型轉換成 str:
~~~
>>> str(123)
'123'
>>> str(1.23)
'1.23'
~~~
## **Python之編寫函數**
在Python中,定義一個函數要使用**def**語句,依次寫出函數名、括號、括號中的參數和冒號:,然后,在縮進塊中編寫函數體,函數的返回值用?return語句返回。
我們以自定義一個求絕對值的 my\_abs 函數為例:
~~~
def my_abs(x):
if x >= 0:
return x
else:
return -x
~~~
**請注意**,函數體內部的語句在執行時,一旦執行到return時,函數就執行完畢,并將結果返回。因此,函數內部通過條件判斷和循環可以實現非常復雜的邏輯。
如果沒有return語句,函數執行完畢后也會返回結果,只是結果為 None。
return None可以簡寫為return。
## **Python函數之返回多值**
**\# 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**,但寫起來更方便。
## **Python之遞歸函數**
在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。
舉個例子,我們來計算階乘**n! = 1 \* 2 \* 3 \* ... \* n**,用函數?**fact(n)**表示,可以看出:
~~~
fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n
~~~
所以,**fact(n)**可以表示為**n \* fact(n-1)**,只有n=1時需要特殊處理。
于是,fact(n)用遞歸的方式寫出來就是:
~~~
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
~~~
遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰
使用遞歸函數需要注意防止棧溢出。在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由于棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出。可以試試計算 fact(10000)。
## **Python之定義默認參數**
例如Python自帶的**int()**函數,其實就有兩個參數,我們既可以傳一個參數,又可以傳兩個參數:
~~~
>>> int('123')
123
>>> int('123', 8)
83
~~~
int()函數的第二個參數是轉換進制,如果不傳,默認是十進制 (base=10),如果傳了,就用傳入的參數。
可見,**函數的默認參數的作用是簡化調用**,你只需要把必須的參數傳進去。但是在需要的時候,又可以傳入額外的參數來覆蓋默認參數值。
我們來定義一個計算 x 的N次方的函數:
~~~
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
~~~
假設計算平方的次數最多,我們就可以把 n 的默認值設定為 2:
~~~
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
~~~
這樣一來,計算平方就不需要傳入兩個參數了:
~~~
>>> power(5)
25
~~~
由于函數的參數按從左到右的順序匹配,所以**默認參數只能定義在必需參數的后面:**
## **Python之定義可變參數**
如果想讓一個函數能接受任意個參數,我們就可以定義一個可變參數:
~~~
def fn(*args):
print args
~~~
可變參數的名字前面有個?**\*?**號,我們可以傳入0個、1個或多個參數給可變參數:
~~~
>>> fn()
()
>>> fn('a')
('a',)
>>> fn('a', 'b')
('a', 'b')
>>> fn('a', 'b', 'c')
('a', 'b', 'c')
~~~
可變參數也不是很神秘,Python解釋器會把傳入的一組參數組裝成一個tuple傳遞給可變參數,因此,在函數內部,直接把變量args看成一個?tuple?就好了。
定義可變參數的目的也是為了簡化調用。假設我們要計算任意個數的平均值,就可以定義一個可變參數:
~~~
def average(*args):
...
~~~
這樣,在調用的時候,可以這樣寫:
~~~
>>> average()
0
>>> average(1, 2)
1.5
>>> average(1, 2, 2, 3, 4)
2.4
~~~
## **對list進行切片**
取一個list的部分元素是非常常見的操作。比如,一個list如下:
~~~
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
~~~
取前3個元素,應該怎么做?
笨辦法:
~~~
>>> [L[0], L[1], L[2]]
['Adam', 'Lisa', 'Bart']
~~~
之所以是笨辦法是因為擴展一下,取前N個元素就沒轍了。
取前N個元素,也就是索引為0-(N-1)的元素,可以用循環:
~~~
>>> r = []
>>> n = 3
>>> for i in range(n):
... r.append(L[i])
...
>>> r
['Adam', 'Lisa', 'Bart']
~~~
對這種經常取指定索引范圍的操作,用循環十分繁瑣,因此,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']
~~~
也可以從索引1開始,取出2個元素出來:
~~~
>>> L[1:3]
['Lisa', 'Bart']
~~~
只用一個**:**,表示從頭到尾:
~~~
>>> L[:]
['Adam', 'Lisa', 'Bart', 'Paul']
~~~
因此,L\[:\]實際上復制出了一個新list。
切片操作還可以指定第三個參數:
~~~
>>> L[::2]
['Adam', 'Bart']
~~~
第三個參數表示每N個取一個,上面的 L\[::2\] 會每兩個元素取出一個來,也就是隔一個取一個。
把list換成tuple,切片操作完全相同,只是切片的結果也變成了tuple。
## **倒序切片**
對于list,既然Python支持L\[-1\]取倒數第一個元素,那么它同樣支持倒數切片,試試:
~~~
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> L[-2:]
['Bart', 'Paul']
>>> L[:-2]
['Adam', 'Lisa']
>>> L[-3:-1]
['Lisa', 'Bart']
>>> L[-4:-1:2]
['Adam', 'Bart']
~~~
記住倒數第一個元素的索引是-1。倒序切片包含起始索引,不包含結束索引。
## **對字符串切片**
字符串 'xxx'和 Unicode字符串 u'xxx'也可以看成是一種list,每個元素就是一個字符。因此,字符串也可以用切片操作,只是操作結果仍是字符串:
~~~
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[-3:]
'EFG'
>>> 'ABCDEFG'[::2]
'ACEG'
~~~
在很多編程語言中,針對字符串提供了很多各種截取函數,其實目的就是對字符串切片。Python沒有針對字符串的截取函數,只需要切片一個操作就可以完成,非常簡單。
## **什么是迭代**
在Python中,如果給定一個**list**或**tuple**,我們可以通過for循環來遍歷這個list或tuple,這種遍歷我們成為迭代(Iteration)。
在Python中,迭代是通過?for ... in?來完成的,而很多語言比如C或者Java,迭代list是通過下標完成的,比如Java代碼:
~~~
for (i=0; i<list.length; i++) {
n = list[i];
}
~~~
可以看出,Python的for循環抽象程度要高于Java的for循環。
**因為 Python 的 for循環不僅可以用在list或tuple上,還可以作用在其他任何可迭代對象上。**
因此,迭代操作就是對于一個集合,無論該集合是有序還是無序,我們用 for 循環總是可以依次取出集合的每一個元素。
~~~
注意: 集合是指包含一組元素的數據結構,我們已經介紹的包括:
1. 有序集合:list,tuple,str和unicode;
2. 無序集合:set
3. 無序集合并且具有 key-value 對:dict
~~~
而迭代是一個動詞,它指的是一種操作,在Python中,就是 for 循環。
迭代與按下標訪問數組最大的不同是,后者是一種具體的迭代實現方式,而前者只關心迭代結果,根本不關心迭代內部是如何實現的。
## **索引迭代**
Python中,**迭代永遠是取出元素本身,而非元素的索引。**
對于有序集合,元素確實是有索引的。有的時候,我們確實想在 for 循環中拿到索引,怎么辦?
方法是使用**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:
~~~
for t in enumerate(L):
index = t[0]
name = t[1]
print index, '-', name
~~~
如果我們知道每個tuple元素都包含兩個元素,for循環又可以進一步簡寫為:
~~~
for index, name in enumerate(L):
print index, '-', name
~~~
這樣不但代碼更簡單,而且還少了兩條賦值語句。
可見,索引迭代也不是真的按索引訪問,而是由 enumerate() 函數自動把每個元素變成 (index, element) 這樣的tuple,再迭代,就同時獲得了索引和元素本身。
## **迭代dict的value**
我們已經了解了**dict對象**本身就是可**迭代對象**,用 for 循環直接迭代 dict,可以每次拿到dict的一個key。
如果我們希望迭代 dict 對象的value,應該怎么做?
dict 對象有一個**values() 方法**,這個方法把dict轉換成一個包含所有value的list,這樣,我們迭代的就是 dict的每一個 value:
~~~
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.values()
# [85, 95, 59]
for v in d.values():
print v
# 85
# 95
# 59
~~~
如果仔細閱讀Python的文檔,還可以發現,dict除了**values()**方法外,還有一個**itervalues()**方法,用**itervalues()**方法替代**values()**方法,迭代效果完全一樣:
~~~
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.itervalues()
# <dictionary-valueiterator object at 0x106adbb50>
for v in d.itervalues():
print v
# 85
# 95
# 59
~~~
**那這兩個方法有何不同之處呢?**
1.**values()**方法實際上把一個 dict 轉換成了包含 value 的list。
2\. 但是**itervalues()**方法不會轉換,它會在迭代過程中依次從 dict 中取出 value,所以 itervalues() 方法比 values() 方法節省了生成 list 所需的內存。
3.?打印 itervalues() 發現它返回一個 對象,這說明在Python中,**for 循環可作用的迭代對象遠不止 list,tuple,str,unicode,dict等**,任何可迭代對象都可以作用于for循環,而內部如何迭代我們通常并不用關心。
**如果一個對象說自己可迭代,那我們就直接用 for 循環去迭代它,可見,迭代是一種抽象的數據操作,它不對迭代對象內部的數據有任何要求。**
## **迭代dict的key和value**
我們了解了如何**迭代 dict**的**key**和**value**,那么,在一個 for 循環中,能否同時迭代 key和value?答案是肯定的。
首先,我們看看 dict 對象的**items()**方法返回的值:
~~~
>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>> print d.items()
[('Lisa', 85), ('Adam', 95), ('Bart', 59)]
~~~
可以看到,items() 方法把dict對象轉換成了包含tuple的list,我們對這個list進行迭代,可以同時獲得key和value:
~~~
>>> for key, value in d.items():
... print key, ':', value
...
Lisa : 85
Adam : 95
Bart : 59
~~~
和 values() 有一個 itervalues() 類似,**items()**也有一個對應的**iteritems()**,iteritems() 不把dict轉換成list,而是在迭代過程中不斷給出 tuple,所以, iteritems() 不占用額外的內存。
## **生成列表**
要生成list \[1, 2, 3, 4, 5, 6, 7, 8, 9, 10\],我們可以用range(1, 11):
~~~
>>> range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
~~~
但如果要生成\[1x1, 2x2, 3x3, ..., 10x10\]怎么做?方法一是循環:
~~~
>>> L = []
>>> for x in range(1, 11):
... L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
~~~
但是循環太繁瑣,而列表生成式則可以用一行語句代替循環生成上面的list:
~~~
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
~~~
這種寫法就是Python特有的列表生成式。利用列表生成式,可以以非常簡潔的代碼生成 list。
寫列表生成式時,把要生成的元素 x \* x 放到前面,后面跟 for 循環,就可以把list創建出來,十分有用,多寫幾次,很快就可以熟悉這種語法。
## **復雜表達式**
使用**for循環**的迭代不僅可以迭代普通的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>
~~~
[](http://img.mukewang.com/540fcd2a0001ff4600940104.jpg)
## **條件過濾**
列表生成式的?**for 循環后面還可以加上 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 的時候,才把循環的當前元素添加到列表中。
## **多層表達式**
for循環可以嵌套,因此,在列表生成式中,也可以用多層for循環來生成列表。
對于字符串 'ABC' 和 '123',可以使用兩層循環,生成全排列:
~~~
>>> [m + n for m in 'ABC' for n in '123']
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
~~~
翻譯成循環代碼就像下面這樣:
~~~
L = []
for m in 'ABC':
for n in '123':
L.append(m + n)
~~~
- 關于我們
- ApiCloud
- 支付模塊
- 微信支付--wxPay(客戶端)
- 微信支付--wxPay(服務端)
- 支付寶支付--aliPay(客戶端配置)
- 支付寶支付--aliPay(服務端配置)
- DoT模板
- 緩存模塊
- 監聽模塊
- 百度定位模塊
- 設置狀態欄字體顏色
- 選擇城市插件
- 跨頁面執行方法
- 安卓-點擊返回事件
- 上傳圖片模塊
- 點擊彈出放大圖片層
- 魅族手機apiready問題
- 分享
- 跨win或frm執行腳本
- 關于ios數字自動識別成手機號
- 百度地圖bMap
- 語音識別模塊
- tabBarMenu底部導航
- 第三方登錄
- QQ網站和appQQ賬號的統一問題解決
- 微信登錄
- QQ登錄
- 微博登錄
- 上拉加載、下拉刷新模塊
- 圖片緩存
- 文件和圖片緩存機制分享
- PHP
- 支付寶及時到賬
- no input file specified報錯解決
- thinkphp 整合kindeditor
- 整合tpshop微信模塊到thinkcmf中
- thinkphp3.1.3整合支付寶
- 網站接入QQ OAuth2.0登錄教程
- ThinkPHP整合百度編輯器Ueditor
- PHP加快執行效率的寫法規范
- ThinkPHP操作大全
- PHP操作大全
- Thinkphp中SQL操作返回值
- php5.3 foreach 使用&(與運算符)引用賦值要注意的問題
- mysql給字段追加值
- 阿里大魚短信平臺接入
- Navicat 導出 Mysql 數據字典
- php 面向對象全面教程
- PHP5下調用SOAP
- PHP處理時間格式添加空格
- 偽裝URL請求(.htaccess)
- url請求參數加解密
- JS插件
- artDialog彈窗-頁面傳值
- jQuery點擊遮罩彈出層固定居中
- jeBox原生彈窗
- bxslider輪播
- js生成指定位數隨機數
- 發送短信倒計時
- js調試
- jQuery.validator 表單驗證規則
- Swiper 輪播
- 獲得焦點時-圖片抖動
- uploadify無刷新上傳圖片
- 導航下拉隱藏上拉顯示
- 獲得焦點時-加黑色蒙版
- jquery.qrcode.js生成二維條形碼(支持中文)
- jquery.qrcode.js生成二維條形碼(官方不支持中文)
- nth-child 選擇器
- 無刷新點擊實現加載更多數據
- 刷新頁面方法
- 判斷滾動條向上向下
- 跨瀏覽器復制jQuery-zclip
- js校驗表單后提交表單的三種方法
- 用JS判斷下拉框是否選中
- div中滾動
- 提交時彈出模態框
- 當圖片不顯示時替換方法
- 前端
- CSS3
- HTML5
- css技巧
- 移動端rem
- Flex布局
- 電商詳情滾動條監聽
- VueCircleMenu圓環按鈕
- iframe自適應頁面高度
- 百度Echart
- input:radio改變選中顏色
- Jquery
- 響應式布局基本實現Media Query
- 循環輸出只輸出新內容
- 小程序
- wx.request坑
- 概要
- git操作
- 本地記住密碼
- 操作
- 生成ssh公鑰 記住密碼
- git避坑
- ES6學習手札
- 調試小插件
- 谷歌插件Postman
- PHP調試助手
- WordPress
- 緩存服務器Redis
- 在線代碼運行 Docker
- 在ubuntu下怎樣安裝https
- BrowserSync 瀏覽器同步測試工具
- getmarkman高效的設計稿標注、測量工具
- PHPstrom軟件
- 服務器
- linux 安裝搭建服務器配置及nginx配置
- tpshop的nginx 服務器配置方法
- (服務器訪問文件404解決辦法)IIS 之 添加MIME擴展類型及常用的MIME類型列表
- mysql部分
- mysql緩存
- MySql監控工具--mytop
- MySql主從搭建
- mysql優化
- Mysql 復制 (主從復制)
- iOS開發筆記 - 上線流程
- VUE避坑指南
- 從零開始學Vue
- Vue-cli
- Webpack
- VUE小記
- npm打包空白
- 打包背景圖片/項目圖片不顯示
- VUE避坑指南/elementUI upload 自定義http-request上傳
- 關于watch監聽路由重復加載方法
- 解決加載內容的時候閃動問題
- vuecli沒有network訪問地址
- python學習
- python初始
- pytho內置函數大全
- win10 播放器播放TS文件問題
- 設計網站
- VUE避坑指南/VUE-CLI部署空白
- swiper使用問題
- uni-app學習手冊
- 目錄結構
- layUI
- nodesass版本sassloader版本問題