主頁 > 後端開發 > 07-Python函式詳解

07-Python函式詳解

2020-09-28 21:01:29 後端開發

函式(Function)是指可重復使用的程式片段,它們允許你為某個代碼塊賦予名字,允許你 通過這一特殊的名字在你的程式任何地方來運行代碼塊,并可重復任何次數,這就是所謂的 呼叫函式,

我們已經使用過了許多內置的函式,例如 len 和 range ,

函式可以通過關鍵字 def 來定義,這一關鍵字后跟一個函式的識別符號名稱,再跟一對圓括 號,其中可以包括一些變數的名稱,再以冒號結尾,結束這一行,

隨后而來的陳述句塊是函式 的一部分,下面的案例將會展示出這其實非常簡單:

def say_hello(): 
# 該塊屬于這一函式 
    print('hello world') 
# 函式結束
say_hello() # 呼叫函式 
say_hello() # 再次呼叫函式


輸出:

hello world hello world

它是如何作業的

我們以上文解釋過的方式定義名為 say_hello 的函式,這個函式不使用引數,因此在括號中 沒有宣告變數,函式的引數只是輸入到函式之中,以便我可以傳遞不同的值給它,并獲得相 應的結果,

要注意到我們可以兩次呼叫相同的函式,這意味著我們不必重新把代碼再寫一次,

函式引數

函式中的引數通過將其放置在用以定義函式的一對圓括號中指定,并通過逗號予以分隔,當 我們呼叫函式時,我們以同樣的形式提供需要的值,要注意在此使用的術語——在定義函式 時給定的名稱稱作“形參”(Parameters),在呼叫函式時你所提供給函式的值稱作“實 參”(Arguments),

def print_max(a, b): 
    if a > b: 
            print(a, '是比較大的數') 
    elif a == b: 
            print(a, '等于', b) 
    else:
            print(b, '是比較大的數')
# 直接傳遞字面值 
print_max(3, 4)
x = 5 
y = 7 

輸出

4 是比較大的數7 是比較大的數

它是如何作業的

在這里,我們將函式命名為 print_max 并使用兩個引數分別稱作 a 和 b ,我們使用一個 簡單的 if...else 陳述句來找出更大的那個數,并將它列印出來,

第一次呼叫函式 print_max 時,我們以實參的形式直接向函式提供這一數字,

在第二次呼叫 時,我們將變數作為實參來呼叫函式,print_max(x, y) 將使得實參 x 的值將被賦值給形參 a ,而實參 y 的值將被賦值給形參 b ,在兩次呼叫中, print_max 都以相同的方式工 作,

區域變數

當你在一個函式的定義中宣告變數時,它們不會以任何方式與身處函式之外但具有相同名稱 的變數產生關系,也就是說,這些變數名只存在于函式這一區域(Local),

這被稱為變數的 作用域(Scope),

所有變數的作用域是它們被定義的塊,從定義它們的名字的定義點開始,

案例:

x = 50 
def func(x): 
    print('x 是:', x) 
    x = 2 
    print('改變區域變數x為', x) 

func(x)
print('x 仍然為', x)

輸出:

x 為:50改變區域變數x為 2x 仍然為 50

它是如何作業的

當我們第一次列印出存在于函式塊的第一行的名為 x 的值時,Python 使用的是在函式宣告 之上的主代碼塊中宣告的這一引數的值,

接著,我們將值 2 賦值給 x ,x 是我們這一函式的區域變數,因此,當我們改變函式中 x 的值的時候,主代碼塊中的 x 則不會受到影響,

隨著最后一句 print 陳述句,我們展示出主代碼塊中定義的 x 的值,由此確認它實際上不受 先前呼叫的函式中的區域變數的影響,

global 陳述句

如果你想給一個在程式頂層的變數賦值(也就是說它不存在于任何作用域中,無論是函式還 是類),那么你必須告訴 Python 這一變數并非區域的,而是全域(Global)的,

我們需要通 過 global 陳述句來完成這件事,因為在不使用 global 陳述句的情況下,不可能為一個定義于 函式之外的變數賦值,

你可以使用定義于函式之外的變數的值(假設函式中沒有具有相同名字的變數),然而,這 種方式不會受到鼓勵而且應該避免,因為它對于程式的讀者來說是含糊不清的,無法弄清楚 變數的定義究竟在哪,

而通過使用 global 陳述句便可清楚看出這一變數是在最外邊的代碼塊 中定義的,

案例:

x = 50
def func():
global x
    print('x 為:', x)
    x = 2
    print('改變全域變數為', x)
