Python核心編程與應用 課件 【ch05】函數_第1頁
Python核心編程與應用 課件 【ch05】函數_第2頁
Python核心編程與應用 課件 【ch05】函數_第3頁
Python核心編程與應用 課件 【ch05】函數_第4頁
Python核心編程與應用 課件 【ch05】函數_第5頁
已閱讀5頁,還剩54頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

Python核心編程與應用函數第五章新工科·數據科學與大數據系列01用戶自定義函數用戶自定義函數01函數的定義deffunctionname(parameters):"函數文檔字符串"function_suitereturn[expression]def:定義函數的關鍵字。functionname:函數名,用戶自定義的名字,命名規(guī)則與變量名相同,本質上是變量。parameters:參數列表,需要傳遞給函數的數據或者條件。函數_文檔字符串:通常說明函數的功能和使用方法。functionsuite:函數功能體,若為空,則只需要寫上pass語句。expression:函數返回值。用戶自定義函數01函數的定義【例5-2】通過time模塊,輸出系統(tǒng)當前的準確時間。importtimedefshow_time():print(time.asctime())show_time()【例5-3】調用系統(tǒng)模塊訪問當前文件夾下的文件清單。importosdefget_file():forf

inos.list

dir('.'):print(f)get_file()

#調用函數用戶自定義函數01函數的調用函數的定義僅僅是聲明了一個函數,真正的執(zhí)行發(fā)生在函數調用時,如show_time()、get_file()。自定義函數完成后,調用函數的方法與Python內建函數的調用完全一樣,使用函數名加括號,如print(),調用時可以有參數也可以沒有參數。書寫時注意必須先定義函數,然后才可以調用該函數。【例5-4】自定義函數實現兩個數相加。#定義函數my_funcdefmy_func():print("thisismycustomfunction")#定義函數adddefadd():numl=int(input('pleaseenteranumber:'))num2=int(input('pleaseenteranumber:'))print('{}+{}={}'.format(num,num2,num1+num2))用戶自定義函數01函數的調用#函數調用add()my_func()運行結果:pleaseenteranumber:18pleaseenteranumber:1918+19=37thisismycustomfunction用戶自定義函數01函數的返回當函數體運行到retumn語句時,就返回到函數調用處,不再執(zhí)行retum后面的代碼。如果函數沒有retumn語,執(zhí)行完函數體最后一條語句后就返回None。【例5-6】顯示今天是工作日或休息日。importdatetimedefget_day_of_week():dow=datetime.date.weekday(datetime.date.today())ifdowinrange(5):return'工作日'else:return'休息日'print(get_day_of_week())02函數實參傳遞函數實參傳遞02形參和實參函數定義時參數列表中的參數叫形式參數,是用于接收外部數據的占位符。函數調用時給定的參數為實參,用于傳遞數據給形參。【例5-7】與某人打招呼。defshow_hello(name):

#name是形參print('hello',name)showhello('xiaoming')

#'xiaoming'是實參運行結果:helloxiaoming函數調用時,把實參'xiaoming'傳遞給形參name。當實參為不同的人名時,就實現了與不同人打招呼。函數實參傳遞02形參和實參【例5-8】求兩數相加。defadd(num1,num2):

#形參num1、num2,只是占位符print('{}+{}={}'.format(numl,num2,num1+num2))add(12,3)

