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