func()
print('x的值為', x)

輸出:

x 為: 50改變全域變數為 2x的值為 2

它是如何作業的

global 陳述句用以宣告 x 是一個全域變數——因此,當我們在函式中為 x 進行賦值時,這 一改動將影響到我們在主代碼塊中使用的 x 的值,

你可以在同一句 global 陳述句中指定不止一個的全域變數,例如 global x, y, z ,

默認引數值

對于一些函式來說,你可能為希望使一些引數可選并使用默認的值,以避免用戶不想為他們 提供值的情況,默認引數值可以有效幫助解決這一情況,

你可以通過在函式定義時附加一個 賦值運算子( = )來為引數指定默認引數值,

案例

def say(message, times=1):
    print(message * times)
say('Hello')
say('World', 5)

輸出

HelloWorldWorldWorldWorldWorld

它是如何作業的

名為 say 的函式用以按照給定的次數列印一串字串,如果我們沒有提供一個數值,則將按 照默認設定,只列印一次字串,我們通過為引數 times 指定默認引數值 1 來實作這一 點,

在第一次使用 say 時,我們只提供字串因而函式只會將這個字串列印一次,在第二次使 用 say 時,我們既提供了字串,同時也提供了一個引數 5 ,宣告我們希望說(Say)這 個字串五次,

注意

只有那些位于引數串列末尾的引數才能被賦予默認引數值,意即在函式的引數串列中擁 有默認引數值的引數不能位于沒有默認引數值的引數之前,

這是因為值是按引數所處的位置依次分配的,舉例來說, def func(a, b=5) 是有效的, 但 def func(a=5, b) 是無效的,

關鍵字引數

如果你有一些具有許多引數的函式,而你又希望只對其中的一些進行指定,那么你可以通過 命名它們來給這些引數賦值——這就是關鍵字引數(Keyword Arguments)——我們使用命 名(關鍵字)而非位置(一直以來我們所使用的方式)來指定函式中的引數

這樣做有兩大優點

其一,我們不再需要考慮引數的順序,函式的使用將更加容易,

其 二,我們可以只對那些我們希望賦予的引數以賦值,只要其它的引數都具有默認引數值,

案例

def func(a, b=5, c=10):
    print('a 是:', a, ' b 是:', b, ' c是:', c)
?
?
func(3, 7)
func(25, c=24)
func(c=50, a=100)

輸出

a 是: 3  b 是: 7  c是:10a 是: 25  b 是: 5  c是:24a 是: 100  b 是: 5  c是:50

它是如何作業的

名為 func 的函式有一個沒有默認引數值的引數,后跟兩個各自帶有默認引數值的引數,

在第一次呼叫函式時, func(3, 7) ,引數 a 獲得了值 3 ,引數 b 獲得了值 7 ,而 c 獲得了默認引數值 10 ,

在第二次呼叫函式時, func(25, c=24) ,由于其所處的位置,變數 a 首先獲得了值 25,然 后,由于命名——即關鍵字引數——指定,變數 c 獲得了值 24 ,變數 b 獲得默認引數值 5 ,

在第三次呼叫函式時, func(c=50, a=100) ,我們全部使用關鍵字引數來指定值,在這里要注 意到,盡管 a 在 c 之前定義,但我們還是我們在變數 a 之前指定了變數 c ,

可變引數

有時你可能想定義的函式里面能夠有任意數量的變數,也就是引數數量是可變的,這可以通 過使用星號來實作

案例

def total(a=5, *numbers, **phonebook):
    print('a', a)
?
    #遍歷元組中的所有專案
    for num in numbers:
        print('num項為:', num)
?
    #遍歷字典中的所有專案
    for key, val in phonebook.items():
        print(key,val)
?
print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560))

輸出

a 10num項為: 1num項為: 2num項為: 3Jack 1123John 2231Inge 1560None

它是如何作業的

當我們宣告一個諸如 *param 的星號引數時,從此處開始直到結束的所有位置引數 都將被收集并匯集成一個稱為“param”的元組(Tuple),

類似地,當我們宣告一個諸如 **param 的雙星號引數時,從此處開始直至結束的所有關鍵字 引數都將被收集并匯集成一個名為 param 的字典(Dictionary),

return 陳述句

return 陳述句用于從函式中回傳,也就是中斷函式,我們也可以選擇在中斷函式時從函式中返 回一個值

def maximum(x, y):
    if x > y:
        return x
    elif x == y:
        return '兩個數相等'
    else:
        return y
print(maximum(2, 3))

輸出:

3

它是如何作業的