#調用時實參和形參一一對應運行結果:12+3=15注意:形參num1num2只是占位符,函數定義時是沒有值的,當調用函數add(12,3)時才把實參12傳遞給num1實參3傳遞給num2,然后程序的流程就轉入執(zhí)行add()函數,運行完print()函數后返回。調用時,實參和形參從左到右一一對應傳遞值。函數實參傳遞02可變參數與不可變參數(1)不可變參數函數執(zhí)行后不會影響實參的值。【例5-9】通過函數交換數據。defswap(num1,num2):num1,num2=num2,num1print('num1={},num2={}'.format(num1,num2))m,n=12,3swap(m,n)print('num1=[},num2=[}.format(m,n))運行結果:num1=3,num2=12num1=12,num2=3調用函數swap(m,n)時,實參m、n的值為12和3,整數是不可變對象,所以即便函數體內修改了num1和num2的值,函數返回后,num1和num2的值保持不變。函數實參傳遞02可變參數與不可變參數(2)可變參數函數參數如果是可變類型,有可能在函數內部直接影響函數外部的變量[例5-11]在列表中增加元素。defadd(names,name):names.append(name)print(names)names=['xiao','ming']add(names,'ramm')add(names,'derek')print(names)運行結果:['xiao','ming','ramm']['xiao','ming','ramm','derek']['xiao','ming','ramm','derek']因為列表是可變對象,所以在函數體內改變了names列表對象后,函數返回后發(fā)現函數外的names列表對象也改變了。函數實參傳遞02參數傳遞類型(1)必備參數調用函數時,實參的個數和位置均需和形參相對應,既不能多也不能少,所以為必備參數。當需要傳遞多個實參時可以用序列替代,如seg是元組,*seq表示拆分元組,也稱為解包,把元組中的元素作為參數輸入。【例5-12】求兩數相減defsub(num1,num2):print('{}-{}={}.format(num1,num2,numl-num2))sub(12,3)sub(*(3,12))運行結果:12-3-93-12=-9函數調用sub(*(3,12))等價于sub(3,12),*表示拆分序列。函數實參傳遞02參數傳遞類型(2)關鍵字參數當參數比較多時,實參、形參按順序一一對應容易出現位置的差錯,關鍵字參數允許按名稱傳遞對應的參數,即用參數名匹配替代位置匹配,因此使用關鍵字參數允許實參和形參的順序不一致。【例5-13】輸出一串姓名。defget_fullname(firstname,lastname,middlename):print('{}{}{}'.format(firstname,middlename,lastname))get_fullname(firstname='ramm',middlename='derek',lastname='dxy')運行結果:rammderekdxy因為給定了參數名,所以實參順序firstname、middlename、lastmame與形參順序firstname、lastname、middlename可以不一樣。函數實參傳遞02參數傳遞類型(3)默認參數有些參數一般直接使用默認值,特殊情況下才需要傳值,這樣的參數被稱為默認參數。【例5-16】根據單價、數量和折扣計算付款金額,默認不打折。defcount_money(price,count,discount=1.0):

#discount是默認參數print(price*count*discount)count_money(100,10)

#discount使用歌認值10count_money(100,10,0.8)

#discount使用實參值08運行結果:1000.0800.0注意:默認參數必須放在參數列表的最后,如果參數列表中出現了默認值,那么其后的所有參數都必須是默認值。函數實參傳遞02參數傳遞類型(4)可變長參數形參前面加上了*或**,將成為可變長參數。*args:表示形參個數可變,以元組方式接收數據。**kwargs:表示形參個數可變,以字典方式接收數據【例5-17】求序列中所有元素的和。defget_total(*args):

#*args表示參數個數任意print(sum(args))get_total(*(1,2,3,4))

#或者gettotal(1,2,3,4),參數以元組的方式傳遞運行結果:10函數實參傳遞02參數傳遞類型(5)函數參數函數也可以作為參數進行傳遞,實現函數的嵌套調用。【例5-19】函數作為參數。defcalculator(func,numl,num2):

#形參func是函數名func(num1,num2)defadd(num1,num2):print(numl+num2)calculator(add,12,3)

#add是函數,在此作為參數傳遞。注意add后面沒有()運行結果:1503函數不定長參數函數不定長參數03*var_args_tuple參數其基本語法如下:deffunction_name([formal_args,]*var_args_tuple):'函數文檔字符串'function_suitereturn[expression]根據語法格式,*varargstuple參數寫在正常參數的后面。【例5-20】向好朋友逐個打招呼defshow_hello(*names):

#*names表示可接收元組或列表fornameinnames:

