Python5-函數(shù)設(shè)計與使用_第1頁
Python5-函數(shù)設(shè)計與使用_第2頁
Python5-函數(shù)設(shè)計與使用_第3頁
Python5-函數(shù)設(shè)計與使用_第4頁
Python5-函數(shù)設(shè)計與使用_第5頁
已閱讀5頁,還剩70頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Python5函數(shù)設(shè)計與使用Python5函數(shù)設(shè)計與使用Python5函數(shù)設(shè)計與使用Python5函數(shù)設(shè)計與使用Python5函數(shù)設(shè)計與使用1函數(shù)在實際開發(fā)中,有許多操作時完全相同或非常相似的,僅僅是要處理的數(shù)據(jù)不同,為此需要實現(xiàn)代碼復(fù)用。函數(shù):可能需要反復(fù)執(zhí)行的代碼封裝為函數(shù),并在需要該段代碼功能的地方調(diào)用??梢詫崿F(xiàn)代碼的復(fù)用更重要的是可以保證代碼的一致性,只需要修改該函數(shù)代碼則所有調(diào)用均受到影響Python提供了許多常用的內(nèi)置函數(shù)如len(),sum()等,也可以自定義函數(shù)。另一種代碼復(fù)用方式:定義面向?qū)ο蟪绦蛟O(shè)計中的類函數(shù)在實際開發(fā)中,有許多操作時完全相同或非常相似的,僅僅是要25.1函數(shù)定義與調(diào)用5.1函數(shù)定義與調(diào)用35.1函數(shù)定義與調(diào)用創(chuàng)建或定義函數(shù)要使用def關(guān)鍵字函數(shù)定義(聲明)格式:

def函數(shù)名([形參列表]):

'''可選的注釋'''

函數(shù)體函數(shù)調(diào)用:

函數(shù)名([實參列表])注意:函數(shù)名命名規(guī)則建議為全小寫字母,可以用下劃線增加閱讀性,如my_func形參列表用()括起來,一個函數(shù)可以沒有形參(parameter),表示不需要接收任何參數(shù),但是括弧必須要有括號后面的冒號必不可少,表示接下來是函數(shù)體#!/usr/local/bin/python3#-*-coding:utf-8-*-"""functiondemo"""

def

fib(n):

'''acceptanintegern.returnthenumberslessthanninFibonaccisequence.'''a,b=

1,

1

whilea<n:

print(a,end='')a,b=b,a+b

print()

def

test_fib(

):n=int(input('請輸入整數(shù)n:'))fib(n)5.1函數(shù)定義與調(diào)用創(chuàng)建或定義函數(shù)要使用def關(guān)鍵字#!/45.1函數(shù)定義與調(diào)用創(chuàng)建或定義函數(shù)要使用def關(guān)鍵字函數(shù)定義(聲明)格式:

def函數(shù)名([形參列表]):

'''注釋'''

函數(shù)體函數(shù)調(diào)用:

函數(shù)名([實參列表])def

fib(n):

'''acceptanintegern.returnthenumberslessthanninFibonaccisequence.'''a,b=

1,

1

whilea<n:

print(a,end='')a,b=b,a+b

print()def

cubic(n):

returnn**3

函數(shù)體一般包括多行,相對于def關(guān)鍵字必須保持一定的空格縮進,是函數(shù)執(zhí)行的代碼塊如果函數(shù)體比較簡單時,也可以與def在同一行:pass語句為空語句,經(jīng)常用在定義一個空函數(shù),以后再擴充函數(shù)可以返回值,也可以不返回。如果函數(shù)體中包含return語句,則執(zhí)行到那里時從函數(shù)中返回(同時返回return語句中相應(yīng)表達式的值,如果未指定則為None),后面的代碼不再執(zhí)行如果執(zhí)行到函數(shù)結(jié)束也無return語句,則等價于returnNone函數(shù)調(diào)用時,根據(jù)需要,可指定實際傳入的參數(shù)值,同時獲取返回值5.1函數(shù)定義與調(diào)用創(chuàng)建或定義函數(shù)要使用def關(guān)鍵字def55.1函數(shù)定義與調(diào)用定義函數(shù)(及模塊)時,開頭部分的注釋并不是必需的,但是如果為函數(shù)的定義加上這段注釋的話,可以為用戶提供友好的提示和使用幫助。該字符串保存在函數(shù)(及模塊)對象的__doc__屬性中,稱為docstringhelp(fib)可以查看相應(yīng)的__doc__屬性IDE界面會給出相應(yīng)的calltip#!/usr/local/bin/python3#-*-coding:utf-8-*-"""functiondemo"""

def

fib(n):

'''acceptanintegern.returnthenumberslessthanninFibonaccisequence.'''a,b=

1,

1

whilea<n:

print(a,end='')a,b=b,a+b

print()

def

test_fib(

):n=int(input('請輸入整數(shù)n:'))fib(n)5.1函數(shù)定義與調(diào)用定義函數(shù)(及模塊)時,開頭部分的注釋并65.2形參與實參5.2形參與實參75.2形參與實參函數(shù)定義(聲明)格式:

def函數(shù)名([形參列表]):

'''注釋'''

函數(shù)體函數(shù)調(diào)用:

函數(shù)名([實參列表])>>>deffib(n):

'''acceptanintegern.returnthenumberslessthanninFibonaccisequence.'''a,b=1,1whilea<n:print(a,end='')a,b=b,a+bprint()>>>fib(1000)#函數(shù)調(diào)用1123581321345589144233377610987形參(parameter)實參(argument)5.2形參與實參函數(shù)定義(聲明)格式:>>>deffi85.2形參與實參定義函數(shù)時,對參數(shù)個數(shù)沒有限制,如有多個形參,則需要使用逗號進行分隔。如:編寫函數(shù),接受兩個整數(shù),并輸出其中最大數(shù)。>>>defprintMax(a,b):

