**函數的參數**
函數定義中的參數有以下幾種:
* 必需參數(位置參數)
* 默認參數
* 關鍵字參數
* 不定長參數
* 不定長關鍵字參數
**必需參數(位置參數)**
* 必需參數(位置參數)必須以正確的順序傳入函數。調用時的數量必須和聲明時的一樣。
我們定義一個打招呼的函數
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def myHello(yourname,myname):
'''定義招呼,需要依次傳入對方的名字以及你的名字'''
print("Hello",yourname,"my name is",myname)
#第一次調用
myHello('lisa','airvip')
#第二次調用
myHello()
~~~
第一次調用,正確輸出
~~~
Hello lisa my name is airvip
~~~
第二次調用,報了 缺少位置參數的錯誤
~~~
Traceback (most recent call last):
File "./test.py", line 10, in <module>
myHello()
TypeError: myHello() missing 2 required positional arguments: 'yourname' and 'myname'
~~~
**默認參數**
* 默認參數在調用時可以傳入也可以不傳入
* 默認參數在函數定義時必須在位置參數之后
我們修改下打招呼的函數
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def myHello(yourname,myname = 'airvip'):
'''定義招呼,需要依次傳入對方的名字以及你的名字'''
print("Hello",yourname,"my name is",myname)
#第一次調用
myHello('lisa','air')
#第二次調用
myHello('lisa')
~~~
第一次調用與第二次調用都會正確輸出
~~~
Hello lisa my name is air
Hello lisa my name is airvip
~~~
可以看出添加了默認參數的函數調用相比只有位置參數的函數調用輕松多了。
**關鍵字參數**
* 關鍵字參數是相對于函數調用來說的,我們用位置參數的例子來說明。
* 使用關鍵字參數允許函數調用時參數的順序與聲明時不一致,因為 Python 解釋器能夠用參數名匹配參數值。
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def myHello(yourname,myname):
'''定義招呼,需要依次傳入對方的名字以及你的名字'''
print("Hello",yourname,"my name is",myname)
#第一次調用
myHello('lisa','airvip')
#第二次調用
myHello('airvip','lisa')
#第三次調用 使用關鍵字
myHello(myname='airvip',yourname='lisa')
~~~
調用結果
~~~
#第一次調用
Hello lisa my name is airvip
#第二次調用
Hello airvip my name is lisa
#第三次調用 使用關鍵字
Hello lisa my name is airvip
~~~
我們不難發現,第一次調用與第三次調用返回的結果是一樣的,然而第二次調用是沒有使用關鍵字(定義函數時的形參),得到了與第一次和第三次調用不一樣的結果。
**不定長參數**
* 在函數處理是可能不確定有幾個參數,我們就可以定義成不定長參數。
* 習慣上使用 *args 來表示不定常參數,當然你也可以使用其他前面加星的變量表示不定長參數。
* 如果在函數調用時沒有指定參數,它就是一個空元組。我們也可以不向函數傳遞未命名的變量。
* 不定長參數允許你傳入 0 個或任意個參數,這些可變參數在函數調用時自動組裝為一個 tuple。
以多個數字求和為例
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def mySum(*args):
sum = 0
for i in args:
sum += i
print(sum)
#調用
mySum() #打印0
mySum(1,2,3) #打印6
mySum(*(1,2,3)) #打印6
mySum(*[1,2,3]) #打印6
~~~
**不定長關鍵字參數**
* 習慣上使用 **kwargs 來表示不定長關鍵字參數,當然你也可以使用其他前面加雙星的變量表示不定長關鍵字參數。
* Python 解釋器會把通過 **kwargs 傳入的參數變成一個 dict 形式。
以收集用戶信息為例
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def userInfo(name,sex='男',*args,salary,**kwargs):
'''用戶信息收集'''
print('用戶信息'.center(20,'*'))
info = """
姓名:{_name}
性別:{_sex}
特征:{_args}
收入:{_salary}
其他: {_kwargs}
""".format(_name = name,_sex = sex,_args = args,_salary = salary,_kwargs = kwargs)
print(info)
userInfo('airvip','男','喜歡女','長得帥',salary='1000000',address='山東')
~~~
調用結果
~~~
********用戶信息********
姓名:airvip
性別:男
特征:('喜歡女', '長得帥')
收入:1000000
其他: {'address': '山東'}
~~~
在 Python 中定義函數時,使用 必需參數(位置參數)、默認參數、不定長參數、關鍵字參數和不定長關鍵字參數,這5種參數的組合。但是參數定義的順序必須是: 必需參數(位置參數)、默認參數、不定長參數、關鍵字參數和不定長關鍵字參數。
總結:
1. 使用了不定長參數默認參數就失效
2. *args 不定長參數,args 接收的是一個 tuple
3. **kwargs 不定長關鍵字參數,kwargs 接收的是一個 dict
4. 不定長參數既可以直接傳入:func(1, 2, 3),又可以先組裝 list 或 tuple ,再通過 *list 或 * tuple 傳入
5. 不定長關鍵字參數既可以直接傳入:func(a=1, b=2),又可以先組裝 dict,再通過 **dict傳入
**再談默認參數**
默認參數很有用,但是使用不當又會產生不可思議的錯誤。
下面來探討這個使用默認參數的例子
給列表末尾添加結束字符串:
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def list_over(L = []):
L.append('Over')
return L
#第一次調用
print(list_over([1,2,3]))
#第二次調用
print(list_over([1,2,3]))
#第三次調用
print(list_over())
#第四次調用
print(list_over())
~~~
調用結果
~~~
[1, 2, 3, 'Over']
[1, 2, 3, 'Over']
['Over']
['Over', 'Over']
~~~
我們理想的結果是
第一次調用結果 等于 第二次調用
第三次調用結果 等于 第四次調用
然而,第三次調用結果 不等于 第四次調用 ,這是為什么呢?
因為 L 也是一個變量,該變量默認指向不變的內存地址空間,每次調用該函數,如果改變了該地址空間的值,則下次調用時,默認參數變量的內容就變了,但是該默認變量的指向沒有發生改變,就造成了異常的結果。
所以,默認參數必須指向不變對象!
那問題來了,那該函數如何修改呢?
~~~
def list_over(L = None):
if L == None:
L = []
L.append('Over')
return L
~~~
這樣無論使用默認參數調用多少次都不會改變默認變量 L 指向的內存空間的值了。
- 跟老司機學Python
- 了解Python
- 1、python簡介
- 2、Python發展史
- 3、Python特點
- 4、Python解釋器
- 入坑Python
- 1、Python環境搭建
- 2、設置環境變量
- 3、開始使用Python
- 4、運行Python程序
- 掌握Python基礎
- Python基礎知識
- Python運算符
- 算術運算符
- 比較運算符
- 賦值運算符
- 邏輯運算符
- 位運算符
- 成員運算符
- 身份運算符
- 運算符優先級
- Python的變量與常量
- Python數據類型
- Number數值
- String字符串
- List列表
- Tuple元組
- Dictionary字典
- Set集合
- Python流程控制語句
- 條件判斷
- 循環控制
- Python函數
- 1、函數是什么
- 2、函數的定義
- 3、函數的參數
- 4、函數的調用
- 5、嵌套函數
- 6、遞歸函數
- 7、匿名函數
- 8、函數式編程
- 9、高階函數
- 1、map
- 2、reduce
- 3、filter
- 4、sorted
- 10、返回函數
- 11、偏函數
- Python文件IO操作
- 標準輸入輸出
- 讀寫文件
- with讀寫文件
- Python高級特性
- 1、列表生成式
- 2、迭代器
- 3、生成器
- 4、裝飾器
- Python模塊初探
- 1、模塊與包
- 2、創建模塊
- 3、模塊中的作用域
- 4、模塊的導入
- Python面向對象編程
- 類與對象
- 類的定義及使用
- 面向對象特性
- 類中的訪問域
- 查看對象詳情
- Python面向對象進階
- 類中的方法
- 類中的特殊成員
- 限制對象的屬性
- 再聊多繼承
- 裝x式創建類
- 創建元類
- Python內置模塊
- os模塊
- sys模塊
- random模塊
- time模塊
- datetime模塊
- shutil模塊
- collections模塊
- base64模塊
- json模塊
- hashlib模塊
- xml模塊
- 1. SAX解析XML
- 2. DOM解析XML
- 3. ElementTree解析XML
- urllib模塊
- logging模塊
- re模塊
- Python第三方模塊
- Pillow與PIL
- Requests
- Tablib
- Xpinyin
- Chardet
- Pycurl
- Virtualenv
- Python操作數據庫
- Mysql操作
- Sqllite操作
- Mongodb操作
- Redis操作
- Python的GUI編程
- Python中GUI的選擇
- Tkinter
- wxPython
- Socket網絡編程
- Socket網絡編程簡聊
- Socket內建方法
- TCP協議編程
- UDP協議編程
- TCP與UDP
- Python電子郵件
- SMTP發郵件
- POP3收郵件
- IMAP收郵件
- 進程線程
- 進程與線程
- 進程編程
- 使用進程池
- 進程間的通信
- 線程編程
- 使用線程鎖
- Python的GIL
- Web編程
- WSGI介紹
- Web框架
- Flask使用
- 模板jinjia2使用
- 項目結構規劃
- 異步與協程
- 概念掃盲
- 異步IO進化之路
- 協程是什么
- yield協程編程
- yield from
- asyncio
- async與await
- aiohttp之client
- aiphttp之server
- 網絡爬蟲
- 網絡爬蟲簡聊
- Beautiful Soup模塊的使用
- pyquery 模塊的使用
- selenium模塊的使用
- 爬取段子實例
- 錯誤與調試
- 錯誤
- 錯誤處理
- 拋出錯誤
- 高效的調試
- Python重要語句
- pass語句
- return語句
- Python開發必知
- pip使用詳解
- 如何對列表進行迭代
- 如何對字典進行迭代
- 字符串格式化
- 知識擴展
- 網絡模型
- GUI是什么