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.引用傳遞可以當做值傳遞使用,只是你需要把他賦值給一個臨時變數副本,不要直接使