ifa>b:print(a,'isthemax')

else:print(b,'isthemax')>>>printMax(3,4)4isthemax注意:這個程序如果輸入的參數(shù)不支持比較運算,會出錯。5.2形參與實參定義函數(shù)時,對參數(shù)個數(shù)沒有限制,如有多個形95.2形參與實參為了避免sideeffect,函數(shù)中的形參(變量)的使用范圍為函數(shù)體(作用域部分會詳細介紹)函數(shù)調(diào)用時向其傳遞實參,python采用賦值傳遞(passbyassignment)的策略與其它高級語言的passbyvalue以及passbyreference不同形參變量=實參變量,即形參變量與實參變量指向同一個對象絕大多數(shù)情況下,在函數(shù)內(nèi)部直接修改形參的值不會影響實參對于不可變對象,顯然如此對于可變對象,如果不是采用in-place(原地)方法來改變該可變對象的值時,也不會影響>>>def

addOne(a): print(a) a+=1 print(a)>>>a=3>>>addOne(a)34>>>a35.2形參與實參為了避免sideeffect,函數(shù)中的形105.2形參與實參可變對象的原地操作會影響函數(shù)外部實參的值,許多時候會要利用該特性>>>defmodify(v):#修改列表元素值

v[0]=v[0]+1

>>>a=[2]>>>modify(a)>>>a[3]注意:如果傳遞給函數(shù)的是Python可變序列,并且在函數(shù)內(nèi)部使用下標(biāo)或其他方式為可變序列增加、刪除元素或修改元素值時,可以使得實參得到相應(yīng)的修改。>>>defmodify(v,item):#為列表增加元素

v.append(item)

>>>a=[2]>>>modify(a,3)>>>a[2,3]>>>defmodify(d):#修改字典元素值或為字典增加元素

d['age']=38>>>a={'name':'Dong','age':37,'sex':'Male'}>>>a{'sex':'Male','age':37,'name':'Dong'}>>>modify(a)>>>a{'sex':'Male','age':38,'name':'Dong'}5.2形參與實參可變對象的原地操作會影響函數(shù)外部實參的值,115.3參數(shù)類型5.3參數(shù)類型125.3參數(shù)類型在Python中,函數(shù)參數(shù)有很多種:普通參數(shù)默認值參數(shù)關(guān)鍵參數(shù)可變長度參數(shù)等等。Python函數(shù)的定義非常靈活,在定義函數(shù)時不需要指定參數(shù)的類型,形參的類型完全由調(diào)用者傳遞的實參類型以及Python解釋器的理解和推斷來決定,類似于重載和泛型(polymorphism);函數(shù)編寫如果有問題,只有在調(diào)用時才能被發(fā)現(xiàn),傳遞某些參數(shù)時執(zhí)行正確,而傳遞另一些類型的參數(shù)時則出現(xiàn)錯誤。5.3參數(shù)類型在Python中,函數(shù)參數(shù)有很多種:135.3.1默認值參數(shù)Python在定義函數(shù)時,支持默認值參數(shù),即可為形參設(shè)置默認值。def函數(shù)名(……,形參名=默認值)函數(shù)體僅僅包含形參名的參數(shù)稱為位置(positional)參數(shù),根據(jù)其出現(xiàn)的位置順序來逐個匹配相應(yīng)的實參調(diào)用帶有默認值參數(shù)的函數(shù)時,可以不對默認值參數(shù)進行賦值,也可以賦值,具有較大的靈活性。使用“函數(shù)名.__defaults__”以元組的形式查看函數(shù)所有默認值參數(shù)的當(dāng)前值。>>>defsay(message,times=1): print(message*times)

