python3 第十六章 - 函數

来源:https://www.cnblogs.com/mrbug/archive/2018/01/21/8322423.html
-Advertisement-
Play Games

函數是組織好的,可重覆使用的,用來實現單一,或相關聯功能的代碼段。函數能提高應用的模塊性,和代碼的重覆利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己創建函數,這被叫做用戶自定義函數。 1、語法 Python 定義函數使用 def 關鍵字,一般格式如下: 預設情況 ...


函數是組織好的,可重覆使用的,用來實現單一,或相關聯功能的代碼段。
函數能提高應用的模塊性,和代碼的重覆利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己創建函數,這被叫做用戶自定義函數。

 

1、語法

Python 定義函數使用 def 關鍵字,一般格式如下:

def 函數名(參數列表):
    函數體

 

預設情況下,參數值和參數名稱是按函數聲明中定義的的順序匹配起來的。

定義一個由自己想要功能的函數,以下是簡單的規則:

  • 函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括弧 ()。
  • 任何傳入參數和自變數必須放在圓括弧中間,圓括弧之間可以用於定義參數。
  • 函數的第一行語句可以選擇性地使用文檔字元串——用於存放函數說明。
  • 函數內容以冒號起始,並且縮進。
  • return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None。

 

實例:

def hello():
    return 'Hello world'

def say(msg):
    print(msg)

def sun(num1, num2):
    print('num1 + num2 =', num1, num2)

 

2、函數調用

Python內置了很多有用的函數,我們可以直接調用。要調用一個函數,需要知道函數的名稱和參數,比如求絕對值的函數abs,只有一個參數:

print('100的絕對值:', abs(100))
print('-20的絕對值:', abs(-20))

以上代碼,輸出:

100的絕對值: 100
-20的絕對值: 20

定義一個函數:給了函數一個名稱,指定了函數里包含的參數,和代碼塊結構。
這個函數的基本結構完成以後,你可以通過另一個函數調用執行,也可以直接從 Python 命令提示符執行。

3、參數傳遞 

在 python 中,類型屬於對象,變數是沒有類型的:

a=[1,2,3]

a="Python"

以上代碼中,[1,2,3] 是 List 類型,"Python" 是 String 類型,而變數 a 是沒有類型,它僅僅是一個對象的引用(一個指針),可以是 List 類型對象,也可以指向 String 類型對象。

 

python 函數的參數傳遞:

  • 不可變類型:類似 c++ 的值傳遞,如 整數、字元串、元組。如fun(a),傳遞的只是a的值,沒有影響a對象本身。比如在 fun(a)內部修改 a 的值,只是修改另一個複製的對象,不會影響 a 本身。
  • 可變類型:類似 c++ 的引用傳遞,如 列表,字典。如 fun(la),則是將 la 真正的傳過去,修改後fun外部的la也會受影響

python 中一切都是對象,嚴格意義我們不能說值傳遞還是引用傳遞,我們應該說傳不可變對象和傳可變對象。

 

什麼是可更改(mutable)與不可更改(immutable)對象?

在 python 中,str, tuple, 和 number 是不可更改的對象,而 list,dict 等則是可以修改的對象。例如:

不可變類型:變數賦值 a=5 後再賦值 a=10,這裡實際是新生成一個 int 值對象 10,再讓 a 指向它,而 5 被丟棄,不是改變a的值,相當於新生成了a。

可變類型:變數賦值 la=[1,2,3,4] 後再賦值 la[2]=5 則是將 list la 的第三個元素值更改,本身la沒有動,只是其內部的一部分值被修改了。

 

不可變對象在函數里修改了參數,原始的參數是不會改變的。例如:

def ChangeInt(a):
    a = 10

b = 2
ChangeInt(b)
print(b) # 結果是 2

實例中有 int 對象 2,指向它的變數是 b,在傳遞給 ChangeInt 函數時,按傳值的方式複製了變數 b,a 和 b 都指向了同一個 Int 對象,在 a=10 時,則新生成一個 int 值對象 10,並讓 a 指向它。

 

可變對象在函數里修改了參數,那麼原始的參數也被改變了。例如:

# 可寫函數說明
def changeme(mylist):
    "修改傳入的列表"
    mylist.append([1, 2, 3, 4])
    print("函數內取值: ", mylist)
    return


# 調用changeme函數
mylist2 = [10, 20, 30]
changeme(mylist2)
print("函數外取值: ", mylist2)

傳入函數的和在末尾添加新內容的對象用的是同一個引用。故輸出結果如下:

函數內取值:  [10, 20, 30, [1, 2, 3, 4]]
函數外取值:  [10, 20, 30, [1, 2, 3, 4]]

 

4、參數

  • 必需參數
  • 關鍵字參數
  • 預設參數
  • 不定長參數

 

