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