#names是可迭代對象print('hello',name)show_hello('xiao','ming','ramm','derek')show_hello(('xiao','ming','ramm','derek'))show_hello(*('xiao','ming','ramm','derek'))函數不定長參數03*var_args_tuple參數運行結果:helloxiaohellominghellorammhelloderekhello('xiao','ming','ramm','derek')helloxiaohellominghellorammhelloDerek程序中寫了三種調用的方法,第一種和第三種調用的結果一樣,都是傳遞了4個參數,即元組前加“*”表示元組解包,成為單個的參數。第二種調用方法showhello(('xiao','ming','ramm','derek'))表示只傳遞了一個參數(元組)給函數。函數不定長參數03*kwargs參數**kwargs參數是另一種不定長參數,用于接收鍵值對,實參需用關鍵字參數。【例5-23】用鍵值對方法顯示個人信息。defgree(**kwargs):

#kwargs是字典對象forkey,valueinkwargs.items():print('[}=[}.format(key,value))gree(name='xiaoming',age=18,gender=False)

#用關鍵字參數作實參運行結果:name=xiaomingage=18gender=False上例是用關鍵字參數作實參,與形參的字典對象匹配。注意:*args和**kwargs參數的書寫順序,在函數中,若同時使用標準參數、*args、**kwargs三種參數,則按如下順序書寫:fnc(arg,*args,**kwargs),即先是必選參數,再是以元組或列表形式的不定長參數,最后是字典形式的不定長參數。Pvthon解釋器以這個順序依次匹配。函數不定長參數03不定長參數舉例【例5-24】顯示商品的類別名稱。northwindjson中的數據來自知名的示例數據庫,是一家貿易公司的供銷存系統(tǒng),其中的商品數據如圖5-2所示。#需要該腳本文件的同級目錄中存在northwindjson文件import

jsondefshow_categories(*cnames):print('所有類別名稱如下:',end='')fornameincnames:print(name,end='

')#測試代碼print('測試')show_categories(飲料類,調味品,水果)運行結果:測試所有類別名稱如下:飲料類調味品水果函數不定長參數03不定長參數舉例當要讀取真實數據時,將測試代碼修改為以下真實數據代碼。#獲取真實數據時withopen('northwind.json',r')

as

f:data=json.loads(f.read())categories=tuple({p['類別]

forp

indata})show_categories(*categories)運行結果:所有類別名稱如下,奶制品果醬水果和蔬菜罐頭飲料點心谷類土豆片/快餐湯焙烤食品果和堅果意大利面食調味品谷類/麥片肉罐頭說明:ip['類別']forpidata)是集合推導式,即獲取所有商品的類別。04函數調用和嵌套函數調用和嵌套04函數的返回值函數通過retum語返回結果。代碼執(zhí)行時遇到retum語,將終止函數內部代碼的執(zhí)行,退出并返回數據到函數調用處,若return后沒有返回值,則默認返回None。【例5-26】利用函數求加法運算defadd(numl,num2):returnnum1+num2print('1+2+3={}'.format(add(add(1,2),3)))運行結果:1+2+3=6函數add(1,2)的返回值再次作為參數調用add()函數,實現函數的重復調用。函數調用和嵌套04多次調用函數,實現代碼復用以圖書管理為例,常用的功能模塊有查找圖書和新增圖書,對應的功能拆解為:①根據標題查找圖書getby_title(title);②新增圖書addbook(titleauthor,price);③批量新增圖書addbooks(*books)。根據需求,規(guī)定新增圖書前,需要根據標題查找該圖書,如果不存在,那么新增該圖書;當批量新增圖書時,可以重復調用新增一本圖書的函數。【例5-28】查找和新增圖書。①初始化圖書集合books=[dict(title='紅樓夢',author='曹雪芹',price=10),dict(title='西游記',author='吳承恩',price=20),dict(title='水滸傳',author='施耐',price=30),dict(title='三國演義',author='羅貫中',price=40)]函數調用和嵌套04多次調用函數,實現代碼復用②根據標題查找圖書,若找到,則返回圖書信息,否則返回Nonedefget_by_title(title):forbinbooks:ifb['title']==title:returnbprint(get_by_title('三國演義'))print(get_by_title('三國志'))