>>>say('hello')#不為默認值參數(shù)傳值hello>>>say('hello',3)#使用調(diào)用者顯示傳遞的值hellohellohello>>>say('hi',7)#使用調(diào)用者顯示傳遞的值hihihihihihihi>>>say.__defaults__(1,)5.3.1默認值參數(shù)Python在定義函數(shù)時,支持默認值參數(shù)145.3.1默認值參數(shù)(defaultsparameter)函數(shù)定義時最前面是位置參數(shù),然后是默認值參數(shù)即默認值參數(shù)右邊不能再有位置參數(shù)。為什么這樣設(shè)計?函數(shù)調(diào)用時默認值參數(shù)可能并沒有包含在實參中!5.3.1默認值參數(shù)(defaultsparameter)155.3.1默認值參數(shù)例:使用指定分隔符將列表中所有字符串元素連接成一個字符串,默認空格。>>>defJoin(List,sep=None): return(sepor'').join(List)>>>aList=['a','b','c']>>>Join(aList)'abc‘>>>Join(aList,',')'a,b,c'5.3.1默認值參數(shù)例:使用指定分隔符將列表中所有字符串元素165.3.1默認值參數(shù)在函數(shù)定義時,計算默認值得到一個tuple,然后保存在func.__defaults__函數(shù)調(diào)用時如何確定默認值參數(shù)的值?如果實參中給出了相應(yīng)的值,則該形參指向?qū)崊⑺玫膶ο笕绻麑崊]有傳遞值,則該形參變量賦予默認值,而默認值保存在func.__defaults__如果默認值參數(shù)的默認值為可變對象,且前面調(diào)用該函數(shù)時原地修改了該對象,保存在__defaults__元組中的默認值也會被修改這種特性可能導(dǎo)致很難發(fā)現(xiàn)的邏輯錯誤。也可能是故意這樣來設(shè)計在函數(shù)的多次調(diào)用間保存狀態(tài)信息5.3.1默認值參數(shù)在函數(shù)定義時,計算默認值得到一個tupl175.3.1默認值參數(shù)>>>defdemo(newitem,old_list=[]):old_list.append(newitem)returnold_list>>>print(demo('5',[1,2,3,4]))#right[1,2,3,4,'5']>>>print(demo('aaa',['a','b']))#right['a','b','aaa']>>>print(demo('a'))#right['a']>>>print(demo('b'))['a','b']>>>print(demo.__defaults__)(['a','b'],)注意:多次調(diào)用函數(shù)并且不為默認值參數(shù)傳遞值時,默認值參數(shù)值在第一次調(diào)用時被更改,可以使用函數(shù)名.__defaults__查看默認參數(shù)的當(dāng)前值如何修改?5.3.1默認值參數(shù)>>>defdemo(newitem185.3.1默認值參數(shù)修改程序如下:defdemo(newitem,old_list=None):ifold_listisNone:old_list=[]old_list.append(newitem)returnold_listprint(demo('5',[1,2,3,4]))#rightprint(demo('aaa',['a','b']))#rightprint(demo('a'))#rightprint(demo.__defaults__)print(demo('b'))+運行該程序,看看和前面的有什么不同?缺省值參數(shù)的缺省值避免采用可變對象,或者采用可變對象但是函數(shù)體不要進行原地操作。除非故意設(shè)計以利用可變對象的這一特征5.3.1默認值參數(shù)修改程序如下:defdemo(newi195.3.2關(guān)鍵字參數(shù)(keywordargument)關(guān)鍵字參數(shù)主要指實參,即調(diào)用函數(shù)時的參數(shù)傳遞方式。通過關(guān)鍵字參數(shù)可以按參數(shù)名字傳遞值,實參順序可以和形參順序不一致,但不影響傳遞結(jié)果,避免了用戶需要牢記位置參數(shù)順序的麻煩。在函數(shù)定義中有多個缺省值參數(shù)時通過關(guān)鍵字參數(shù)來明確傳遞哪些參數(shù),哪些采用缺省值注意關(guān)鍵字參數(shù)與函數(shù)定義時的缺省值參數(shù)的區(qū)別,雖然兩者形式一致,但兩者之間并不等同調(diào)用時可以使用位置參數(shù)和關(guān)鍵字來傳遞參數(shù),但是與函數(shù)定義時類似,關(guān)鍵字參數(shù)右邊不能有位置參數(shù)

