python函数详解
寫在篇前
??函數能提高應用的模塊性,和代碼的重復利用率,是編程必須具備的基本抽象能力。python函數更是奇妙靈活,與很多特性值得探討,本篇文章就來詳細看看python 函數那些巧妙之處。首先,在篇前簡單說說python函數的形式。比如說我們要實現一個函數:計算一個數m的n次方,那么函數可以定義如下:
def exponentiation(m, n):return m^n# def 是函數定義關鍵字 # exponentiation 是函數名 # (m,n)是函數參數,后面冒號之后是函數體 # return 表示返回值,一個函數也可以沒有函數體,此時返回值為None函數參數
-
必選參數
?必選參數,又稱為位置參數,我們上面定義的函數exponentiation中m, n 就是必選參數。當調用該函數時,每一個必選參數都必須傳入合適的值。
-
默認參數
?修改函數exponentiation為:
def exponentiation(m, n=2):return m^n?這樣,n便是一個默認參數,當計算一個數的二次方時,只需要傳入參數m即可:
>>> exponentiation(3) 9?需要注意的是,必選參數必須在前,默認參數在后,否則Python的解釋器會報錯;為了避免不必要的坑,默認參數必須指向不變對象。 另外,在函數定義的時候就會確定默認參數的值,當我們改變x的值的時候對默認參數值并沒有影響,即:
>>> x = 42 >>> def spam(a, b=x): ... print(a, b) ... >>> spam(1) 1 42 >>> x = 23 >>> spam(1) 1 42 >>> -
可變參數
??可變參數是python函數靈活性的表現之一,如果有這樣一個需求,編寫一個函數計算若干個數的和,這時可變參數便是一種好的選擇:
def calc_sum(*args):sum = 0for arg in args:sum += argreturn sumprint(calc_sum(1, 2, 3)) # 可變參數可傳入0個或任意個參數,在函數調用時自動組裝為一個tuple nums = [1, 2, 3] print(calc_sum(*nums)) # *nums意思是將nums中的所有元素以可變參數的形式傳入函數 -
關鍵字參數
?關鍵字參數允許你傳入0個或任意個含參數名的參數,在函數內部會自動組裝為一個dict。
def print_info(pc_id, pc_name, **kwargs):print(pc_id, pc_name, kwargs, sep='\n')other_info = {'city': 'NanJing', 'company': 'APPLE'} print_info('0001', 'IMac-2018', city='NanJing', company='APPLE') print_info('0001', 'IMac-2018', **other_info)0001 IMac-2018 {'city': 'NanJing', 'company': 'APPLE'} 0001 IMac-2018 {'city': 'NanJing', 'company': 'APPLE'}
?關鍵字參數可以傳入任意參數名,那我們可不可以限制他傳入指定的參數名呢?答案是當然可以,采用命名關鍵字可以實現該需求。但是這里需要搞清楚一個邏輯上的問題。這里的指定的參數名要和前面的必選參數區分開來。命名關鍵字參數如果有默認值可以不傳入,但是如果傳入就只能是已經限定的關鍵字參數。
def print_info(pc_id, pc_name, *, city, company):# 用一個 *,區分必選參數和關鍵字參數print("pc_id: %s\tpc_name: %s" % (pc_id, pc_name), end='\t')if city:print('city:%s' % city, end='\t')if company:print('company:%s' % company)other_info = {'city': 'NanJing', 'company': 'APPLE'}print_info('0001', 'IMac-2018', city='NanJing', company='APPLE') print_info('0001', 'IMac-2018', **other_info)# 但是如果函數定義中已經有了一個可變參數,命名關鍵字參數就不再需要分隔符*了 # def print_info(pc_id, pc_name, *args, city, company):-
小結
以上四種參數可以靈活的進行組合應用,需要注意的是,參數定義的順序必須是:必選參數、默認參數、可變參數、(命名關鍵字參數)關鍵字參數。
def f(a, b, c=0, *args, **kw):print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
特殊函數
匿名函數
??在python中可以通過lambda來定義匿名函數,其返回一個函數表達式,類似于def,但是比def更輕巧,可以沒有名字。
# 關鍵字`lambda`表示匿名函數,冒號前面的`x`,`y`表示函數參數 # 匿名函數有個限制:只能有一個表達式,不用寫return,返回值就是該表達式的結果。 >>>add = lambda x,y: x+y >>>add(2,3) 5?需要注意的是,lambda表達式中的參數x、y等是自由變量, 在運行時綁定值,而不是定義時就綁定,這跟函數的默認值參數定義是不同的。 因此在下面例子中,調用這個lambda表達式的時候,x的值是執行時的值。
>>> x = 10 >>> a = lambda y: x + y >>> x = 20 >>> b = lambda y: x + y >>> a(10) 30 >>> b(10) 30高階函數
??一個函數接收另一個函數作為參數,這種函數稱之為高階函數(Higher-order Functions)。python中有幾個常用的內置高階函數:
-
filter
?filter() 函數接收兩個參數,一個函數和一個序列,其中傳入的函數會依次作用于序列的每一個元素,根據返回值是True或則False決定是否保留該元素。
filter(lambda x: x>10, [1, 56, 3, 36, 9])>>> g = filter(lambda x: x>10, [1, 56, 3, 36, 9]) >>> g <filter object at 0x10207b470> >>> type(g) <class 'filter'> >>> list(g) [56, 36] -
map/reduce
??map()函數接收兩個參數,一個是函數,一個是Iterable,map將傳入的函數依次作用到序列的每個元素,并把結果作為新的Iterator返回;reduce() 把一個函數作用在一個序列[x1, x2, x3, …]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算。
>>> r = map(lambda x:x*x, [1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> type(r) <class 'map'> >>> list(r) [1, 4, 9, 16, 25, 36, 49, 64, 81]from functools import reduce >>>reduce(lambda x,y: x+y, [1,2,3,4]) 10 -
sorted
??用于可迭代對象的排序,如:
# 實例1 >>> sorted([36, 5, -12, 9, -21], key=abs) [5, 9, -12, -21, 36] -
返回函數
??高階函數除了可以接受函數作為參數,也可以將函數作為返回值,實現“延遲計算”。
def calc_sum(lst):def lazy_sum():return sum(lst)return lazy_sum>>> f = calc_sum([1, 2, 3, 4]) >>>f <function calc_sum.<locals>.lazy_sum at 0x10e9bd158> >>>f() 10
偏函數
??偏函數的作用是為函數某些參數設置默認值,使調用更加方便,以下會是一個好的例子:
points = [ (1, 2), (3, 4), (5, 6), (7, 8) ] import math def distance(p1, p2):x1, y1 = p1x2, y2 = p2return math.hypot(x2 - x1, y2 - y1) >>> pt = (4, 3) >>> points.sort(key=partial(distance,p2=pt)) # 注意這里必須是p2=pt >>> points [(3, 4), (1, 2), (5, 6), (7, 8)]回調函數
??在計算機程序設計中,回調函數,是指通過函數參數傳遞到其它代碼的,某一塊可執行代碼的引用。這一設計允許了底層代碼調用在高層定義的子程序。關于理解可以參考回調函數是什么。這里我們也給出一個例子輔助理解:
def greeting(name):print('hello %s!' % name)def someone_coming(callback):name = input()callback(name)def main():someone_coming(greeting)if __name__ == '__main__':main()內置函數
??這里確切的應該說是其他內置函數,因為上面也涉及很多內置函數,如sorted、filter、map等。另外,python內置函數非常之多,如果想了解更全面的內部函數,可以參考內置函數1,內置函數2
-
zip()
?用于將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表。需要注意的是,當多個可迭代數據length不同時,取最小長度,其他忽略。
>>>a = [1,2,3] >>> b = [4,5,6] >>> c = [4,5,6,7,8] >>> zipped = zip(a,b) # 打包為元組的列表 [(1, 4), (2, 5), (3, 6)] >>> zip(a,c) # 元素個數與最短的列表一致 [(1, 4), (2, 5), (3, 6)] >>> zip(*zipped) # 與 zip 相反,*zipped 可理解為解壓,返回二維矩陣式 [(1, 2, 3), (4, 5, 6)] -
reversed()
?用于反轉序列,生成新的可迭代對象
>>> a = reversed(range(10)) # 傳入range對象 >>> a # 類型變成迭代器 <range_iterator object at 0x035634E8> >>> list(a) [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] -
enumerate()
?enumerate() 函數用于將一個可遍歷的數據對象(如列表、元組或字符串)組合為一個索引序列,同時列出數據和數據下標,一般用在 for 循環當中
>>>seq = ['one', 'two', 'three'] >>> for i, element in enumerate(seq): ... print i, element0 one 1 two 2 three
總結
以上是生活随笔為你收集整理的python函数详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Shell脚本编程详解
- 下一篇: websocket python爬虫_p