python学习随笔(七)_函数
函數?? ?#作用:封裝和復用
?? ?數學定義:y=f(x) ,y是x的函數,x是自變量。y=f(x0, x1, ..., xn)
?? ?Python函數
?? ??? ?由若干語句組成的語句塊、函數名稱、參數列表構成,它是組織代碼的最小單元
?? ??? ?完成一定的功能
?? ?函數的作用
?? ??? ?*結構化編程對代碼的最基本的封裝*,一般按照功能組織一段代碼
?? ??? ?封裝的目的為了復用*,減少冗余代碼
?? ??? ?代碼更加簡潔美觀、可讀易懂
?? ?函數的分類
?? ??? ?內建函數,如max()、reversed()等
?? ??? ?庫函數,如math.ceil()等
函數定義、調用
?? ?def語句定義函數
?? ?def 函數名(參數列表):
?? ??? ?函數體(代碼塊)
?? ??? ?[return 返回值]
?? ??? ?函數名就是標識符*,命名要求一樣
?? ??? ?語句塊必須縮進,約定4個空格
?? ??? ?Python的函數沒有return語句,隱式會返回一個None值
?? ??? ?*定義中的參數列表成為*形式參數*,只是一種符號表達,簡稱形參
?? ?調用
?? ??? ?函數定義,只是聲明了一個函數,它不會被執行,需要調用
?? ??? ?調用的方式,就是函數名加上小括號,括號內寫上參數
?? ??? ?*調用時寫的參數是*實際參數*,是實實在在傳入的值,簡稱實參
定義時是形參,調用時是實參,調用加小括號
python是動態的,強類型語言
因為是動態的,參數沒有定義類型,會帶來很大問題(自由工業化開發會帶來問題)
無法限制參數類型,除非進行判斷
能不能控制這個?是解決團隊的問題
函數參數
?? ?參數調用時傳入的參數要和定義的個數相匹配(可變參數例外)
?? ?位置參數
?? ??? ?def f(x, y, z) 調用使用 f(1, 3, 5)#順序對應,個數也要相同#傳參,傳入實參
?? ??? ?按照參數定義順序傳入實參
?? ?關鍵字參數?? ?#誰等于誰就是關鍵字傳參(keyword)
?? ??? ?def f(x, y, z) 調用使用 f(x=1, y=3, z=5)?? ?#順序可以不一樣,因為可以按名字找
?? ??? ?使用形參的名字來出入實參的方式,如果使用了形參名字,那么傳參順序就可和定義順序不同
?? ?傳參
?? ??? ?f(z=None, y=10, x=[1])
?? ??? ?f((1,), z=6, y=4.1)
?? ??? ?f(y=5, z=6, 2) #位置參數必須在前,keyword在后是可以的
?? ??? ?要求位置參數必須在關鍵字參數之前傳入,位置參數是按位置對應的
函數參數默認值?? ?#記得時候可以記帶等號不可以放前面
? 參數默認值(缺省值)
? 定義時,在形參后跟上一個值
def add(x=4, y=5):
return x+y
測試調用 add(6, 10) 、add(6, y=7) 、add(x=5) 、add()、add(y=7)、 add(x=5, 6) #這個不可以、add(y=8,
4)、add(x=5, y=6)、add(y=5, x=6)
測試定義后面這樣的函數 def add(x=4,y)#非缺省跟在非缺省后不可以(記得時候可以記帶等號不可以放前面)
? 作用
? 參數的默認值可以在未傳入足夠的實參的時候,對沒有給定的參數賦值為默認值
? 參數非常多的時候,并不需要用戶每次都輸入所有的參數,簡化函數調用
? 舉例
? 定義一個函數login,參數名稱為host、port、username、password
函數參數默認值
?
? 在形參前使用*表示該形參是可變參數,可以接收多個實參
****收集多個實參為一個tuple***
可變類型和解構類型,但不全相同(keyword-only)
def fn(*args,x,y,**kwargs)
(x,y)屬于keyword-only:在后面 必須定義關鍵字傳參
可以用缺省值,必須使用關鍵字傳參#經常給keyword-only定義缺省值
def add(*,x,y):?? ?#逗號標志后面的是keyword-only
***總結定義形參和傳參的幾種類型(定義時是形參,調用時是實參)
定義形參:,位置參數,可變位置參數(封裝成元組tuple),可變關鍵字傳參(封裝成dict字典)
定義傳參:位置傳參,關鍵字傳參,混著用的時候:位置傳參在前,關鍵字傳參在后
普通位置傳參:位置傳參和關鍵字傳參都支持但是位置傳參在前
可變參數:
?? ?可變位置傳參:不允許關鍵字傳參,只可以寫在一起讓可變參數對應#add(1,2,3,4)
?? ?可變關鍵字傳參只收集關鍵字傳參,不可以位置傳參
位置參數往放前(可變的也要放前),關鍵字參數放后(記帶星的放后星星放最后)
傳參時對應形參必須只有一個,全是關鍵字傳參可以不考慮順序
函數參數
??? 參數規則
***參數列表參數一般順序是,普通參數、缺省參數、可變位置參數、keyword-only參數(可帶缺
省值)、可變關鍵字參數
模版:def fn(x, y, z=3, *arg, m=4, n, **kwargs):
print(x,y,z,m,n)
print(args)
print(kwargs)
參數解構
***只能在參數傳參中運用
?? ?傳參的時候才解構,解構出元素作為實參
? 非字典類型使用*解構成位置參數
****字典類型使用**解構成關鍵字參數
字典解構:一個*解key,**解字典
add(*{'a': 5, 'b': 6})#解構后為x = 'a',y = 'b'
#add(**{'a': 5, 'b': 6})#解構后為'a' = 5,'b' = 6
函數默認return none,如果想要函數有返回值修改return
------------------------------------------------------------------------------------------------------------------------------------
函數返回值
return 語句
一個函數只有一條return語句
多分支結構可以有多條return,但只能執行一條return
#多分支結構可以設置個變量,最后return變量,可以省著每次分支都寫return
if..ret=..else..ret=..最后return ret
函數可以返回值可以不同類型
一個函數只要碰到return就立即返回終止
函數默認return none,往往函數需要寫return
return返回必須是一個值,不是一個會被它封裝成一個元組
返回多個值包在容器中? 得到它們使用解構一一對應
---------------------------------------------------------------------------------------------------------------------------
作用域****
嵌套函數
?? ?函數內部的函數不可以在外部單獨執行#因為在外部沒有定義,報NameError
?? ?在外部的函數可以調用嵌套在內的函數
****###函數是有可見范圍的,這就是作用域
函數內部的標識符(變量),外部是不可見的
函數定義直接過,執行時看前面定義有沒有用到變量
函數內部
x = 5
def show():
?? ?x += 1#報錯
?? ?print(x)
show()
x = x +1?? ?#在函數內部要先定義,要不然會說內部沒有定義
?? ?#右邊x+1,賦值即重新定義,賦值要先算右邊,
?? ?#右邊是內部本地變量(本地作用域),x要重新定義
嵌套函數:賦值即重新定義,但是是定義自己的變量
全局作用域?? ?#在整個運行環境中都可見
局部作用域(local)?? ?#在函數和類等內部中可見
---------------------------------------------------------------------------------------------------------------------------
全局作用域(了解,寫函數基本不用,改動影響太大)
global x?? ?#使用全局作用域變量
?? ?#盡可能放在前面第一行
global 用在局部作用域中定義一個全局作用域中操作變量
但是global只影響當前作用域
函數應該用定義形參,傳參這種形式用,盡量不要用global
---------------------------------------------------------------------------------------------------------------------------
閉包***#一般在有嵌套函數時候用
自由變量:未在本地作用域中定義的變量。例如定義在內存函數外的外層函數的作用域中的變量
本來變量在外層函數? 內層函數用到了這個局部變量,閉包就已經產生
nonlocal?? ?關鍵字
?? ?#聲明變量不在本地作用域中,但是在外層作用域中找,但是不會再全局作用域中找
?? ?#形成閉包
?? ?#一層層向外找但不在全局中找
?? ?#不可在全局下一層中用(因為全局中的下一層可以直接用全局變量了)
形參可以當局部變量來看
---------------------------------------------------------------------------------------------------------------------------
默認值的作用域
函數也是對象,如果對象中包含引用類型時,會更改默認值,簡單類型不會更改默認值
函數名.__defaults__?? ??? ?#查看默認值屬性,使用元組保存所有位置參數默認值#使用元組位置就不會變
函數名.__kwdefaults__?? ?#查看使用字典保存所有keyword-only參數的默認值,dict是關鍵字傳參
缺省值函數默認的特殊屬性,生命周期跟函數同樣周期共消亡
缺省值只有自己的作用域的,要看缺省值指的是什么,如果指的是缺省值送給形參,形參的作用域就在函數內部,它是局部作用域中的局部變量
#default這個東西它又屬于函數對象本身的特殊屬性,它是放在函數對象上的
#函數對象是和函數定義相關的,函數在定義時它的標識符(形參)關聯到它內存中創建的那一個函數對象上去了
默認值作用域為形參用,形參可以當函數的局部變量來看
如果形參可變的類型(如列表),(無缺省值)沒有固定的缺省值,有缺省值也會變的
#有時候這個特性是好的,有的時候這種特性是不好的,有副作用
def foo(xyz=[], u='abc', z=123):
?? ?xyz.append(1)
?? ?return xyz
print(foo(), id(foo))
print(foo.__defaults__)
print(foo(), id(foo))
print(foo.__defaults__)#引用類型默認值改變
def foo(xyz=[], u='abc', z=123):
?? #xyz = foo.__defaults__
??? xyz = xyz[:] # 影子拷貝,簡單類型空列表內存中新生成一份,內存地址不同
??? xyz.append(1)
??? print(xyz)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10,5])
print(foo.__defaults__)#不改變默認值
def foo(xyz=None, u='abc', z=123):#使用不可變類型默認值
??? if xyz is None:#使用默認值時創建列表
??????? xyz = []
??????? xyz.append(1)# 如果傳入一個列表,就修改這個列表
??? print(xyz)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10,5])
print(foo.__defaults__)
第一種方法
?? ?使用影子拷貝創建一個新的對象,永遠不能改變傳入的參數
第二種方法
?? ?通過值的判斷就可以靈活的選擇創建或者修改傳入對象
?? ?這種方式靈活,應用廣泛
?? ?很多函數的定義,都可以看到使用None這個不可變的值作為默認參數,可以說這是一種慣用法
---------------------------------------------------------------------------------------------------------------------------
變量名解析原則LEGB?? ??? ?#一個名詞的查找順序就是LEGB,一層一層向外解析
LEGB規定了查找一個名稱的順序為:local-->enclosing function locals-->global-->builtin
Local,本地作用域、局部作用域的local命名空間。函數調用時創
建,調用結束消亡
Enclosing,Python2.2時引入了嵌套函數,實現了閉包,這個就
是嵌套函數的外部函數的命名空間
Global,全局作用域,即一個模塊的命名空間。模塊被import時
創建,解釋器退出時消亡
Build-in,內置模塊的命名空間,生命周期從python解釋器啟動
時創建到解釋器退出時消亡。例如 print(open),print和open都是內置的變量
---------------------------------------------------------------------------------------------------------------------------
函數的銷毀
#函數的定義一般只做一次,除非你想把它覆蓋掉再定義一次
#定義函數的目的就是復用,要明確為什么要銷毀,不要輕易銷毀
全局函數的銷毀
?? ? 重新定義同名函數
?? ?del 語句刪除函數對象
?? ?程序結束時
局部函數銷毀
?? ?重新在上級作用域定義同名函數
?? ?del 語句刪除函數名稱,函數對象的引用計數減1
?? ?上級作用域銷毀時
?
--------------------------------------------------------------------------------------------------------------------------
遞歸函數
#棧和線程相關,棧是每個線程自己的空間
函數執行要壓棧,一個落一個,函數局部變量也要壓棧,用完后彈出
#局部變量,函數調用時創建,調用結束消亡
遞歸 Recursion
函數直接或者間接調用自身就是遞歸
遞歸一定要有退出條件 return 出一個結果
每次計算后也要return
import sys
print(sys.getrecursionlimit)?? ?#查看遞歸層數
---------------------------------------------------------------------------------------------------------------------------
匿名函數
格式
?? ?lambda 參數列表 : 表達式
map是生成一個惰性求值的
(lambda x : 0)(3)
冒號后面不可以用等號
---------------------------------------------------------------------------------------------------------------------------
生成器***
生成器generator
next()?? ?#
生成器函數必須包含yield語句,生成器函數的函數體不會立即執行
協程??? #非搶占式,輪詢
yield from?? ?#新語法從可迭代對象中一個個拿元素
for x in range(10)? =>?? yield from range(10)
?? ?yield x
轉載于:https://www.cnblogs.com/springquanquan/p/9573783.html
總結
以上是生活随笔為你收集整理的python学习随笔(七)_函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一副明月眼镜大概多少钱?
- 下一篇: mono+jexus 部署之Compil