1. 程式人生 > >Python 函式引數

Python 函式引數

簡述

在 Python 中,函式的定義非常簡單,滿足對應的語法格式要求即可。對於呼叫者來說,只需關注如何傳遞正確的引數,以及獲取相應的返回值就足夠了,無需瞭解函式的內部實現(除非想學習、跟蹤原始碼)。

話雖如此,但對於函式的定義來說,靈活性非常高。除了常規定義的必選引數以外,還支援預設引數、可變引數、以及關鍵字引數。這樣以來,不但能處理複雜的引數,還可以簡化呼叫者的程式碼。

|

形參和實參

不止 Python,幾乎所有的程式語言都會涉及兩個術語:parameter 和 argument。那麼,它們之間究竟有什麼區別呢?

  • parameter 是指函式定義中的引數,而 argument 指的是函式呼叫時的實際引數。
  • 簡略描述:parameter = 形參(formal parameter), argument = 實參(actual parameter)。

例如,定義一個簡單的函式:

>>> def greet(param1, param2):
...     pass
... 
>>> 
>>> greet('Hello', 'Python')

其中,param1 和 param2 是函式的形參,而在函式 greet() 被呼叫時,傳入的('Hello''Python')則是實參。

固定數量引數的函式

到目前為止,關於函式,我們介紹的都是固定數量的引數。來看一個簡單的示例:

>>> def greet(say, msg):
...     print(say, msg)
... 
>>> 
>>> greet('Hello', 'Python')
Hello Python

這裡,函式 greet() 有兩個引數,用兩個引數呼叫這個函式,執行得很順利,不會有任何錯誤。

倘若,引數的個數不匹配,會發生什麼?

>>> greet()  # 沒有引數
...
TypeError: greet() missing 2 required positional arguments: 'say'
and 'msg' >>> >>> greet('Hi') # 只有一個引數 ... TypeError: greet() missing 1 required positional argument: 'msg'

顯然,直譯器會發牢騷。但是,對 Python 來說,要解決這個問題簡直是易如反掌,繼續往下看!

預設引數

定義函式時,可以使用賦值運算子(=)為引數指定一個預設值。

注意: 如果引數沒有預設值,在呼叫時必需為其指定一個值;如果引數有預設值,那麼在呼叫時值是可選的,如果為其提供了一個值,將會覆蓋預設值。

>>> def greet(say, name = 'James', msg = 'I am your biggest fan!'):
...     print(say, ',', name, ',', msg)
... 
>>> greet('Hi')  # 只提供強制性的引數
Hi , James , I am your biggest fan!
>>> 
>>> greet('Hi', 'Kobe')  # 給出一個可選引數
Hi , Kobe , I am your biggest fan!
>>> 
>>> greet('Hi', 'Kobe', 'I want to challenge you!')  # 給出所有引數
Hi , Kobe , I want to challenge you!

由於 say 沒有預設值,所以必須指定;name、msg 有預設值,所以值是可選的。

函式中的所有引數都可以有預設值,但是,一旦存在一個預設引數,其右側的所有引數也必須有預設值。也就是說,非預設引數不能在預設引數之後。

例如,將上面的函式定義為:

def greet(name = 'James', say):

就會引發錯誤:

SyntaxError: non-default argument follows default argument

關鍵字引數

當使用某些值呼叫函式時,這些值將根據其位置分配給引數。

例如,在上述函式 greet() 中,當使用 greet('Hi', 'Kobe') 呼叫它時,'Hi' 被賦值給引數 say,同樣地,'Kobe' 被賦值給 name。

Python 允許使用 kwarg = value 格式的關鍵字引數呼叫函式:

>>> def greet(say, name = 'James'):
...     print(say, ',', name)
... 
>>> 
>>> greet(say = 'Hi', name = 'Kobe')  # 2 個關鍵字引數
Hi , Kobe
>>> 
>>> greet(name = 'Kobe', say = 'Hi')  # 2 個關鍵字引數(次序顛倒)
Hi , Kobe
>>> 
>>> greet('Hi', name = 'Kobe')  # 位置引數與關鍵字引數混合使用
Hi , Kobe

當以這種方式呼叫函式時,關鍵字引數必須在位置引數之後,所有傳遞的關鍵字引數都必須與函式接受的某個引數匹配,並且它們的順序不重要。

例如,像下面這樣呼叫,會引發錯誤:

>>> greet(name = 'Kobe', 'Hi')  # 關鍵字引數在位置引數之前
...
SyntaxError: positional argument follows keyword argument
>>>
>>> greet('Hi', na = 'Kobe')  # na 不匹配
...
TypeError: greet() got an unexpected keyword argument 'na'

可變引數

可變引數也被稱為不定長引數,顧名思義,就是傳入的引數個數是可變的,可以是任意個(0、1、2 … N)。

要定義可變引數,僅需在引數名之前新增一個星號(*)。在函式內部,這些引數被包裝為一個 tuple。

注意:* 非彼 *,不要誤認為是 C/C++ 中的指標。