#沒找到,返回None運行結果:{'title':'三國演義','author':'羅貫中','price':40}None函數調用和嵌套04多次調用函數,實現代碼復用③新增圖書。新增前先判斷圖書是否存在,不存在則增加。defadd_book(t,a,p):ifnotget_by_title(t):books.append(dict(title=t,author=a,price=p))add_book('python','guido',40)

#新增圖書print(get_by_title('python'))運行結果:['title':'python','author':'guido','price':40)函數調用和嵌套04多次調用函數,實現代碼復用④批量新增圖書時,只需重復調用新增單一圖書的方法defadd_books(bs):forb

inbs:add_book(b['title'],b['author'],b['price'])add_books([{'title':'白雪公主','author':'安徒生','price':10}{'title':'灰姑娘','author':'安徒生','price':20}{'title':'海的女兒','author':'格林','price':30}])print(books)程序運行后,將三本新書白雪公主、灰姑娘、海的女兒都加入了books列表。函數調用和嵌套04函數嵌套聲明Python除了在函數中調用其他函數,即嵌套調用外,還允許在函數中再定義函數,即嵌套定義。【例5-29】函數套聲明。defouter_func():print('thisisfromouterfunction')definnerfunc():print('thisisfrominnerfunction')inner_func()outer_func()運行結果:thisisfromouterfunctionthisisfrominnerfunction注意:函數可以嵌套定義,但不能交叉定義,即不能在外部函數和內部函數之間相互調用否則會引發(fā)死循環(huán)。05變量的作用域變量的作用域05變量的作用域變量作用域指的是變量的有效范圍或者變量能被訪問的范圍。變量只能在有效的作用范圍內被訪問。變量創(chuàng)建后,其作用域就確定了。【例5-33】函數內創(chuàng)建的變量只能被函數內的代碼訪問。deffunc():name='xiaoming'print(name)運行結果:NameError:name'name'isnotdefined系統(tǒng)報錯,因為變量name只能在函數func()內部訪問。變量的作用域05變量作用域法則(1)變量賦值Python中所有變量都是在第一次賦值時創(chuàng)建,作用域也隨之確定。變量只有賦值后才能被應用。(2)函數內的所有變量的作用域僅限該函數內具體含義包括:①函數內定義的變量,只能被函數內的代碼使用,不能在函數外部引用這些變量。②函數內定義的變量與函數外的變量同名,代表兩個不同的變量,遵循本地優(yōu)先原則。③函數內的代碼可以引用函數外的變量,前提是函數內沒有對該變量賦過值。④函數內的變量作用域,只有在函數內代碼執(zhí)行時才能訪問。變量的作用域05變量作用域法則(3)函數定義的本地作用域和程序模塊定義的全局作用域的關系①每個模塊(即一個Pvthon文件)都有一個全局作用域。②全局作用域的作用范圍僅限單個文件。③每次對函數調用都創(chuàng)建一個新的本地作用域。④被賦值的變量除非聲明為全局或者非本地變量,否則都是本地變量。(4)Python變量名搜索和解析Python查找一個變量,遵循LEGB原則:本地作用域L(Local)上一層結構中的本地作用域E(Enclosing)全局作用域G(Global)內置作用域B(Built-in)。Python以L一E-GB的規(guī)則查找變量,即:在局部找不到,會去局部外的局部找,再找不到,會去全局找,最后去內置中找,如果還找不到,就提示變量不存在錯誤,如圖5-3所示。變量的作用域05變量作用域法則變量的作用域05全局變量全局變量位于模塊文件頂層,其作用域為全文件,若想在函數內部修改這個全局變量的值,方法是用關鍵字global在函數內部聲明變量為全局變量。定義全局變量的語法格式如下global變量名1,變量名2,···【例5-39】全局變量使用舉例。下面4段代碼顯示了全局變量的使用方法,注意它們的區(qū)別代碼1:x=99

#此X為全局變量deffunc():X=100