什麼是必需參數?必需參數須以正確的順序傳入函數。調用時的數量必須和聲明時的一樣。下麵的實例中調用say()函數,你必須傳入一個參數,不然會出現語法錯誤:

def say(msg):
    print(msg)  # 列印傳入的參數

#調用say
say('hello world')

以上代碼,輸出:

hello world

但,我們如下調用時,就會報錯:

def say(msg):
    print(msg)  # 列印傳入的參數

#調用say
say()

以上代碼,報錯:

TypeError: say() missing 1 required positional argument: 'msg'

調用函數的時候,如果傳入的參數數量不對,會報TypeError的錯誤,並且Python會明確地告訴你。

 

如果傳入的參數數量是對的,但參數類型不能被函數所接受,也會報TypeError的錯誤,並且給出錯誤信息:str是錯誤的參數類型:

print(abs('abc'))

以上代碼,會報錯:

TypeError: bad operand type for abs(): 'str'

 

什麼是關鍵字參數?關鍵字參數和函數調用關係緊密,函數調用使用關鍵字參數來確定傳入的參數值。使用關鍵字參數允許函數調用時參數的順序與聲明時不一致,因為 Python 解釋器能夠用參數名匹配參數值。

我們來看實例:

#  申明一個函數say,第一個參數為:name,第二個參數為:msg
def say(name, msg):
    print('%s 說:%s' %(name, msg))  # 列印傳入的參數

# 普通方式調用say()
say('roy', 'hello world')

# 用關鍵字參數的方式調用say()
say(msg='這是用關鍵字參數的方式調用的', name='roy')

以上代碼,輸出:

roy 說:hello world
roy 說:這是用關鍵字參數的方式調用的

我們可以看出,在第二次調用的時候,我們根本沒有按照函數申明時的參數順序去傳遞參數,但也是正確的輸出了內容。

 

什麼是預設參數?調用函數時,如果沒有傳遞參數,則會使用預設參數。以下實例中如果沒有傳入 msg 參數,則使用預設值:

#  申明一個函數say,第一個參數為:name,第二個參數為:msg
def say(name, msg='hello world'):
    print('%s 說:%s' %(name, msg))  # 列印傳入的參數

# 調用
say('roy')

以上代碼,輸出:

roy 說:hello world

設置預設參數時,有幾點要註意:

一是必選參數在前,預設參數在後,否則Python的解釋器會報錯(思考一下為什麼預設參數不能放在必選參數前面);

二是如何設置預設參數。當函數有多個參數時,把變化大的參數放前面,變化小的參數放後面。變化小的參數就可以作為預設參數。

 

什麼是不定長參數?你可能需要一個函數能處理比當初聲明時更多的參數。這些參數叫做不定長參數,和上述幾種參數不同,聲明時不會命名。基本語法如下:

def functionname([formal_args,] *var_args_tuple ):
   "函數_文檔字元串"
   function_suite
   return [expression]

加了星號(*)的變數名會存放所有未命名的變數參數。如果在函數調用時沒有指定參數,它就是一個空元組。我們也可以不向函數傳遞未命名的變數。如下實例:

# 可寫函數說明
def printinfo(arg1, *vartuple):
    "列印任何傳入的參數"
    print("輸出: ")
    print(arg1)
    for var in vartuple:
        print(var)
    return


# 調用printinfo 函數
printinfo(10)
printinfo(70, 60, 50)

以上代碼,輸出:

輸出: 
10
輸出: 
70
60
50

 

5、匿名函數

python 使用 lambda 來創建匿名函數。

所謂匿名,意即不再使用 def 語句這樣標準的形式定義一個函數。

  • lambda 只是一個表達式,函數體比 def 簡單很多。
  • lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
  • lambda 函數擁有自己的命名空間,且不能訪問自己參數列表之外或全局命名空間里的參數。
  • 雖然lambda函數看起來只能寫一行,卻不等同於C或C++的內聯函數,後者的目的是調用小函數時不占用棧記憶體從而增加運行效率。


lambda 函數的語法只包含一個語句,如下:

lambda [arg1 [,arg2,.....argn]]:expression

實例:

# 可寫函數說明
sum = lambda arg1, arg2: arg1 + arg2

# 調用sum函數
print("相加後的值為 : ", sum(10, 20))
print("相加後的值為 : ", sum(20, 20))

以上代碼,輸出:

相加後的值為 :  30
相加後的值為 :  40

 

有些時候,當我們在傳入函數時,不需要顯式地定義函數,直接傳入匿名函數更方便。匿名函數有個限制,就是只能有一個表達式,無需寫return,返回值就是該表達式的結果。用匿名函數有個好處,因為函數沒有名字,不必擔心函數名衝突。此外,匿名函數也是一個函數對象,也可以把匿名函數賦值給一個變數,再利用變數來調用該函數

 