>>> def greet(*names):
...     print(names)
... 
>>> 
>>> greet()  # 沒有引數,返回空元組
()
>>>
>>> greet('Jordan', 'James', 'Kobe')
('Jordan', 'James', 'Kobe')

有時,必須在函式定義中使用位置引數以及可變引數,但位置引數始終必須在可變引數之前。

>>> def greet(say, *names):
...     print(say, names)
... 
>>> 
>>> greet('Hi')
Hi ()
>>> 
>>> greet('Hi', 'Jordan', 'James', 'Kobe')
Hi ('Jordan', 'James', 'Kobe')

通常情況下,可變引數會出現在形參列表的最後,因為它們會把傳遞給函式的所有剩餘輸入引數都收集起來。可變引數之後出現的任何形參都是“強制關鍵字”引數,這意味著,它們只能被用作關鍵字引數,而不能是位置引數。

>>> def greet(*names, sep = ','):
...     return sep.join(names)
... 
>>> 
>>> greet('Jordan', 'James', 'Kobe')
'Jordan,James,Kobe'
>>> 
>>> greet('Jordan', 'James', 'Kobe', sep = '/')  # 被用作關鍵字引數
'Jordan/James/Kobe'
>>>
>>> greet('Jordan', 'James', 'Kobe', '/')  # 被用作位置引數
'Jordan,James,Kobe,/'

任意關鍵字引數

還有一種機制,用於任意數量的關鍵字引數。為了做到這一點,使用雙星號(**):

>>> def greet(**all_star):
...     print(all_star)
... 
>>> greet()  # 沒有引數,返回空字典
{}
>>> 
>>> greet(name = 'James', age = 18)
{'name': 'James', 'age': 18}

當最後一個形式為 **msgs 的形參出現時,它將收到一個字典,其中包含所有關鍵字引數,除了與形參對應的關鍵字引數之外。還可以與 *names 的形參相結合(*names 必須出現在 **msgs 之前)。

例如,定義一個這樣的函式:

>>> def greet(say, *names, **msgs):
...     print('--', say)
...     for name in names:
...         print(name)
...     print('-' * 40)
...     keys = sorted(msgs.keys())
...     for key in keys:
...         print(key, ':', msgs[key])
... 
>>> 
>>> greet('Hi', 'Jordan', 'James', 'Kobe', msg = 'I want to challenge you!', challenger = 'Waleon')
-- Hi
Jordan
James
Kobe
----------------------------------------
challenger : Waleon
msg : I want to challenge you!

注意: 在列印內容之前,通過對 msgs 字典的 keys() 方法的結果進行排序來建立關鍵字引數名稱列表。如果沒有這樣做,則列印引數的順序是未定義的。

對引數進行解包

正如“可變引數”那樣,也可在函式呼叫中使用 * 操作符。只不過在這種情況下,與在函式定義中 * 的語義相反,引數將被解包而不是打包。

>>> def greet(name, age):
...     print(name, age)
... 
>>> 
>>> t = ('James', 18)
>>> greet(*t)
James 18

還有一種方式,幾乎沒有必要提到,這裡也羅嗦一下:

>>> greet(t[0], t[1])
James 18

與解包相比,這種呼叫方式顯然不舒適。另外,在一般情況下,呼叫 greet(t[0], t[1]) 幾乎是徒勞的,因為長度是未知的。“未知”的意思是:長度只在執行時才知道,而不是在編寫指令碼時就知道。

同樣地,字典也可以用 ** 操作符傳遞關鍵字引數:

>>> def greet(name, age = 18):
...     print(name, age)
... 
>>> 
>>> d = {'name':'James', 'age':32}
>>> greet(**d)
James 32

相關推薦

Python函式引數和返回值

- 函式引數和返回值的作用 函式:封裝功能獨立的程式碼,在需要時通過函式名被呼叫 引數:外界希望在函式內部處理的資料 返回值:函式完成工作後,給呼叫者的一個結果 函式根據有無引數和返回值,可以相互結合,共有4種組合形式 1.無引數,無返回值 2.無引數,有返回值 3.有引數,無返回值

python函式引數的填坑之路

背景 最近在看廖雪峰老師的python3教程之函式的引數 受益匪淺,但是在實踐的過程中,發現了一些不解之謎 兩個錯誤 import _thread import time def func1(x): while x: print(x) x = x -1 _threa

Python 函式 引數傳遞

引數傳遞    在 python 中,型別屬於物件,變數是沒有型別的:        a=[1,2,3]        a="Runoob" &nbs

python 函式引數作為引用時

作為引數傳入函式中,執行結束後,實參到底會不會影響 1. 各種型別資料,引數名到底對應什麼? 如果你學過c或者c++, 你應該知道引用這個東西,我簡單的理解為,如果這個引數名上的地址,存的不是它的值,而是它對應值得位置,那就是引用。從上圖不難發現,python常用

python-函式引數和文件

