一、迭代器與生成器
迭代器是一個可以記住遍歷的位置的對象,迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束,迭代器只能往前不會後退。迭代器有兩個基本的方法:iter() 和 next(),字符串,列表或元組對象都可用於創建迭代器:
#!/usr/bin/python3
list=[1,2,3,4]
it = iter(list) # 創建迭代器對象
for x in it:
print (x, end=" ")
執行以上程序,輸出結果如下:
1 2 3 4
可以使用 next() 函數:
#!/usr/bin/python3
import sys # 引入 sys 模塊
list=[1,2,3,4]
it = iter(list) # 創建迭代器對象
while True:
try:
print (next(it))
except StopIteration:
sys.exit()
執行以上程序,輸出結果如下:
1
2
3
4
創建一個迭代器:
把一個類作爲一個迭代器使用需要在類中實現兩個方法 iter() 與 next() ,Python 的構造函數爲 init(), 它會在對象初始化的時候執行;
iter() 方法返回一個特殊的迭代器對象, 這個迭代器對象實現了 next() 方法並通過 StopIteration 異常標識迭代的完成。
next() 方法(Python 2 裏是 next())會返回下一個迭代器對象。
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
StopIteration 異常用於標識迭代的完成,防止出現無限循環的情況,在 next() 方法中我們可以設置在完成指定循環次數後觸發 StopIteration 異常來結束迭代。
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)
在 Python 中,使用了 yield 的函數被稱爲生成器(generator)在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回 yield 的值, 並在下一次執行 next() 方法時從當前位置繼續運行。調用一個生成器函數,返回的是一個迭代器對象。
二、函數
- 函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()
- 任何傳入參數和自變量必須放在圓括號中間,圓括號之間可以用於定義參數
- 函數內容以冒號起始,並且縮進
- return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None
def 函數名(參數列表):
函數體
#!/usr/bin/python3
# 計算面積函數
def area(width, height):
return width * height
def print_welcome(name):
print("Welcome", name)
print_welcome("Runoob")
w = 4
h = 5
print("width =", w, " height =", h, " area =", area(w, h))
函數調用
定義一個函數:給了函數一個名稱,指定了函數裏包含的參數,和代碼塊結構。
#!/usr/bin/python3
# 定義函數
def printme( str ):
# 打印任何傳入的字符串
print (str)
return
# 調用函數
printme("我要調用用戶自定義函數!")
printme("再次調用同一函數")
參數傳遞
在 python 中,類型屬於對象,變量是沒有類型的:
a=[1,2,3]
a="Runoob"
以上代碼中,[1,2,3] 是 List 類型,“Runoob” 是 String 類型,而變量 a 是沒有類型,她僅僅是一個對象的引用(一個指針),可以是指向 List 類型對象,也可以是指向 String 類型對象。
在 python 中,strings, tuples, 和 numbers 是不可更改的對象,而 list,dict 等則是可以修改的對象
- 不可變類型:類似 c++ 的值傳遞,如 整數、字符串、元組。如fun(a),傳遞的只是a的值,沒有影響a對象本身。比如在 fun(a)內部修改 a 的值,只是修改另一個複製的對象,不會影響 a 本身。
- 可變類型:類似 c++ 的引用傳遞,如 列表,字典。如 fun(la),則是將 la 真正的傳過去,修改後fun外部的la也會受影響
不可變類型
實例中有 int 對象 2,指向它的變量是 b,在傳遞給 ChangeInt 函數時,按傳值的方式複製了變量 b,a 和 b 都指向了同一個 Int 對象,在 a=10 時,則新生成一個 int 值對象 10,並讓 a 指向它。
可變類型
可變對象在函數裏修改了參數,那麼在調用這個函數的函數裏,原始的參數也被改變了。
參數
- 必需參數
- 關鍵字參數
- 默認參數
- 不定長參數
1、必需參數
必需參數須以正確的順序傳入函數。調用時的數量必須和聲明時的一樣。
#!/usr/bin/python3
#可寫函數說明
def printme( str ):
"打印任何傳入的字符串"
print (str)
return
# 調用 printme 函數,不加參數會報錯
printme()
2、關鍵字參數
關鍵字參數和函數調用關係緊密,函數調用使用關鍵字參數來確定傳入的參數值。
#!/usr/bin/python3
#可寫函數說明
def printinfo( name, age ):
"打印任何傳入的字符串"
print ("名字: ", name)
print ("年齡: ", age)
return
#調用printinfo函數
printinfo( age=50, name="runoob" )
3、默認參數
調用函數時,如果沒有傳遞參數,則會使用默認參數。以下實例中如果沒有傳入 age 參數,則使用默認值:
#!/usr/bin/python3
#可寫函數說明
def printinfo( name, age = 35 ):
"打印任何傳入的字符串"
print ("名字: ", name)
print ("年齡: ", age)
return
#調用printinfo函數
printinfo( age=50, name="runoob" )
print ("------------------------")
printinfo( name="runoob" )
4、不定長參數
你可能需要一個函數能處理比當初聲明時更多的參數。這些參數叫做不定長參數,和上述 2 種參數不同,聲明時不會命名。
加了星號 * 的參數會以元組(tuple)的形式導入,存放所有未命名的變量參數。
#!/usr/bin/python3
# 可寫函數說明
def printinfo( arg1, *vartuple ):
"打印任何傳入的參數"
print ("輸出: ")
print (arg1)
print (vartuple)
# 調用printinfo 函數
printinfo( 70, 60, 50 )
還有一種就是參數帶兩個星號 **,會以字典的形式導入。
#!/usr/bin/python3
# 可寫函數說明
def printinfo( arg1, **vardict ):
"打印任何傳入的參數"
print ("輸出: ")
print (arg1)
print (vardict)
# 調用printinfo 函數
printinfo(1, a=2,b=3)
聲明函數時,參數中星號 * 可以單獨出現,例如:
def f(a,b,*,c):
return a+b+c
如果單獨出現星號 * 後的參數必須用關鍵字傳入。
匿名函數
python 使用 lambda 來創建匿名函數。
- lambda 只是一個表達式,函數體比 def 簡單很多,僅僅能在lambda表達式中封裝有限的邏輯進去。
- lambda 函數擁有自己的命名空間,且不能訪問自己參數列表之外或全局命名空間裏的參數。
lambda [arg1 [,arg2,.....argn]]:expression
#!/usr/bin/python3
# 可寫函數說明
sum = lambda arg1, arg2: arg1 + arg2
# 調用sum函數
print ("相加後的值爲 : ", sum( 10, 20 ))
print ("相加後的值爲 : ", sum( 20, 20 ))
return語句
return [表達式] 語句用於退出函數,選擇性地向調用方返回一個表達式。不帶參數值的return語句返回None。
#!/usr/bin/python3
# 可寫函數說明
def sum( arg1, arg2 ):
# 返回2個參數的和."
total = arg1 + arg2
print ("函數內 : ", total)
return total
# 調用sum函數
total = sum( 10, 20 )
print ("函數外 : ", total)