6、return語句

return [表達式] 語句用於退出函數,選擇性地向調用方返回一個表達式。不帶參數值的return語句返回None。

實例:

#  這是一個有return語句的函數
def hello():
    return 'Hello world'

#  這是一個有return語句的函數,預設返回None
def say(msg):
    print(msg)

#  調用 hello 並把它的結果賦值給 變數
msg = hello()
print(msg)

# 調用 say
say('您好')

以上代碼,輸出:

Hello world
您好

 

 

7、註釋

函數的第一行語句可以選擇性地使用文檔字元串——用於存放函數說明,例如:

def test():
    """
    this is test
    :return: int string
    """
    return 1

可以調用 __doc__ 查看函數的文檔:

def test():
    """
    this is test
    :return: int string
    """
    return 1

print(test.__doc__)

以上代碼,輸出:

    this is test
    :return: int string

 

在python3中你還可以這樣為函數添加註釋:

def dog(name:str, age:(1, 99), species:'狗狗的品種') -> tuple:
    return (name, age, species)

如上,可以使用:對參數逐個進行註釋,註釋內容可以是任何形式,比如參數的類型、作用、取值範圍等等,返回值使用->標註,所有的註釋都會保存至函數的屬性。

查看這些註釋可以通過 __annotations__ 獲取,結果會議字典的形式返回:

def dog(name:str, age:(1, 99), species:'狗狗的品種') -> tuple:
    return (name, age, species)


print(dog.__annotations__)

以上代碼,輸出:

{'name': <class 'str'>, 'age': (1, 99), 'species': '狗狗的品種', 'return': <class 'tuple'>}

另外,使用函數註釋並不影響預設參數的使用:

def dog(name:str ='dobi', age:(1, 99) =3, species:'狗狗的品種' ='Labrador') -> tuple:
    return (name, age, species)

print(dog())

以上代碼,輸出:

('dobi', 3, 'Labrador')

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JavaScript作為一個動態語言,很大程度上的詬病就是缺少了面向對象的 類 這個概念,ES5傳統的方法是通過構造函數來實現類的特性;ES6引入了類這一概念,將 這個概念作為對象的模板,通過關鍵字 可以定義類;本質上ES6中引入的類是一個語法糖,其大部分功能ES5均可實現; JavaScript語 ...
  • 一.插值 v-once 通過使用 v-once 指令,你也能執行一次性地插值,當數據改變時,插值處的內容不會更新。但請留心這會影響到該節點上所有的數據綁定: v-html 雙大括弧會將數據解釋為普通文本,而非 HTML 代碼。為了輸出真正的 HTML,你需要使用 v-html 指令: 這個 span ...
  • 說是模塊,其實在MVC中就是區域,新建一個區域專門管理整個微信功能。 Web項目新建區域 在Web項目Areas目錄下新建一個區域,名稱為“Weixin",如下圖: 接著打開web.config,修改如下代碼: 文件路徑:D:\abp version\aspnet-zero-3.4.0\aspnet ...
  • 字元串是Python中最常用的數據類型,而且很多時候你會用到一些不屬於標準ASCII字元集的字元,這時候代碼就很可能拋出UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 10: ordinal not in ra ...
  • 呵呵!作為一名教python的老師,我發現學生們基本上一開始很難搞定python的裝飾器,也許因為裝飾器確實很難懂。搞定裝飾器需要你瞭解一些函數式編程的概念,當然還有理解在python中定義和調用函數相關語法的一些特點。 我沒法讓裝飾器變得簡單,但是通過一步步的剖析,我也許能夠讓你在理解裝飾器的時候 ...
  • 轉載自:http://in355hz.iteye.com/blog/1860787 最近業務中需要用 Python 寫一些腳本。儘管腳本的交互只是命令行 + 日誌輸出,但是為了讓界面友好些,我還是決定用中文輸出日誌信息。 很快,我就遇到了異常: Python代碼 UnicodeEncodeError ...
  • 給定一個字元串,求它最長的迴文子串長度,例如輸入字元串'35534321',它的最長迴文子串是'3553',所以返回4。 最容易想到的辦法是枚舉出所有的子串,然後一一判斷是否為迴文串,返回最長的迴文子串長度。不用我說,枚舉實現的耗時是我們無法忍受的。那麼有沒有高效查找迴文子串的方法呢?答案當然是肯定 ...
  • Servlet簡單實現請求分發(類thinkphp5) 1.寫請求分發的原由 今天晚上筆者在使用java的servlet寫博客網站的時候,想實現MVC開發模式,然後就發現,一個請求的動作就要寫servlet實現類,這也太麻煩了吧,於是就在想,可不可以一個contorller控制器中實現多個請求,像t ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...