四類引數 普通引數 預設引數 關鍵字引數 收集引數 關鍵字引數開始 語法 def func(p1=v1, p2=v2.....): func_body 呼叫函式: func(p1=value1, p2=value2......

一篇文章讓你掌握python函式引數的各種用法

  python的函式引數型別比較豐富,而且用法相對比較複雜,今天我們介紹幾種簡單常用的。 當然在學習Python的道路上肯定會困難,沒有好的學習資料,怎麼去學習呢? 學習Python中有不明白推薦加入交流群        

python函式引數的部分求值方法

在python中,呼叫函式時,會從左到右對所有引數表示式進行求值,使用functools模組中的partial()函式可以對函式引數進行部分求值。 程式示例: from functools import partial def f(x,y,z): return x

python函式引數定義及解析(包含帶星號引數

前言:python中函式引數的傳遞是通過賦值來傳遞的。函式的引數有兩個方面值得注意: 1.函式引數是如何定義的 2.在呼叫函式的過程中引數是如何被解析的 python函式引數的定義方式 func(arg1, arg2, …) 這是最常見的定義方式,一個函式

Python函式引數預設值的陷阱和原理深究 • cenalulu's Tech Blog

本文將介紹使用mutable物件作為Python函式引數預設值潛在的危害,以及其實現原理和設計目的 陷阱重現 我們就用實際的舉例來演示我們今天所要討論的主要內容。 下面一段程式碼定義了一個名為generate_new_list_with的函式。該函式的本意是在每次呼叫時都新建一個包含有給

python 函式引數(必選引數、預設引數、可選引數、關鍵字引數)

參考: ######################################################## 函式引數:必選引數、預設引數、可選引數、關鍵字引數 ##############################################

Python 函式引數形式

一、位置引數   根據定義的函式的引數位置來判斷引數的值。位置引數一旦定義,在呼叫函式時,就必須傳入對應的引數值。 def show_info(name, age): print("name: {0}, age: {1}".form

Python] Python函式引數中的*,** 以及不帶*的差異!

Python的函式定義中有兩種特殊的情況,即出現*,**的形式,加上不帶*的,三種情況,差異性在哪裡呢? 第一種:引數個數固定,可以帶引數名字,或者不帶名字。 第二種:引數個數任意,但不能帶引數名字,引數是tuple型別。 第三種,引數個數任意,但必須帶引數名字,引數是di

python函式引數(1)

(1)<1> 定義帶有引數的函式示例如下:def add2num(a, b): c = a+b print c <2> 呼叫帶有引數的函式以呼叫上面的add2num(a, b)函式為例:def add2num(a, b): c

python 函式引數的傳遞(引數帶星號的說明) 元組傳遞 字典傳遞

python中函式引數的傳遞是通過賦值來傳遞的。函式引數的使用又有倆個方面值得注意:1.函式引數是如何定義的 2.在呼叫函式的過程中引數是如何被解析 先看第一個問題,在python中函式引數的定義主要有四種方式:1.F(arg1,arg2,...)這是最常見的定義方式,一個函式可以定義任意個引數,每個引

Python 函式引數

簡述 在 Python 中,函式的定義非常簡單,滿足對應的語法格式要求即可。對於呼叫者來說,只需關注如何傳遞正確的引數,以及獲取相應的返回值就足夠了,無需瞭解函式的內部實現(除非想學習、跟蹤原始碼)。 話雖如此,但對於函式的定義來說,靈活性非常高。除了常規定

python函式引數詳解

值傳遞和引用傳遞區別如果你傳入的引數物件是可變物件:列表,字典,這個時候就是引用傳遞。如果你傳入的引數物件是不可變的物件:數字,元組,字串,這個時候就是值傳遞。對於值傳遞,函式內部修改的是引數的副本,不會改變原值;對於引用傳遞,函式內部修改了是變數的指向,從而相應對變數進行了

Python函式引數傳遞的問題

Python中的一些概念: 變數:沒有型別,可以指向任何物件 物件:有型別。物件分為可變物件和不可變物件 從id可以看出變數是沒有型別的,同一組資料指向不同的物件,id不同。 Python中引數傳遞是傳遞的變數的值,即變數所指向的物件的地址。 傳遞規律

python函式引數預設值

在stackoverflow上看到這樣一個程式: #! /usr/bin/env python # -*- coding: utf-8 -*- class demo_list: def __init__(self, l=[]): self.l =

python函式引數傳遞規則

1、宣告一個引數具有預設值引數的函式,如下: def hello(name = 'python')     print('你好',name) ---無引數傳遞直接呼叫函式,則為:你好,python--(hello) ---有引數傳遞時,如:hello('小明')--結果為:

關於Python函式引數傳遞方式--值傳遞?引用傳遞!

渣渣我在學習中遇到的一點問題,特地貼出來,由於我水平渣,所以如有問題,請多指教 經過測試可以發現: python3 不允許我們選擇引數傳遞方式,但是他已經全部採用了引用傳遞。有幾點需要注意: 1.引用傳遞可以當做值傳遞使用,只是你需要把他賦值給一個臨時變數副本,不要直接使