摘要:我們常用的內(nèi)置函數(shù)就是一個可變參數(shù)函數(shù)。匿名函數(shù)返回一個函數(shù)對象,在可以作為函數(shù)參數(shù)傳遞給函數(shù)。定義函數(shù)時,可以為參數(shù)指定默認(rèn)值調(diào)用函數(shù)時,可以通過關(guān)鍵字參數(shù)調(diào)用。
上一節(jié)我們學(xué)習(xí)了函數(shù)的定義和調(diào)用,理解了基本的函數(shù)知識。本節(jié)進一步學(xué)習(xí)函數(shù)相關(guān)的更多內(nèi)容,深入了解函數(shù),包括:默認(rèn)參數(shù)、關(guān)鍵字參數(shù)、位置參數(shù)、變量的作用域等等。
形參和實參的不同首先,我們先搞清兩個概念:
形參(parameters),是定義函數(shù)時聲明的參數(shù)名稱,它定義了函數(shù)可以接受的參數(shù)類型;
實參(arguments),是調(diào)用函數(shù)時傳給函數(shù)的實際值。
比如下面的函數(shù)定義:
def func(foo, bar=True, **kwargs): pass
foo, bar, kwargs?是函數(shù)的形參(parameters)。
當(dāng)我們調(diào)用func時,比如:
func(20, bar=False, abc="xyz")
傳給函數(shù)的值20,False和"xyz"就是實參。
默認(rèn)參數(shù)值默認(rèn)參數(shù)就是在函數(shù)定義時,給參數(shù)一個默認(rèn)值。調(diào)用該函數(shù)時可以不給有默認(rèn)值的參數(shù)傳值,這樣調(diào)用時的參數(shù)可以減少。
看下面的例子:
def say_hi(name, greeting="Hi", more=""): print(greeting, name, more)
這個函數(shù)有三個參數(shù),其中greeting和more有默認(rèn)值,調(diào)用該函數(shù)時,有以下幾種形式:
只傳一個值給name: say_hi(‘Tom’)
給可選參數(shù)greeting傳值: say_hi(‘Tom’, ‘Hello’)
給所有參數(shù)傳值: say_hi(‘Tom’, ‘Hello’, ‘how are you’)
一個函數(shù)可以有任意多個默認(rèn)參數(shù),也可以全部參數(shù)都有默認(rèn)值。但是,沒有默認(rèn)值的參數(shù)不能在有默認(rèn)值的參數(shù)的后面,否則會報錯。也就是說,參數(shù)的先后順序必須是無默認(rèn)值參數(shù)在前,有默認(rèn)值參數(shù)在后面。
In [175]: def foo(a=1, b): ...: return a + b File "", line 1 def foo(a=1, b): ^ SyntaxError: non-default argument follows default argument
默認(rèn)參數(shù)值只生成一次,如果默認(rèn)值是可變對象比如list、dict、set等就會出現(xiàn)詭異的結(jié)果,使用時要非常留心。下面的例子,默認(rèn)值為一個空list,函數(shù)調(diào)用時它把第一個參數(shù)放到list里面。
def func(a, L=[]): L.append(a) return L print(func(1)) print(func(2)) print(func(3))
程序的輸出是:
[1] [1, 2] [1, 2, 3]
這是因為默認(rèn)值L在函數(shù)定義時生成,后面的調(diào)用(使用默認(rèn)值,不給L傳值)就會不斷給定義時生成的默認(rèn)list添加元素。
如果你希望使用這個詭異的特性也沒問題,但要清楚它是什么。通常我們不建議默認(rèn)值為可變對象,而是不可變的整數(shù)、浮點數(shù)、字符串等等。
關(guān)鍵字參數(shù)調(diào)用函數(shù)時,我們可以使用“關(guān)鍵字參數(shù)”,它的形式是:kwarg=value。比如前面的say_hi函數(shù)的調(diào)用:
In [180]: say_hi(name="Tom") Hi Tom In [181]: say_hi(name="Tom", greeting="Hello") Hello Tom In [182]: say_hi(name="Tom", more="how are you") Hi Tom how are you In [183]: say_hi(more="good day", name="Tom", greeting="Hi") Hi Tom good day
上面最后一個調(diào)用告訴我們,關(guān)鍵字參數(shù)是通過關(guān)鍵字來確認(rèn)參數(shù)的,所以可以不用按照函數(shù)定義時的順序傳遞參數(shù)。
關(guān)鍵字參數(shù)跟默認(rèn)參數(shù)類似有參數(shù)位置的限制,關(guān)鍵字參數(shù)后面必須都是關(guān)鍵字參數(shù)。
下面的調(diào)用都是無效的:
say_hi() # 缺少必須的參數(shù)name say_hi(name="Tom", "Hello") # 關(guān)鍵字參數(shù)后面出現(xiàn)了非關(guān)鍵字參數(shù) say_hi("Tom", name="Tim") # 同樣的參數(shù)傳了兩個值 say_hi(age=10) # 函數(shù)定義中不存在的關(guān)鍵字參數(shù)
如果函數(shù)定義的最后一個參數(shù)是兩個星號加名稱:**name,那么它接受一個字典包含所有關(guān)鍵字參數(shù),這個字典不包括name前面聲明的普通參數(shù):
In [190]: def foo(a, **kwargs): ...: print(a) ...: for k, v in kwargs.items(): ...: print("%s : %s" % (k, v)) ...: In [191]: foo(1) 1 In [192]: foo(a=1) 1 In [193]: foo(a=1, b=2, c=3, d=4, e="a") 1 b : 2 c : 3 d : 4 e : a
可見,**kwargs把a后面的所有關(guān)鍵字參數(shù)都接收了。這對我們以后寫參數(shù)非常多的函數(shù)時很有幫助。
可變參數(shù)列表可變參數(shù)列表類似關(guān)鍵字參數(shù)**kwargs,因為它沒有key只有value,所以它是一個序列(確切的說是一個tuple),它的形式是*args,名稱前面有一個星號*,用以接收不確定數(shù)量的參數(shù)。我們常用的內(nèi)置函數(shù)print就是一個可變參數(shù)函數(shù)。
下面我自己定義一個可變參數(shù)函數(shù):
In [197]: def foo(*args): ...: print(type(args)) ...: print("|".join(args)) ...: In [198]: foo("a", "b", "c", "d")a|b|c|d
同樣的,可變參數(shù)后面必須跟關(guān)鍵字參數(shù):
In [204]: def foo(*args, joiner="|"): ...: print(type(args)) ...: print(joiner.join(args)) ...: In [205]: foo("a", "b", "c", "d")解包參數(shù)列表a|b|c|d In [206]: foo("a", "b", "c", "d", joiner="/") a/b/c/d
這個正好跟可變參數(shù)列表相反,如果要調(diào)用的函數(shù)的參數(shù)值已經(jīng)在list或tuple里面了,我們可以通過解包list或tuple來給函數(shù)傳值。比如內(nèi)置的range()函數(shù)可以輸入兩個參數(shù):start和stop,如果它們在一個llist或tuple里面,可以通過*操作符解包來傳值:
In [207]: list(range(1, 8)) Out[207]: [1, 2, 3, 4, 5, 6, 7] In [208]: args = [1, 8] In [209]: list(range(*args)) Out[209]: [1, 2, 3, 4, 5, 6, 7]
同樣的,dict可以通過**操作符傳遞關(guān)鍵字參數(shù):
In [212]: d = {"name":"Tom", "greeting":"Hello", "more":"good day"} In [213]: say_hi(**d) Hello Tom good daylambda函數(shù)
通過關(guān)鍵字lambda來實現(xiàn)小的匿名函數(shù)。匿名函數(shù)返回一個函數(shù)對象,在可以作為函數(shù)參數(shù)傳遞給函數(shù)。比如內(nèi)置函數(shù)sorted中的key參數(shù)就接受一個函數(shù)對象。
In [215]: func = lambda a, b: a * b In [216]: func(1,2) Out[216]: 2 In [217]: func(3,5) Out[217]: 15
再看看sorted使用lambda函數(shù)的情況,先對學(xué)生按姓名排序,再按年齡排序:
In [218]: students = [ ...: {"name": "Tom", "age": 12}, ...: {"name": "Jack", "age": 13}, ...: {"name": "Aby", "age": 10},] In [219]: sorted(students, key=lambda s: s["name"]) Out[219]: [{"name": "Aby", "age": 10}, {"name": "Jack", "age": 13}, {"name": "Tom", "age": 12}] In [220]: sorted(students, key=lambda s: s["age"]) Out[220]: [{"name": "Aby", "age": 10}, {"name": "Tom", "age": 12}, {"name": "Jack", "age": 13}]變量的作用域和生命周期
程序中的變量不是在任何地方都可見的,它有自己的作用域。
局部變量定義在函數(shù)內(nèi)部的變量只在函數(shù)內(nèi)部可見,也就是說,它是函數(shù)的局部變量。
In [1]: def func(): ...: x = "hello" ...: print(x) ...: In [2]: func() hello In [3]: x ------------------------ NameError Traceback (most recent call last)in ----> 1 x NameError: name "x" is not defined
x是func內(nèi)部的一個變量,對該函數(shù)內(nèi)部可見,所以print(x)語句能打印x的值。但是在函數(shù)外部訪問x時就會報錯:x是未定義的。
全局變量相對于局部變量,全局變量是定義在函數(shù)外部的,它具有全局作用域。
In [4]: x = "hello" In [5]: def func2(): ...: print(x) ...: In [6]: func2() hello In [7]: x Out[7]: "hello"
如果要在函數(shù)內(nèi)部修改全局變量,就需要用關(guān)鍵字global來聲明全局變量:
In [8]: def func3(): ...: global x ...: x += "world" ...: print(x) ...: In [9]: func3() helloworld In [10]: x Out[10]: "helloworld"
局部變量變量的生命周期從函數(shù)調(diào)用開始,到函數(shù)運行結(jié)束為止;全局變量的生命周期直到整個程序結(jié)束為止。
刪除函數(shù)前面的章節(jié)中,我們使用關(guān)鍵字del來刪除列表或其中的元素,它同樣可以用來刪除函數(shù):
In [11]: def func4(): ...: print("func4") ...: In [12]: func4() func4 In [13]: del func4 In [14]: func4() ------------------- NameError Traceback (most recent call last)in ----> 1 func4() NameError: name "func4" is not defined
在Python中,函數(shù)也是對象,所以用del刪除函數(shù)就跟刪除其它對象一樣。
文檔字符串(docstring)作為類、函數(shù)或模塊之內(nèi)的第一個表達式出現(xiàn)的字符串字面值。它在代碼執(zhí)行時會被忽略,但會被解釋器識別并放入所在類、函數(shù)或模塊的?doc?屬性中。由于它可用于代碼內(nèi)省,因此是對象存放文檔的規(guī)范位置。
In [15]: def my_func(): ...: """first line is summary of this function ...: ...: the more lines are details of this function ...: """ ...: pass ...: In [16]: print(my_func.__doc__) first line is summary of this function the more lines are details of this function
寫docstring的規(guī)則一般是這樣的:
(1)第一行簡短概述該函數(shù)或類的功能
(2)第二行空白
(3)后面幾行詳細(xì)描述函數(shù)的參數(shù)、返回值等等
定義函數(shù)時,參數(shù)稱為“形參”,表述參數(shù)的類型;調(diào)用函數(shù)時,參數(shù)為“實參”,是傳給函數(shù)的具體值。
定義函數(shù)時,可以為參數(shù)指定默認(rèn)值;調(diào)用函數(shù)時,可以通過關(guān)鍵字參數(shù)調(diào)用。
定義函數(shù)是,可以指定參數(shù)為可變參數(shù)列表?*args或**kwargs;調(diào)用函數(shù)時,可以通過解包list,tuple和dict來傳入?yún)?shù)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/43788.html
摘要:以下這些項目,你拿來學(xué)習(xí)學(xué)習(xí)練練手。當(dāng)你每個步驟都能做到很優(yōu)秀的時候,你應(yīng)該考慮如何組合這四個步驟,使你的爬蟲達到效率最高,也就是所謂的爬蟲策略問題,爬蟲策略學(xué)習(xí)不是一朝一夕的事情,建議多看看一些比較優(yōu)秀的爬蟲的設(shè)計方案,比如說。 (一)如何學(xué)習(xí)Python 學(xué)習(xí)Python大致可以分為以下幾個階段: 1.剛上手的時候肯定是先過一遍Python最基本的知識,比如說:變量、數(shù)據(jù)結(jié)構(gòu)、語法...
摘要:調(diào)用函數(shù)就是通過函數(shù)名再傳入它需要的參數(shù)即可。遞歸函數(shù)遞歸函數(shù)就是函數(shù)自己調(diào)用自己。我們以計算一個整數(shù)的階乘來看看遞歸函數(shù)是什么樣子的。階乘的公式如下它的遞歸函數(shù)的定義如下遞歸函數(shù)都有一個跳出遞歸的條件,在本函數(shù)中就是。 函數(shù),是編程中很重要的一個概念。簡單來說,函數(shù)是一段可重復(fù)使用的代碼段,給這段代碼起個名字就是函數(shù)名。在程序的任何地方都可以通過函數(shù)名來使用這段代碼,這就是函數(shù)調(diào)用。...
摘要:計算機編程中,會經(jīng)常涉及輸入輸出,輸入輸出。提供功能的設(shè)備就是輸入輸出設(shè)備,比如,鍵盤,鼠標(biāo)就是典型的輸入設(shè)備,顯示器就是典型的輸出設(shè)備。的語言提供了方便的輸入輸入和輸出印刷函數(shù)。 計算機編程中,會經(jīng)常涉及輸入輸出(IO,輸入/輸出)。提供IO功能的設(shè)備就是輸入輸出設(shè)備,比如,鍵盤,鼠標(biāo)就是典型的輸入設(shè)備,顯示器就是典型的輸出設(shè)備。程序在運行過程中,數(shù)據(jù)存儲在內(nèi)存中,但有時候它需要用戶...
摘要:首先,在學(xué)習(xí)之前一定會考慮一個問題版本選擇對于編程零基礎(chǔ)的人來說,選擇。建議從下面課程開始教程標(biāo)準(zhǔn)庫官方文檔非常貼心地提供中文翻譯首先需要學(xué)習(xí)的基礎(chǔ)知識,下載安裝導(dǎo)入庫字符串處理函數(shù)使用等等。 提前說一下,這篇福利多多,別的不說,直接讓你玩回最有手感的懷舊游戲,參數(shù)貼圖很方便自己可以根據(jù)喜好修改哦。 本篇通過以下四塊展開,提供大量資源對應(yīng)。 showImg(https://segmen...
摘要:第二個索引元素不在分片內(nèi)。顯示操作索引指向第個元素,第個元素不存在。序列加法乘法表示個空列表空列表用初始化成員資格運算符布爾運算符,檢查值是否在序列中。修改列表,沒有返回值。在原位置對列表排序。 序列 例: Edward = [abc, 12] 序列中的所有元素都是有編號的,從0開始遞增。 Note: 使用負(fù)數(shù)索引-1,Python會從右邊,也就是從最后一個元素開始計數(shù)。最后一個元素...
閱讀 823·2021-09-07 09:58
閱讀 2681·2021-08-31 09:42
閱讀 2854·2019-08-30 14:18
閱讀 3086·2019-08-30 14:08
閱讀 1831·2019-08-30 12:57
閱讀 2757·2019-08-26 13:31
閱讀 1298·2019-08-26 11:58
閱讀 1052·2019-08-23 18:06