>>>defdemo(a,b,c=5): print(a,b,c)>>>demo(3,7)375>>>demo(a=7,b=3,c=6)736>>>demo(c=8,a=9,b=0)908deffunc(a,b,c=5,d=6):print(a,b,c,d)func(1,2,7)func(1,2,5,8)func(b=1,a=2,c=7)func(1,2,d=8)func(1,b=2,d=8)5.3.2關(guān)鍵字參數(shù)(keywordargument)關(guān)鍵205.3.3可變長度參數(shù)(variable-lengthparameters)可變長度參數(shù)在定義函數(shù)時主要有兩種形式:*parameter:將那些尚沒有匹配形參的位置實參組合成一個元組賦值給可變長度位置參數(shù)。**parameter:將那些尚沒有匹配形參的關(guān)鍵字實參組合成一個dict賦值給該參數(shù)如果存在,*name形式的參數(shù)應(yīng)該出現(xiàn)在缺省值參數(shù)之后如果存在,**name形式的參數(shù)應(yīng)該出現(xiàn)在最后每種類型的可變長度參數(shù)只能出現(xiàn)一次>>>defdemo(*p): print(p)>>>demo(1,2,3)(1,2,3)>>>demo(1,2)(1,2)>>>demo(1,2,3,4,5,6,7)(1,2,3,4,5,6,7)*parameter無論調(diào)用該函數(shù)時傳遞了多少實參,沒有匹配的位置參數(shù)一律將其放在元組中。5.3.3可變長度參數(shù)(variable-lengthp215.3.3可變長度參數(shù)(variable-lengthparameters)可變長度參數(shù)在定義函數(shù)時主要有兩種形式:*parameter:收集沒有匹配的位置實參放在一個元組中**parameter,收集沒有匹配的關(guān)鍵字實參放在一個字典中。>>>defdemo(*p): print(p)>>>demo(1,2,3)(1,2,3)>>>demo(1,2)(1,2)>>>demo(1,2,3,4,5,6,7)(1,2,3,4,5,6,7)(1)*parameter無論調(diào)用該函數(shù)時傳遞了多少實參,一律將其放在元組中。>>>defdemo(**p): foriteminp.items(): print(item)

>>>demo(x=1,y=2,z=3)('z',3)('y',2)('x',1)(2

)**parameter調(diào)用該函數(shù)時自動將接收的關(guān)鍵字參數(shù)轉(zhuǎn)換為字典。5.3.3可變長度參數(shù)(variable-lengthpa22僅允許關(guān)鍵字傳遞的形參(keyword-onlyparameter)補充Python3還引入了keyword-only形參,即這些參數(shù)只能通過關(guān)鍵字參數(shù)的形式來傳遞keyword-only參數(shù)出現(xiàn)在可變長度的位置參數(shù)之后如果沒有可變長度位置參數(shù),則添加一個*keyword-only參數(shù)也可以指定缺省值,即支持name或者name=default方式調(diào)用時必須采取關(guān)鍵字參數(shù)傳遞,或者不傳遞表示采用缺省值def

kwonly(a,

*b,c,d=5):

return

(a,b,c,d)

def

kwonly2(a,b,*,c,d=5):

return

(a,b,c,d)

print(kwonly(1,

2,c=3))print(kwonly2(1,

2,c=3,d=4))僅允許關(guān)鍵字傳遞的形參(keyword-onlyparam23形參與實參之間的匹配函數(shù)定義中的形參順序位置參數(shù)

缺省值參數(shù)

可變長度位置參數(shù)

僅允許關(guān)鍵字傳遞參數(shù)

可變長度字典參數(shù)函數(shù)調(diào)用中的實參順序:位置參數(shù)

關(guān)鍵字參數(shù)函數(shù)調(diào)用時,根據(jù)傳遞的實參按照以下規(guī)則匹配形參:首先按照位置匹配形參中的位置參數(shù)和缺省值參數(shù)接下來根據(jù)關(guān)鍵字參數(shù)的名字匹配形參中的各個參數(shù)剩下的位置參數(shù)組成tuple賦值給可變長度位置參數(shù)剩下的關(guān)鍵字參數(shù)組成dict賦值給可變長度字典參數(shù)函數(shù)定義中尚未匹配的參數(shù)設(shè)置為缺省值如果仍然有尚未匹配的形參和實參則報錯每個參數(shù)只能匹配一次形參與實參之間的匹配函數(shù)定義中的形參順序245.3.3可變長度參數(shù)(教材上例子)幾種不同類型的參數(shù)可以混合使用不建議這樣做,易導(dǎo)致代碼混亂而嚴重降低可讀性,可能導(dǎo)致查錯非常困難>>>deffunc_4(a,b,c=4,*aa,**bb): print(a,b,c) print(aa) print(bb)

>>>func_4(1,2,3,4,5,6,7,8,9,xx='1',yy='2',zz=3)123(4,5,6,7,8,9){'zz':3,'xx':'1','yy':'2'}>>>func_4(1,2,3,4,5,6,7,xx='1',yy='2',zz=3)123(4,5,6,7){'zz':3,'xx':'1','yy':'2'}5.3.3可變長度參數(shù)(教材上例子)幾種不同類型的參數(shù)可以混25例子def

_print(*args,sep='',end='\n',file=sys.stdout,flush=False):line=

[]

forvalueinargs:line.append(format(value))file.write(sep.join(line))file.write(end)

ifflush:file.flush()def

_trace(func,*args,**kwargs):

ifhasattr(func,'calls'):func.calls+=

1

else:func.calls=

1

ifkwargs:

print('[%d]callingfunction:%s(%s,%s)'%

(func.calls,func.__name__,

','.join(map(str,args)),

','.join([k+'='+str(v)

fork,vinkwargs.items()])))

else:

print('[%d]callingfunction:%s(%s)'%

(func.calls,func.__name__,

','.join(map(str,args))))

returnfunc(*args,**kwargs)_print函數(shù)實現(xiàn)print類似的功能_trace:跟蹤函數(shù)的調(diào)用,利用函數(shù)對象的屬性來保存函數(shù)調(diào)用的狀態(tài)信息。注意內(nèi)置函數(shù)不支持用戶自定義的屬性+思考:你還知道有什么辦法來保存函數(shù)調(diào)用的狀態(tài)信息嗎?例子def_print(*args,sep='',en265.3.4參數(shù)傳遞的序列解包為含有多個變量的函數(shù)傳遞參數(shù)時,可以使用Python列表、元組、集合、字典以及其他可迭代對象作為實參,并在實參名稱前加一個星號*,Python解釋器將自動進行解包。等價于傳遞多個參數(shù),每個參數(shù)為迭代對象的每個元素(對于字典而言為每個key)**表示對于字典對象進行序列解包等價于傳遞多個關(guān)鍵字參數(shù),關(guān)鍵字的變量名為字典對象dictobj的key,而值為dictobj[key]注意序列解包與函數(shù)定義時的可變長參數(shù)的區(qū)別。>>>defdemo(a,b,c): print(a+b+c) >>>seq=[1,2,3]>>>demo(*seq)6>>>tup=(1,2,3)>>>demo(*tup)6>>>dic={1:'a',2:'b',3:'c'}>>>demo(*dic)6>>>set={1,2,3}>>>demo(*set)6>>>demo(*dic.values())abc>>>dic2={'a':1,'b':2,'c':3}

>>>demo(**dic2)65.3.4參數(shù)傳遞的序列解包為含有多個變量的函數(shù)傳遞參數(shù)時27例子def

_trace(func,*args,**kwargs):

ifhasattr(func,'calls'):func.calls+=

1

else:func.calls=

1

ifkwargs:

print('[%d]callingfunction:%s(%s,%s)'%

(func.calls,func.__name__,

','.join(map(str,args)),

','.join([k+'='+str(v)

fork,vinkwargs.items()])))

else:

print('[%d]callingfunction:%s(%s)'%

(func.calls,func.__name__,

','.join(map(str,args))))

returnfunc(*args,**kwargs)例子def_trace(func,*args,**kwar285.4return語句5.4return語句295.4return語句return語句用于從一個函數(shù)中返回并結(jié)束函數(shù)的執(zhí)行,同時還可以通過其從函數(shù)中返回一個值。無論return語句出現(xiàn)在函數(shù)的什么位置,一旦得到執(zhí)行將直接結(jié)束函數(shù)的執(zhí)行。函數(shù)的返回值類型由return語句返回值的類型來決定如果函數(shù)沒有return語句或者沒有執(zhí)行return語句,執(zhí)行了不帶任何值的return語句,則函數(shù)都默認為返回空值None。>>>defmaximum(x,y): ifx>y: returnx else: returny>>>theMax=maximum(3,4)>>>print(theMax)45.4return語句return語句用于從一個函數(shù)中返回305.4return語句在調(diào)用內(nèi)置數(shù)據(jù)類型的方法時,一定要注意該方法有沒有返回值。print([1,2,3,4,9,5,7].sort())可能不是想要的結(jié)果:sort方法為原地排序,返回None>>>defmaximum(x,y): ifx>y: returnx else: returny>>>theMax=maximum(3,4)>>>print(theMax)4>>>defmaximum(x,y): ifx>y: print(x) else: print(y)>>>theMax=maximum(3,4)4>>>print(theMax)None(1)具有返回值(2)

沒有返回值。5.4return語句在調(diào)用內(nèi)置數(shù)據(jù)類型的方法時,一定要注318.6

使用IDLE調(diào)試代碼(p202)首先單擊菜單“Debug””Debugger”打開調(diào)試器窗口然后打開并運行要調(diào)試的程序切換到調(diào)試器窗口進行調(diào)試IDEL調(diào)試器窗口Go:繼續(xù)執(zhí)行Step:按順序執(zhí)行代碼Over:按順序執(zhí)行代碼,如果為函數(shù),則不進入函數(shù)體內(nèi)Out:執(zhí)行代碼直到跳出當(dāng)前函數(shù)體在源代碼.py文件中鼠標(biāo)右鍵彈出上下文菜單后可以設(shè)置和清除當(dāng)前行的斷點

8.6使用IDLE調(diào)試代碼(p202)首先單擊菜單“Deb325.5變量作用域5.5變量作用域335.5變量作用域(scope)變量保存的是對象的引用:變量起作用的范圍稱為變量作用域。對象沒有所謂作用域的概念,但是要引用對象,必須要通過變量一個變量在函數(shù)外部定義和在函數(shù)內(nèi)部定義,其作用域是不同的:只有定義(賦值)、global和nonlocal才會建立或者改變變量的作用域局部變量:一般而言,在函數(shù)內(nèi)部定義(包括參數(shù))的變量,有效范圍為函數(shù)體全局變量:在模塊內(nèi)定義且不在函數(shù)內(nèi)定義的變量,有效范圍為定義的模塊局部變量的引用比全局變量速度快。全局變量增加了不同函數(shù)之間的隱式耦合度。5.5變量作用域(scope)變量保存的是對象的引用:345.5.1局部變量局部變量在函數(shù)內(nèi)定義,只在該函數(shù)內(nèi)起作用函數(shù)的形參屬于局部變量函數(shù)結(jié)束時,無法再訪問局部變量被自動刪除。def

local(a=0):x=

3y=

4

print(a,x,y)#print(X)

X=

88

#globallocal(2)print(x)234Traceback(mostrecentcalllast):print(x)NameError:name'x'isnotdefined5.5.1局部變量局部變量在函數(shù)內(nèi)定義,只在該函數(shù)內(nèi)起作用355.5.2全局變量全局變量:其作用域為全局的,能夠同時作用于函數(shù)內(nèi)外。deffunc1(a=0):x=

3y=

4

print(a,x,y)

print(X)

X=

88

#globalprint(X)func1(2)8823488def

local(a=0):x=

3y=

4

print(a,x,y)#print(X)

X=

88

#globallocal(2)print(x)234Traceback(mostrecentcalllast):print(x)NameError:name'x'isnotdefined變量綁定:決定變量所指向的對象latebinding:函數(shù)中的變量在調(diào)用時才會綁定5.5.2全局變量全局變量:其作用域為全局的,能夠同時作用36函數(shù)作用域可以在任何地方(選擇、循環(huán)、函數(shù)內(nèi)部)定義函數(shù),只要該處支持語句選擇和循環(huán)結(jié)構(gòu)不會改變變量的作用域:在退出循環(huán)之后仍然有效列表解析式中引入的變量是局部變量,退出之后不再有效latebinding:函數(shù)中的全局變量在調(diào)用時才會綁定functions=

[]fornin

[1,

2,

3]:

def

func(x):

returnn*xfunctions.append(func)

#期待輸出[2,4,6],但是輸出[6,6,6]print([function(2)

forfunctioninfunctions])

functions=

[]fornin

[1,

2,

3]:

def

func(x,n=n):

returnn*xfunctions.append(func)

print([function(2)

forfunctioninfunctions])

函數(shù)作用域可以在任何地方(選擇、循環(huán)、函數(shù)內(nèi)部)定義函數(shù),只37變量的作用域搜索在訪問變量(注意不是賦值)時,怎么找到具體是哪個作用域內(nèi)的變量?Local:函數(shù)內(nèi)部賦值的變量,且沒有通過global/nonlocal聲明過

Enclosing:外層函數(shù)內(nèi)部賦值的變量,從最里層往外層搜索

Global(模塊):在函數(shù)外部定義的變量或者在函數(shù)體內(nèi)通過global聲明過Builtin(python):在python環(huán)境的內(nèi)置模塊built-in中定義的變量LEGB規(guī)則:按照順序搜索相應(yīng)的作用域,直到找到匹配為止LocalEnclosingGlobalBuiltinglobalx:改變x的作用域為全局變量nonlocalx:表示x不是局部變量,而是外層函數(shù)中定義的變量,跳過local作用域從里到外往外層函數(shù)(但不會到函數(shù)外)搜索變量的作用域搜索在訪問變量(注意不是賦值)時,怎么找到具體是38賦值改變作用域注意:global/nonlocal會跳過局部作用域,改變其作用域分別為全局范圍和外層的某個函數(shù)范圍。賦值會改變變量的作用域,而賦值發(fā)生的地方?jīng)Q定了其所在的作用域def

func1():

print(X)

def

func2():

print(X)X=X+

1

print(X)X=

88func1()print()func2()print()88Traceback(mostrecentcalllast):print(X)UnboundLocalError:localvariable'X'referencedbeforeassignmentX在函數(shù)體內(nèi)賦值,作用域為Local賦值改變作用域注意:deffunc1():88X在函數(shù)體內(nèi)39賦值改變作用域內(nèi)層的(局部)變量會隱藏更外層同名的(全局)變量def

func1():

print(X)

def

func2():

print(X)X=X+

1

print(X)def

func2_():

print(X)

Y=X+

1

print(Y)X=88func2_()8889def

func3():X=

1

print(X)X=88func3()88UnboundLocalError:localvariable'X'1def

func3_():X=

1

print(X)

importsys

print(sys.modules[__name__].X)

88可通過模塊對象來訪問全局變量賦值改變作用域內(nèi)層的(局部)變量會隱藏更外層同名的(全局)變40global改變作用域globalx:表示x為全局變量,當(dāng)函數(shù)體要改變?nèi)肿兞康闹禃r使用def

func1():

print(X)

def

func2():

print(X)X=X+

1

print(X)def

func2_():

print(X)

Y=X+

1

print(Y)X=88func2_()print(X)88898888UnboundLocalError:localvariable'X'def

func4():

globalX

print(X)

#globalXX=X+

1

print(X)

func4(

)print(X)

888989global改變作用域globalx:表示x為全局變量,415.8高級話題(6)嵌套函數(shù)(補充)在函數(shù)體內(nèi)再定義新的函數(shù)Python中函數(shù)也是對象def

linear(a,b):

def

result(x):

returna*x+b

returnresult

func_1_1=linear(1,

1)func_2_1=linear(2,

1)print('f(x)=x+1,f(10)=',func_1_1(10))print('f(x)=2x+1,f(10)=',func_2_1(10))自由變量:在函數(shù)體內(nèi)未賦值但是使用的變量在result函數(shù)定義時,a和b為自由變量按照LEGB規(guī)則,自由變量繼續(xù)在外層函數(shù)中由里到外尋找。每次調(diào)用linear返回一個新的函數(shù)對象func,返回的函數(shù)對象不再依賴于外層函數(shù)linear(實際上已經(jīng)返回退出了)外層函數(shù)return時進行非全局的自由變量的綁定保存在func.__closure__中含有自由變量的代碼塊稱為閉包(closure)5.8高級話題(6)嵌套函數(shù)(補充)在函數(shù)體內(nèi)再定義新的42嵌套函數(shù)的latebinding不是在定義函數(shù)時綁定,而是在定義函數(shù)的函數(shù)體中返回時綁定非全局的自由變量在函數(shù)調(diào)用時綁定全局變量

def

makeActs():funcs=

[]

foriinrange(3):j=

[i]

print(hex(id(j)))

def

func(n):

print(n*j[0])

print(hex(id(j)))funcs.append(func)

returnfuncs

acts=makeActs()[act(10)

foractinacts]0x1148da00x113d6980x11478f0200x11478f0200x11478f0200x11478f0期待輸出為:0*n,n,*2n(n=10),即0,10,20實際輸出:20,20,20可以看到自由變量j都指向同一個對象

與global語句類似,如果在內(nèi)層函數(shù)要對于外層的自由變量賦值,需要使用nonlocal語句表示函數(shù)體賦值不會變?yōu)榫植孔兞?,而是外層函?shù)的自由變量嵌套函數(shù)的latebinding不是在定義函數(shù)時綁定,而是43嵌套函數(shù)的latebindingdef