maximum 函式將會回傳引數中的最大值,在本例中是提供給函式的數值,它使用一套簡單的 if...else 陳述句來找到較大的那個值并將其回傳,

要注意到如果 return 陳述句沒有搭配任何一個值則代表著 回傳 None ,None 在 Python 中一 個特殊的型別,代表著虛無,舉個例子, 它用于指示一個變數沒有值,如果有值則它的值便 是 None(虛無) ,

每一個函式都在其末尾隱含了一句 return None ,除非你寫了你自己的 return 陳述句,你可 以運行 print(some_function()) ,其中 some_function 函式不使用 return 陳述句,就像這 樣:

def some_function(): 
    pass

Python 中的 pass 陳述句用于指示一個沒有內容的陳述句塊,

提示:

有一個名為 max 的內置函式已經實作了“找到最大數”這一功能,所以盡可能地使 用這一內置函式,

DocStrings 檔案字串

Python 有一個甚是優美的功能稱作檔案字串(Documentation Strings),在稱呼它時通常 會使用另一個短一些的名字docstrings,

DocStrings 是一款你應當使用的重要工具,它能夠幫 助你更好地記錄程式并讓其更加易于理解,令人驚嘆的是,當程式實際運行時,我們甚至可 以通過一個函式來獲取檔案!

案例

def print_max(x, y):
    '''列印兩個數值中的最大數,
這兩個數都應該是整數'''
?
    # 如果可能,將其轉換至整數型別
    x = int(x)
    y = int(y)
    if x > y:
        print(x, '大些')
    else:
        print(y, '大些')
print_max(3, 5)
print(print_max.__doc__)

輸出

5 大些列印兩個數值中的最大數,這兩個數都應該是整數

它是如何作業的

函式的第一行邏輯行中的字串是該函式的 檔案字串(DocString),這里要注意檔案字符 串也適用于后面相關章節將提到的模塊(Modules)與類(Class)

該檔案字串所約定的是一串多行字串,其中第一行以某一大寫字母開始,以句號結束,第二行為空行,后跟的第三行開始是任何詳細的解釋說明,

在此強烈建議你在你所有重要功 能的所有檔案字串中都遵循這一約定,

我們可以通過使用函式的 __doc__ (注意其中的雙下劃綫)屬性(屬于函式的名稱)來獲取 函式 print_max 的檔案字串屬性,只消記住 Python 將所有東西都視為一個物件,這其中 自然包括函式,我們將在后面的類(Class)章節討論有關物件的更多細節,

自動化工具可以以這種方式檢索你的程式中的檔案,因此,我強烈推薦你為你撰寫的所有重 要的函式配以檔案字串,你的 Python 發行版中附帶的 pydoc 命令與 help() 使用檔案字 符串的方式類似,

嵌套函式

python允許創建嵌套函式,也就是說我們可以在函式里面定義函式,而且現有的作用域和變數生存周期依舊不變,

需要注意:1.外部函式的變數可以被內部函式所使用,但不能被內部函式修改,若要修改需要添加關鍵字nonlocal

def max(a,b):
    return a if a>b else b
print(max(5,2)) #5
def the_max(x,y,z):
    c = max(x,y)
    return max(c,z)
?
print(the_max(1,5,3))   #5

輸出

55

嵌套函式作用:

1.封裝-資料隱藏:外部無法訪問“嵌套函式”,

2.減少重復代碼

3.閉包

閉包

啥是閉包?

如果一個函式定義在另一個函式的作用域內,并且參考了外層函式的變數,則該函式稱為閉包,

閉包是Python所支持的一種特性,它讓在非global scope定義的函式可以參考其外圍空間中的變數,這些外圍空間中被參考的變數叫做這個函式的環境變數,

環境變數和這個非全域函式一起構成了閉包,

def outer():
    a = 1
    def inner():
        print(a)
    return inner
inn = outer()
inn()   #1

閉包特點:

一個函式回傳的函式物件,這個函式物件執行的話依賴非函式內部的變數值,這個時候,函式回傳的實際內容如下:
1 函式物件
2 函式物件需要使用的外部變數和變數值


在函式的外部使用內部函式

總結

我們已經了解了許多方面的函式,但我們依舊還未覆寫到所有型別的函式,不過,我們已經 覆寫到了大部分你每天日常使用都會使用到的 Python 函式,

接下來,我們將了解如何創建并使用 Python 模塊,

IT入門 感謝關注

練習地址:www.520mg.com/it

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/135409.html

標籤:Python

上一篇:06 一篇,學會python回圈與分支

下一篇:08-python中的包與模塊

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more