#此X為局部變量print(x)

#運行結果:99func()print(x)

#運行結果:99變量的作用域05nonlocal語句nonlocal的含義是非本地,即所聲明的變量不在本地查找,去上一層函數體中查找。所以,nonlocal使用在嵌套函數中,不能用在頂層函數中,且聲明的變量必須已經創(chuàng)建。【例5-40】nonlocal使用舉例下面四段代碼顯示了nonlocal變量的使用方法,注意它們的區(qū)別代碼一:deffunc1():x=100deffunc2():x=200print(x)#運行結果:100func2()print(x)#運行結果:100func1()注意:func1中的x和func2中的x各自獨立,在各自的命名空間中,是兩個不同的變量。變量的作用域05nonlocal語句nonlocal語句小結:①nonlocal語句必須使用在嵌套函數中,聲明變量為非本地變量。②用nonlocal說明的變量需要去上一層函數中查找此變量。③用nonlocal說明的變量必須在上一層函數中已經定義過,即賦過值。④通常只有在子函數中想修改上一層函數的變量時,才使用nonlocal說明該變量。⑤使用nonlocal理論上可以加快變量的搜索速度。06偏函數和高階函數偏函數和高階函數06改造標準函數為自定義函數int()函數可以把字符串轉換為整數,當僅輸入字符串時,int()函數默認按十進制轉換,如int(12345=12345,將字符串12345轉為十進制數值12345。int()函數還有一個base參數,默認值為10。如果傳入base參數,那么可以進行N進制轉十進制的運算。如int(10101base-2)表示將二進制字符串10101轉換為十進制數,結果為21。同理,int(123458)把八進制轉十進制,結果為5349。假設需要重復轉換二進制字符串,每次調用int(x,base=2)時,必須傳入參數based=2,非常麻煩,這時可以定義一個int2()函數,默認傳入參數base=2。【例5-42】設置默認值參數。def

int2(x,base=2):

#設置默認值參數returnint(x,base)print(int2('10010'))

#函數調用運行結果:18偏函數和高階函數06偏函數Python的functools模塊提供了很多有用的函數工具其中包括偏函數functools.partial創(chuàng)建的偏函數imnt20)比自定義的函數imt2)更加方便。【例5-43】創(chuàng)建偏函數。import

functoolsint2=functools.partial(int,base=2)

#創(chuàng)建一個偏函數int2print(int2('10000000'),int2('1010101'))運行結果:12885所以,functoolspartial的作用是通過設置默認參數的方法把一個函數的某些參數固定,然后返回一個新的函數,調用這個新函數使應用更簡單。在創(chuàng)建偏函數時,實際上可以接收更多的默認參數,使用*args和**kw接收不定長的參數。偏函數和高階函數06高階函數高階函數是把函數作為參數傳入,或者將函數作為返回值的一種函數表達方式。Python中,函數本身就是一個可變數據類型,指向一個對象,所以函數名就是變量名。變量可以指向函數,還可以把函數作為實參傳遞給形參。(1)指向函數的變量指向函數的變量表示函數本身賦值給變量,變量即指向了該函數。(2)函數名作為變量使用(3)函數名作為實參傳遞把函數名作為實參傳遞給形參,也稱傳入函數。(4)map()函數map()函數是映射函數,可接收兩個參數:函數和可選代對象(iterable)。map()函數將傳入的函數依次作用到可迭代對象的每個元素,把結果作為新的可迭代對象返回。偏函數和高階函數06高階函數(5)reduce()函數reduce()函數的作用是把一個函數(假設為累加)作用在一個序列[x1,x2,x3]上,執(zhí)行時,先從x1、x2兩個參數開始,得到累加結果,然后繼續(xù)與x3元素累加,依次類推,直至全部元素累加完。寫成數學格式就是:reduce(f,[x1,x2,x3,x4])=f(f(f(x1,x2),x3),x4)(6)filter()函數filter()函數是過濾函數把傳入的函數依次作用于每個元素,根據返回值是True還是False來決定保留還是丟棄該元素。與map0)函數不同,filter()函數不僅把函數映射到每一個元素,還決定元素的去留,返回的結果也只是元素本身。(7)sorted()函數sorted()函數可以對list列表排序,默認升序,也可以使用參數reverse改為降序。07匿名函數匿名函數07所謂匿名,就是沒有名字,匿名函數就是定義一個沒有函數名的函數。Python用lambda表達式創(chuàng)建匿名函數,語法格式如下:lambda