makeActs2():funcs=

[]

foriinrange(3):j=

[i]

print(hex(id(j)))

def

func(n,

j=j):

print(n*j[0])

print(hex(id(j)))funcs.append(func)

returnfuncs

acts2=makeActs2()[act(10)

foractinacts2]

def

makeActs():funcs=

[]

foriinrange(3):j=

[i]

print(hex(id(j)))

def

func(n):

print(n*j[0])

print(hex(id(j)))funcs.append(func)

returnfuncs

acts=makeActs()[act(10)

foractinacts]0x11334400x113d0800x114237800x1133440100x113d080200x1142378嵌套函數(shù)的latebindingdefmakeActs2445.8高級話題:可調(diào)用對象函數(shù)可以調(diào)用,實際上函數(shù)通過classfunction來實現(xiàn)自己定義的類如果實現(xiàn)了__call__()方法,則也是可調(diào)用對象class

linear2:

def

__init__(self,a,b):self.a,self.b=a,b

def

__call__(self,x):

returnself.a*x+self.b

taxes=linear2(0.3,2)print(taxes(5))

#3.5def

linear(a,b):

def

result(x):

returna*x+b

returnresult

dir(linear)dir(linear2)5.8高級話題:可調(diào)用對象函數(shù)可以調(diào)用,實際上函數(shù)通過c455.5.2全局變量(教材上的例子)全局變量:其作用域為全局的,能夠同時作用于函數(shù)內(nèi)外。>>>defdemo(): globalx x=3 y=4 print(x,y)>>>x=5>>>demo()34>>>x3>>>yTraceback(mostrecentcalllast):File"<pyshell#83>",line1,in<module>yNameError:name'y'isnotdefined>>>delx>>>xTraceback(mostrecentcalllast):File"<pyshell#85>",line1,in<module>xNameError:name'x'isnotdefined一個變量已在函數(shù)外定義,如果在函數(shù)內(nèi)需要為這個變量賦值,并要將這個賦值結(jié)果反映到函數(shù)外,可以在函數(shù)內(nèi)用global聲明這個變量,將其映射到全局作用域。5.5.2全局變量(教材上的例子)全局變量:其作用域為全局465.5.2全局變量(教材上的例子)全局變量:其作用域為全局的,能夠同時作用于函數(shù)內(nèi)外>>>defdemo(): globalx x=3 y=4 print(x,y)>>>demo()34>>>x3>>>yTraceback(mostrecentcalllast):File"<pyshell#98>",line1,in<module>yNameError:name'y'isnotdefined在函數(shù)內(nèi)部直接將一個變量聲明為全局變量,在函數(shù)外沒有聲明,在調(diào)用這個函數(shù)之后,將增加為新的全局變量。5.5.2全局變量(教材上的例子)全局變量:其作用域為全局475.5.2全局變量示例示例pi=3.141592653589793e=2.718281828459045defmy_func():globalpipi=3.14print('globalpi=',pi)e=2.718print('locale=',e)print('modulepi=',pi)print('modulee=',e)my_func()print('modulepi=',pi)print('modulee=',e)5.5.2全局變量示例示例pi=3.14159265358485.6lambda表達式(自學(xué))5.6lambda表達式(自學(xué))495.6lambda表達式lambda表達式用來定義一個僅僅包含一行代碼的匿名函數(shù),即沒有函數(shù)名字,函數(shù)體只可以包含一個表達式,且該表達式的計算結(jié)果為函數(shù)的返回值。不允許包含其他復(fù)雜的語句,只能是表達式,但是注意函數(shù)調(diào)用也是表達式,因此可以調(diào)用print、map、list等lambda表達式也是函數(shù)的一種,因此也遵循前面介紹過的函數(shù)的參數(shù)定義和傳遞、函數(shù)的作用域所使用的規(guī)則含有默認參數(shù),調(diào)用時使用關(guān)鍵參數(shù)f=lambdax,y,z:x+y+zprint

