標籤:意義 其他 指定 ace one == 調用 方式 元素
Python3 函數
函數是組織好的,可重複使用的,用來實現單一,或相關聯功能的程式碼片段。
函數能提高應用的模組性,和代碼的重複利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己建立函數,這被叫做使用者自訂函數。
定義一個函數
你可以定義一個由自己想要功能的函數,以下是簡單的規則:
- 函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括弧 ()。
- 任何傳入參數和自變數必須放在圓括弧中間,圓括弧之間可以用於定義參數。
- 函數的第一行語句可以選擇性地使用文檔字串—用於存放函數說明。
- 函數內容以冒號起始,並且縮排。
- return [運算式] 結束函數,選擇性地返回一個值給調用方。不帶運算式的return相當於返回 None。
參數傳遞
在 python 中,類型屬於對象,變數是沒有類型的:
a=[1,2,3]a="Runoob"
以上代碼中,[1,2,3] 是 List 類型,"Runoob" 是 String 類型,而變數 a 是沒有類型,她僅僅是一個對象的引用(一個指標),可以是指向 List 類型對象,也可以是指向 String 類型對象。
可更改(mutable)與不可更改(immutable)對象
在 python 中,strings, tuples, 和 numbers 是不可更改的對象,而 list,dict 等則是可以修改的對象。
- 不可變類型:變數賦值 a=5 後再賦值 a=10,這裡實際是新產生一個 int 值對象 10,再讓 a 指向它,而 5 被丟棄,不是改變a的值,相當於新產生了a。
- 可變類型:變數賦值 la=[1,2,3,4] 後再賦值 la[2]=5 則是將 list la 的第三個元素值更改,本身la沒有動,只是其內部的一部分值被修改了。
python 函數的參數傳遞:
- 不可變類型:類似 c++ 的值傳遞,如 整數、字串、元組。如fun(a),傳遞的只是a的值,沒有影響a對象本身。比如在 fun(a)內部修改 a 的值,只是修改另一個複製的對象,不會影響 a 本身。
- 可變類型:類似 c++ 的引用傳遞,如 列表,字典。如 fun(la),則是將 la 真正的傳過去,修改後fun外部的la也會受影響。
python 中一切都是對象,嚴格意義我們不能說值傳遞還是引用傳遞,我們應該說傳不可變對象和傳可變對象。
python 傳不可變對象執行個體:
#!/usr/bin/python3 def ChangeInt( a ): a = 10b = 2ChangeInt(b)print( b ) # 結果是 2
執行個體中有 int 對象 2,指向它的變數是 b,在傳遞給 ChangeInt 函數時,按傳值的方式複製了變數 b,a 和 b 都指向了同一個 Int 對象,在 a=10 時,則新產生一個 int 值對象 10,並讓 a 指向它。
傳可變對象執行個體:
可變對象在函數裡修改了參數,那麼在調用這個函數的函數裡,原始的參數也被改變了。例如:
#!/usr/bin/python3 # 可寫函數說明def changeme( mylist ): "修改傳入的列表" mylist.append([1,2,3,4]); print ("函數內取值: ", mylist) return # 調用changeme函數mylist = [10,20,30];changeme( mylist );print ("函數外取值: ", mylist)
傳入函數的和在末尾添加新內容的對象用的是同一個引用。故輸出結果如下:
函數內取值: [10, 20, 30, [1, 2, 3, 4]]函數外取值: [10, 20, 30, [1, 2, 3, 4]]
參數
以下是調用函數時可使用的正式參數類型:
必需參數
必需參數須以正確的順序傳入函數。調用時的數量必須和聲明時的一樣。
如調用printme()函數,你必須傳入一個參數,不然會出現語法錯誤:
#!/usr/bin/python3 #可寫函數說明def printme( str ): "列印任何傳入的字串" print (str); return; #調用printme函數printme();
以上執行個體輸出結果:
Traceback (most recent call last): File "test.py", line 10, in <module> printme();TypeError: printme() missing 1 required positional argument: ‘str‘
關鍵字參數
關鍵字參數和函數調用關係緊密,函數調用使用關鍵字參數來確定傳入的參數值。
使用關鍵字參數允許函數調用時參數的順序與聲明時不一致,因為 Python 解譯器能夠用參數名匹配參數值。
以下執行個體中示範了函數參數的使用不需要使用指定順序:
#!/usr/bin/python3 #可寫函數說明def printinfo( name, age ): "列印任何傳入的字串" print ("名字: ", name); print ("年齡: ", age); return; #調用printinfo函數printinfo( age=50, name="runoob" );
以上執行個體輸出結果:
名字: runoob年齡: 50
預設參數
調用函數時,如果沒有傳遞參數,則會使用預設參數。以下執行個體中如果沒有傳入 age 參數,則使用預設值:
def printinfo(name, age=35): print ("名字: ", name); print ("年齡: ", age); return;printinfo(‘alex‘)
輸出結果:
名字: alex年齡: 35
參數預設值的繼承性
#! /usr/bin/env python# -*- coding: utf-8 -*-class demo_list: def __init__(self, l=[]): print(id(l),x=‘‘) self.l = l def add(self, ele): self.l.append(ele)def appender(ele): obj = demo_list() obj.add(ele) print obj.lif __name__ == "__main__": for i in range(5): appender(i)
輸出結果為:
4346933688 [0]
4346933688 [0, 1]
4346933688 [0, 1, 2]
4346933688 [0, 1, 2, 3]
4346933688 [0, 1, 2, 3, 4]
可以清晰看出每次調用__init__函數時,預設參數l都是同一個對象,其id為4346933688。
關於預設參數,文檔中是這樣說的:
Functions in Python are first-class objects, and not only a piece of code.
我們可以這樣解讀:函數也是對象,因此定義的時候就被執行,預設參數是函數的屬性,它的值可能會隨著函數被調用而改變。其他對象不都是如此嗎?
帶*的參數:用來接受可變數量參數
目前為止,我們要定義一個函數的時候,必須要預先定義這個函數需要多少個參數(或者說可以接受多少個參數)。一般情況下這是沒問題的,但是也有在定義函數的時候,不能知道參數個數的情況(想一想C語言裡的printf函數),在Python裡,帶*的參數就是用來接受可變數量參數的。看一個例子:
def funcD(a, b, *c): print(a) print(b) print("length of c is: %d " % len(c)) print(c)funcD(1,2,3,4,5,6)
結果:
12length of c is: 4 (3, 4, 5, 6)
我們看到,前面兩個參數被a、b接受了,剩下的4個參數,全部被c接受了,c在這裡是一個tuple。我們在調用funcD的時候,至少要傳遞2個參數,2個以上的參數,都放到c裡了,如果只有兩個參數,那麼c就是一個empty tuple。
func(*args) 傳入的參數為以元組形式存在args中
def f(*args): print(args) print(type(args))f(1,2,3)f(*[4,5,6]) # 這個方式可以直接將一個列表的所有元素當作不定參數
結果:
(1, 2, 3)<class ‘tuple‘>(4, 5, 6)<class ‘tuple‘>
func( **kwargs)傳入的參數為以字典形式存在args中
def f(**args): print(args) print(type(args))f(a=1,b=2,c=3)f(**{‘d‘:4,‘e‘:5,‘f‘:6}) # 這個方式可以直接傳入將一個字典的所有索引值當作關鍵字參數
結果:
{‘a‘: 1, ‘b‘: 2, ‘c‘: 3}<class ‘dict‘>{‘d‘: 4, ‘e‘: 5, ‘f‘: 6}<class ‘dict‘>
func(*args, **kwargs)
傳入的順序必須和定義順序相同,這裡是先不定參數列表,再是關鍵字參數字典,如:
帶**的參數:
如果一個函數定義中的最後一個形參有 ** (雙星號)首碼,所有正常形參之外的其他的關鍵字參數都將被放置在一個字典中傳遞給函數,比如:
def funcF(a, **b): print(a) for x in b: print(x + ": " + str(b[x]))funcF(100, c=‘你好‘, b=200)
結果:
100c: 你好b: 200
可以看到,b是一個dict對象執行個體,它接受了關鍵字參數b和c。
有關*和**的最本質的意義:
在python中的函數,我們要注意兩個特點,一個就關鍵字參數,一個就是任意參數。任意參數的本質意義是讓函數能夠接受任意多個參數,它的本質意義是用*args表示一個集合,等到這個參數賦值的時候,它會儘可能的接收它能接受的參數,形成一個集合。
也就是說,實際上,假設函數的形參還是與實參的個數是對應的,而*args的引入,就代表*args,表示有0到任意多個形參。同理**args(他是一個字典集合)。
Python學習 Day7 Python3 函數