參數1,參數2,···:表達式lambda表達式的含義:對給定的若參數用后面的表達式進行計算并返回值。lambda表達式創(chuàng)建的匿名函數只能包含一條語句,沒有retum語,函數返回值就是表達式的值。lambda表達式由三部分組成:①關鍵字lambda;②參數,多個參數之間用“,”分隔;③表達式,參數與表達式之間用“:”分隔。匿名函數07lambda的參數類型lambda表達式的參數相當于函數的形參,寫函數時可以沒有形參,也可以有很多不同形式的形參。lambda

參數1,參數2,···:表達式lambda表達式中參數的形式(假設有a、b兩個以及其他參數)如下。a,b:必備參數。a=1,b=2:默認值參數。*args:元組形式的不定長參數**kwargs:字典形式的不定長參數。a,b=1*args:多種類型混合使用的參數空:無參數。匿名函數07lambda的表達式類型lambda參數1,參數2,·.·:表達式該表達式是lambda的返回值,前面默認省略了一個關鍵字return。表達式類型如下:①1,字面值常量;②None,空值;③a+b,運算表達式;④sum(a),返回函數值;⑤1if

a>10

else

0,返回邏輯判斷的結果。【例5-63】表達式類型為字面值常量。func=Lambda:'Helloxiaoming'print(func())運行結果:Helloxiaoming08遞歸函數遞歸08遞歸與循環(huán)有一定的相似之處,循環(huán)是在滿足條件時重復執(zhí)行代碼塊,而遞歸是滿足條件時重復執(zhí)行自身。所以遞歸是自我調用,常常用在函數中構成遞歸函數,遞歸函數就是直接或間接地調用自身的函數。函數遞歸時,為了避免無限地調用自身而陷入死機,必須有一個遞歸結束條件。Python在處理遞歸調用時要用到一個特殊的數據結構:棧棧是函數或程序運行時系統(tǒng)為其分配的一段內存區(qū)域,具有后進先出的特性。棧的空間大小受系統(tǒng)內存空間大小的限制,因為函數遞歸調用意味著每調用自身一次,就在內存復制一份該函數,所以Python有一個可用的遞歸深度的限制,以避免耗盡計算機中的內存,默認深度是1000。遞歸08【例5-76】計算斐波那契數列斐波那契數列又稱為黃金分割數列,指的是這樣一個數列:1、1、2、3、5、8、13、21···,它的遞歸定義如下求解fb(n)的值需要求解fib(n-1)fib(n-2)而要求解fib(n-1)需要求解fib(n-2)fib(n-3);同理,求解fib(n-2)需要求解fib(n-3)fib(n-4),依次遞推,直至求fib(2)=fib(1)+fib(0),而fib(1)-1,fib(0)-1是已知的,再從fib(1)fib(0)回推得到fib(2),根據fib(2)fib(1)回推得到fib(3),一路回推得到fib(4)、fib(5),直至fib(n)。這就是求斐波那契數列的遞歸思想。遞歸08程序如下:deffoo(n):ifn==1or

n==0:

#遞歸出口return1returnfoo(n-1)+foo(n-2)

#遞歸print(foo(30))運行結果:1346269遞歸的優(yōu)點:遞歸使代碼看起來更加整潔、優(yōu)雅,可以將復雜任務分解成更簡單的子問題。遞歸的缺點:遞歸的邏輯很難調試、遞歸算法解題的運行效率較低。在遞歸調用的過程中系統(tǒng)開辟了棧來存儲每層的返回點、

溫馨提示

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

評論

0/150

提交評論