(f(1,2,3))

def

f(x,y,z):

returnx+y+zg=lambdax,y=2,z=3:x+y+zprint

(g(2,z=4,y=5))print

(g(2,z=4))

1185.6lambda表達式lambda表達式用來定義一個僅僅505.6lambda表達式lambda表達式是匿名函數(shù),避免了可能的名字沖突可以用作CodeJumpTable:代碼跳轉(zhuǎn)表可以用于那些參數(shù)為函數(shù)對象的函數(shù),比如map、reduce、filtered、sorted等key='f1'

D='f1':

(lambda:

2

+

2),'f2':

(lambda:

2

*

4),'f3':

(lambda:

2

**

6)}

print(D[key]())

L=

[lambdax:x**

2,

lambdax:x**

3,

lambdax:x**

4]

forfinL:

print(f(2))print(L[0](3))

5.6lambda表達式lambda表達式是匿名函數(shù),避免515.6lambda表達式>>>L=[1,2,3,4,5]>>>print(map((lambdax:x+10),L))[11,12,13,14,15]>>>L[1,2,3,4,5]>>>defdemo(n): returnn*n>>>demo(5)25>>>a_list=[1,2,3,4,5]>>>list(map(lambdax:demo(x),a_list))[1,4,9,16,25]lambda表達式不允許包含其他復(fù)雜的語句,但在表達式中可以調(diào)用其他函數(shù)。沒有名字的lambda表達式?jīng)]有名字的,使用函數(shù)調(diào)用的lambda表達式5.6lambda表達式>>>L=[1,2,3,4,5]525.6lambda表達式>>>data=range(20)>>>print(data)[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]>>>importrandom>>>random.shuffle(data)>>>print(data)[4,3,11,13,12,15,9,2,10,6,19,18,14,8,0,7,5,17,1,16]>>>data.sort(key=lambdax:x)>>>print(data)[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]>>>data.sort(key=lambdax:len(str(x)))>>>print(data)[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]>>>data.sort(key=lambdax:len(str(x)),reverse=True)>>>print(data)[10,11,12,13,14,15,16,17,18,19,0,1,2,3,4,5,6,7,8,9]lambda表達式其他示例5.6lambda表達式>>>data=range(20535.7案例精選5.7案例精選545.7案例精選:遞歸函數(shù)(補充)遞歸函數(shù):指的是在函數(shù)體內(nèi)直接或者間接調(diào)用本函數(shù)實現(xiàn)起來非常方便,但應(yīng)注意遞歸調(diào)用不要一直進行下去,沒有終止遞歸調(diào)用的深度是受到限制的效率較低,如果有可能通過循環(huán)實現(xiàn)def

factorialRecur(n):

#階乘,通過遞歸實現(xiàn)

ifn==

1:

return

1

else:

returnn*factorialRecur(n-

1)importsysprint(sys.getrecursionlimit())

#1000old=sys.getrecursionlimit()sys.setrecursionlimit(50)print(factorialRecur(45))sys.setrecursionlimit(old)"C:\Users\dlmao\PycharmProjects\pythonClass\function.py",line540,infactorialRecurifn==1:RecursionError:maximumrecursiondepthexceededincomparisondef

factorial(n):

#階乘,通過loop實現(xiàn)result=n

foriinrange(1,n):result*=i

returnresult5.7案例精選:遞歸函數(shù)(補充)遞歸函數(shù):指的是在函數(shù)體555.7案例精選例1:編寫函數(shù)計算圓的面積。frommathimportpiasPI#importtypes

def

CircleArea(r):

ifisinstance(r,int)

orisinstance(r,float):

#確保接收的參數(shù)為數(shù)值

returnPI*r*r

else:

print('Youmustgivemeanintegerorfloatasradius.')

print(CircleArea(3))28.2743338823081385.7案例精選例1:編寫函數(shù)計算圓的面積。frommat565.7案例精選例2:編寫函數(shù),接收任意多個實數(shù),返回一個元組,其中第一個元素為所有參數(shù)的平均值,其他元素為所有參數(shù)中大于平均值的實數(shù)。def

demo2(*para):avg=sum(para)

/len(para)

#注意Python2.x與Python3.x對除法運算符“/”的解釋不同g=

[iforiinparaifi>avg]

return

(avg,)

+tuple(g)

print(demo2(1,

2,

3,

4))(2.5,3,4)元組的+運算5.7案例精選例2:編寫函數(shù),接收任意多個實數(shù),返回一個元575.7案例精選例3:編寫函數(shù),接收字符串參數(shù),返回一個元組,其中第一個元素為大寫字母個數(shù),第二個元素為小寫字母個數(shù)。def

demo3(s):result=

[0,

0]

forchins:

if

'a'

<=ch<=

'z':result[1]

+=

1

elif

'A'

<=ch<=

'Z':result[0]

+=

1

returnresult

print(demo3('aaaabbbbC'))[1,8]ch.islower()ch.isupper()5.7案例精選例3:編寫函數(shù),接收字符串參數(shù),返回一個元組585.7案例精選例4:編寫函數(shù),接收包含20個整數(shù)的列表lst和一個整數(shù)k作為參數(shù),返回新列表。處理規(guī)則為:將列表lst中下標(biāo)k之前的元素逆序,下標(biāo)k之后的元素依序,然后將整個列表lst中的所有元素逆序。def

demo4(lst,k):x=lst[:k]x.reverse()y=lst[k:]y.reverse()r=x+yr.reverse()

returnr

lst=list(range(1,

21))print(lst)print(demo4(lst,

5))[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20][6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,1,2,3,4,5]5.7案例精選例4:編寫函數(shù),接收包含20個整數(shù)的列表ls595.7案例精選例5:編寫函數(shù),接收整數(shù)參數(shù)t,返回斐波那契數(shù)列中大于t的第一個數(shù)。def

demo5(t):a,b=

1,

1

whileb<t:a,b=b,a+b

else:

returnb

print(demo5(50))55fib(n)=fib(n-1)+fib(n-2)a保存fib(n-1)b保存fib(n-2)5.7案例精選例5:編寫函數(shù),接收整數(shù)參數(shù)t,返回斐波那契605.7案例精選例6:編寫函數(shù),接收一個包含若干整數(shù)的列表參數(shù)lst,返回一個元組,其中第一個元素為列表lst中的最小值,其余元素為最小值在列表lst中的下標(biāo)。注意:你的運行結(jié)果可能不一樣!importrandomdef

demo6(lst):m=min(lst)result=

(m,)

forindex,valueinenumerate(lst):

ifvalue==m:result=result+

(index,)

returnresult

x=

[random.randint(1,

20)

foriinrange(50)]print(x)print(demo6(x))minenumerateoperator+random.randintlistcomprehension建議result使用list,而不是tuple!5.7案例精選例6:編寫函數(shù),接收一個包含若干整數(shù)的列表參615.7案例精選例7:編寫函數(shù),接收一個整數(shù)t為參數(shù),打印楊輝三角形前t行。def

demo7(t):

print([1])

print([1,

1])line=

[1,

1]

foriinrange(2,t):r=

[]

forjinrange(0,len(line)

-

1):r.append(line[j]

+line[j+

1])line=

[1]

+r+

[1]

print(line)

demo7(10)下一行相比上一行多了兩個數(shù),最前面和最后為1,中間的各項都是上一行中連續(xù)兩項之和5.7案例精選例7:編寫函數(shù),接收一個整數(shù)t為參數(shù),打印楊625.7案例精選(補充)例7:編寫函數(shù),接收一個整數(shù)t為參數(shù),打印楊輝三角形前t行。def

demo7_(t):line=

[1]i=

-1

foriinrange(t-1):

print(line)

line=

[sum(i)

foriinzip([0]

+line,line+

[0])]

ifi>=0

ort==

1:

print(line)

def

pas_triangles():a=

[1]

while

True:

yieldaa=

[sum(i)

foriinzip([0]

+a,a+

[0])]

def

demo7__(t):

g=pas_triangles()

forninrange(t):

print(next(g))5.7案例精選(補充)例7:編寫函數(shù),接收一個整數(shù)t為參數(shù)635.7案例精選例8:編寫函數(shù),接收一個正偶數(shù)為參數(shù),輸出兩個素數(shù),并且這兩個素數(shù)之和等于原來的正偶數(shù)。如果存在多組符合條件的素數(shù),則全部輸出。importmathdef

IsPrime(n):m=int(math.sqrt(n))

+

1

foriinrange(2,m):

ifn%i==

0:

return

False

return

True

def

demo8(n):

ifisinstance(n,int)

andn>

0

andn%

2

==

0:

foriinrange(3,int(n/

2)

+

1):

ifIsPrime(i)

andIsPrime(n-i):

print(i,

'+',n-i,

'=',n)demo8(60)5.7案例精選例8:編寫函數(shù),接收一個正偶數(shù)為參數(shù),輸出兩645.7案例精選例9:編寫函數(shù),接收兩個正整數(shù)作為參數(shù),返回一個數(shù)組,其中第一個元素為最大公約數(shù),第二個元素為最小公倍數(shù)。def

demo9(m,n):

ifm>n:m,n=n,mp=m*n

whilem!=

0:r=n%mn=mm=r

return

(int(p/n),n)

print(demo9(20,

30))輾轉(zhuǎn)相除法(歐幾里德法):(m,n)(n%m,m)….(0,n)思考題:采用遞歸方式實現(xiàn)最大公約數(shù)5.7案例精選例9:編寫函數(shù),接收兩個正整數(shù)作為參數(shù),返回655.7案例精選例10:編寫函數(shù),接收一個所有元素值互不相等的整數(shù)數(shù)列x,和一個整數(shù)n,要求將值n的元素作為支點,將列表中所有值小于n元素全部放到n前面,所有值大于n的元素放到n后面。importrandomdef

demo10(x,n):

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論