摘要:局部變量只能在其被聲明的函數內部訪問,而全局變量可以在整個程序范圍內訪問。調用函數時,所有在函數內聲明的變量名稱都將被加入到作用域中。
函數
(一)定義函數
你可以定義一個由自己想要功能的函數,以下是簡單的規則:
(1)函數代碼塊以?def?關鍵詞開頭,后接函數標識符名稱和圓括號()。
(2)任何傳入參數和自變量必須放在圓括號中間。圓括號之間可以用于定義參數。
(3)函數的第一行語句可以選擇性地使用文檔字符串—用于存放函數說明。
(4)函數內容以冒號起始,并且縮進。
(5)return結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當于返回 None。
語法: def functionname( parameters ): "函數_文檔字符串" function_suite return [expression]
默認情況下,參數值和參數名稱是按函數聲明中定義的的順序匹配起來的。
練習1:沒有返回return的函數,返回none
>>> def sum(a,b): ... print a+b >>> print sum(5,4)
練習2:返回列表及元組
>>> def bar(): ... return "abc",[42,"python"],"guido" >>> def foo(): ... return ["hello",1000,-98.6]
注:bar()函數返回一個元組,foo()函數返回一個列表,由于元組語法上不一定帶上圓括號,所以讓人覺得返回了多個值。所以可以適當加上括號。
從返回值的角度看可以通過以下三種方式進行數據的存儲:
(在對x,y,z 和a,b,c的賦值中每個變量會接收對應的返回值,而tuple1會隱式地返回整個元組)
>>>tuple1=bar() >>> x,y,z=bar() >>> (a,b,c)=bar()
(二)調用函數
定義一個函數只給了函數一個名稱,指定了函數里包含的參數,和代碼塊結構。這個函數的基本結構完成以后,你可以通過另一個函數調用執行,也可以直接從Python提示符執行。
>>> def printme(str): ... print str; ... Return >>> printme("調用自定義的函數")
練習3:求列表中第二大的數
方法一:
>>> a=[10,50,-1,3,2,10] >>> def secNum(lista): ... lista.sort() ... return lista[-2] ... >>> print secNum(a) 10
方法二:
>>> def secNum(lista): ... max_number=max(lista) ... lista.remove(max_number) ... return max(lista)
方法三:
算法:
1 比較列表中前2個數,大的作為為列表中暫時的最大數,小的
作為次大數,分別存在2個變量里
2 遍歷列表從第三個數開始以后后的值,去和最大值去比較,存在2種可能
3 如果大于,當前值作為列表中暫時的最大數,以前最大的變為
次大的。
4 如果小于,和次大的比較,大于它就是次大值,小于繼續遍歷
后續值。
#coding=utf-8 a=[10,10,10,0,10,10,0] def?secondBiggestNumber(lista):
???? #判斷是否是列表或元組
???? if?not?isinstance(lista,(list,tuple)):
???????? return?None
??? ?#判斷是否有2個以上元素
??? ?if?len(lista)<=1:
???????? return?None
???? #判斷每個元素的的值是否為數字
???? for?i?in?lista:
???????? if?isinstance(i,(int,float)):
???????????? continue
???????? else:
???????????? return?None
???? #比較列表中前2個數,大的作為為列表中暫時的最大數,小的
???? #作為次大數,分別存在2個變量里
???? if?lista[0]>lista[1]:
???????? biggest_number=lista[0]
???????? second_biggest_number=lista[1]
???? else:
???????? biggest_number=lista[1]
???????? second_biggest_number=lista[0]
???? #遍歷列表從第三個數開始以后后的值,去和最大值去比較
???? for?i?in?lista[2:]:
??????? #如果大于,當前值作為列表中暫時的最大數,以前最大的變為
?????? ?#次大的。
??????? if?i?>?biggest_number:
??????????? second_biggest_number=biggest_number
??????????? biggest_number=i
?????? #如果小于,和次大的比較,大于它就是次大值,小于繼續遍歷
????? ?#后續值。
??????? elif?i?==?biggest_number:
??????????? continue
?????? ?else:
??????????? if?biggest_number==second_biggest_number:
??????????????? second_biggest_number=i
?????????? ?if?i?>second_biggest_number:
??????????????? second_biggest_number=i
???? return?second_biggest_number
print?secondBiggestNumber(a)
練習4:計算10000次浮點數運算的耗時
import time import random >>> def compute_float_time_consume(): ... start_time=time.time() ... for i in range(10000): ... random.random()**2 ... end_time=time.time() ... return end_time-start_time
(三)參數傳遞
在Python中,類型屬于對象,變量是沒有類型的:
a=[1,2,3] a="Runoob"
以上代碼中,[1,2,3]?是 List 類型,"Runoob"?是 String 類型,而變量 a 是沒有類型,她僅僅是一個對象的引用(一個指針),可以是 List 類型對象,也可以指向 String 類型對象。
(1)可更改(mutable)與不可更改(immutable)對象
在 python 中,strings, tuples, 和 numbers 是不可更改的對象,而 list,dict 等則是可以修改的對象。
不可變類型:變量賦值?a=5?后再賦值?a=10,這里實際是新生成一個 int 值對象 10,再讓 a 指向它,而5被丟棄,不是改變a的值,相當于新生成了a。
可變類型:變量賦值?la=[1,2,3,4]?后再賦值?la[2]=5?則是將 list la 的第三個元素值更改,本身la沒有動,只是其內部的一部分值被修改了。
(2)python 函數的參數傳遞:
不可變類型:類似 c++ 的值傳遞,如 整數、字符串、元組。如fun(a),傳遞的只是a的值,沒有影響a對象本身。比如在 fun(a)內部修改 a 的值,只是修改另一個復制的對象,不會影響a本身。
可變類型:類似 c++ 的引用傳遞,如列表,字典。如 fun(a),則是將 a 真正的傳過去,修改后fun外部的a也會受影響
python 中一切都是對象,嚴格意義我們不能說值傳遞還是引用傳遞,我們應該說傳不可變對象和傳可變對象。
練習3:傳不可變對象
>>> def ChangeInt(a): ... a=10 >>> b=2 >>> ChangeInt(b) >>> print b #結果是2
練習4:傳可變對象
>>> def changeme(mylist): ... mylist.append([1,2,3,4]) ... print mylist ... return >>> mylist=[10,20,30] >>> changeme(mylist) #[10, 20, 30, [1, 2, 3, 4]] >>> print mylist #[10, 20, 30, [1, 2, 3, 4]]
注:實例中傳入函數的和在末尾添加新內容的對象用的是同一個引用
(2)參數類型
python中函數傳遞參數有四種形式:
fun1(a,b,c)
fun1(a,b,c)是直接將實參賦予行參,根據位置做匹配,即嚴格要求實參的數量與行參的數量位置相等,比較一般,大多數語言常用這種方式。
>>> def a(x,y):print x,y >>> a(4,5) #4 5
fun2(a=1,b=2,c=3)
fun2(a=1,b=2,c=3)根據鍵值對的形式做實參與行參的匹配,通過這種式就可以忽略了參數的位置關系,直接根據關鍵字來進行賦值,同時該種傳參方式還有個好處就是可以在調用函數的時候作為個別選填項,不要求數量上的相等,即可以fun5(3,4)來調用fun2函數,這里關鍵就是前面的3,4覆蓋了原來a、b兩個行參的值,但c還是不變采用原來的默認值3,這種模式相較第一種更加靈活,不僅可以通過fun6(c=5,a=2,b=7)來打亂行參的位置,而且可以在但沒有對應行參傳遞的時候常用定義函數時的默認值。
>>> def a(x,y=3):print x,y >>> a(4) #4 3
注:Python傳可變對象-傳默認參數會記住值-這是坑須知道
#coding=utf-8 def add_end(L=[]): #或者L=[1, 2, 3] L.append("END") return L print add_end([1, 2, 3]) print add_end(["x", "y", "z"]) print add_end() print add_end() print add_end()
只有在默認參數時候,L才會記住每次append的值
如果你每次都傳入值,L就會每次顯示你傳入的數據而不會記住你上一次傳入的值
改成如下:
def add_end(L=None): if L is None: L=[] L.append("END") return L
解析:
Python傳默認參數需注意:
默認參數是[],但是函數似乎每次都”記住了”上次添加了’END’后的list;
Python函數在定義的時候,默認參數的值就被計算出來了即[];
因為默認參數L也是一個變量,它指向對象[],每次調用該函數,如果改變了L的內容,則下次調用時,默認參數的內容就變了,不在是函數定義時的[]了;
定義默認參數必須牢記一點:默認參數必須指向不變對象!
所以:函數的默認參數最好別用可變對象,否則存在累加操作結果
的情況
fun3(*args)--元組參數
fun3(*args),這傳參方式是可以傳入任意個參數,這些若干參數都被放到了tuple元組中賦值給行參args,之后要在函數中使用這些行參,直接操作args這個tuple元組就可以了,這樣的好處是在參數的數量上沒有了限制,但是因為是tuple,其本身還是有次序的,這就仍然存在一定的束縛,在對參數操作上也會有一些不便。
>>> def a(*x):print x >>> a(1,2,3) (1, 2, 3) >>> a(x=1,y=2,z=3) Traceback (most recent call last): File "", line 1, in TypeError: a() got an unexpected keyword argument "x"
注:不管有多少個,在函數內部都被存放在以形參名為標識符的元組中。
練習5:累計乘法
>>>?def?mul(*arg): ...?????result=1 ...?????for?i?in?arg: ...?????????if?not?isinstance(i,(int,float,long)): ...?????????????return?None ...?????????else: ...?????????????result*=i ...?????return?result ... >>>?mul(1,2,3,4) 24
fun4(**kargs)--參數是字典
fun4(*kargs)最為靈活,形參名前加兩個表示,參數在函數內部將被存放在以形式名為標識符的dictionary中,這時調用函數的方法則需要采用arg1=value1,arg2=value2這樣的形式。
>>> def a(**x):print x >>> a(x=1,y=2,z=3) {"y": 2, "x": 1, "z": 3} >>> a(1,2,3) Traceback (most recent call last): File "", line 1, in TypeError: a() takes exactly 0 arguments (3 given)
綜合練習3:mul(1,2,3,4,5,a=6,b=7)實現連乘函數,需要用到arg,*kw,且函數有固定2個參數:a,b
def mul(a, b, *arg, **kw): result=1 if not isinstance(a, (int, float, long)) and not isinstance(b, (int, float, long)): return None else: result=a*b for i in arg: if not isinstance(i, (int, float, long)): return None else: result *= i for j in kw.values(): if not isinstance(j, (int, float, long)): return None else: result *= j return result
調用函數的方式:
(1)mul(10,20,20,34,c=40,d=50)
(2)mul(10,20,(20,34),*{"c":40,"d":50})
(3)mul(10,20,30,40,f=20,(20,34),*{"c":40,"d":50})
等價于 tup=(20,34) dic={"c":40,"d":50}
mul(10,20,30,40,f=40,tup,*dic)
注意我們的元組和字典參數僅僅是被調函數中最終接收的元組和字典的子集
(四)匿名函數
python使用lambda來創建匿名函數。
(1)lambda只是一個表達式,函數體比def簡單很多。
(2)lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
(3)lambda函數擁有自己的命名空間,且不能訪問自有參數列表之外或全局命名空間里的參數。
(4)雖然lambda函數看起來只能寫一行,卻不等同于C或C++的內聯函數,后者的目的是調用函數時不占用棧內存從而增加運行效率。
(5)lambda函數返回一個函數對象,如果沒有變量接受這個返回值,它很快就被丟棄,也正是由于lambda是一個表達式,所以它可以直接作為List,dict的成員
def與lambda區別:
注:在def中,用return可以返回的可以放在lambda后面,不能用return返回的不能定義在lambda后.因此,像if或for或print這種語句就不能用于lambda中,lambda一般只用來定義簡單的函數。
語法:
lambda函數的語法只包含一個語句:
lambda[arga,arg2……]:expression
幾個規則:
1.一般也就一行表達式,必須有返回值
不能有return?
可以沒有參數,可以有一個或多個參數
練習6:x的y次方
>>> sum=lambda x,y:x**y >>> print sum(10,20)
練習7:
def make_repeater(n): return lambda s: s*n twice = make_repeater(2) #等價lambda s: s*2 print twice("word") ##等價lambda s: "word"*2 print twice(5) ###等價lambda s: 5*2
(五)全局變量和局部變量
定義在函數內部的變量擁有一個局部作用域,定義在函數外的擁有全局作用域。
局部變量只能在其被聲明的函數內部訪問,而全局變量可以在整個程序范圍內訪問。調用函數時,所有在函數內聲明的變量名稱都將被加入到作用域中。
>>> total=0 >>> def sum(a,b): ... total=a+b ... print total ... return total >>> sum(10,20) #結果 30 30 >>> print total #結果 0 >>> total=0 >>> def sum(a,b): ... global total ... total=a+b ... print total ... return total >>> sum(10,20) #結果 30 30 >>> print total #結果 30
總結:
1 函數中使用全局變量,聲明為global
2 否則當局部變量使用,且局部變量都要在函數開始的地方做賦值
3 如果函數中的變量沒有聲明為global,且在外部有同名的變量
則可以直接使用,如果進行了賦值操作,則此變量變為局部變量
且在使用前必須初始化賦值。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/40914.html
摘要:為我們提供了許多內置函數,例如并提供了創建用戶定義函數的能力。會將該變量視為函數級作用域中的局部變量。回到目錄中函數的用途是什么是中的內置函數之一。請注意,這種類型的參數語法不允許將命名參數傳遞給函數。函數接受一個稱為的可選參數。 ...
摘要:回到目錄評論區抽粉絲送書啦歡迎大家在評論區提出意見和建議抽兩位幸運兒送書,實物圖如下開發從入門到精通內容簡介案例教學。 ? 作者主頁:海擁 ? 作者簡介:?CSDN...
摘要:調用以回調函數地址為參數的函數這個主題就稍微繞一些了,也就是說在接口中,需要傳入回調函數作為參數。這個問題在中也可以解決,并且回調函數可以用定義。代碼代碼很簡單回調函數的傳入參數為,返回參數也是。 項目中要對一個用 C 編寫的 .so 庫進行邏輯自測。這項工作,考慮到靈活性,我首先考慮用 Python 來完成。 研究了一些資料,采用 python 的 ctypes 來完成這項工作。已經...
摘要:主要是庫文件頭文件文件不一致的問題。定義模塊函數其中函數參數是模塊自身,是傳遞的參數列表,返回值定義了一個整形數,這里會申請空間增加引用計數,交由來管理這個引用。 C++開發python windows版本的擴展模塊示例測試環境介紹和準備測試環境:操作系統:windows10Python版本:3.7.0VS版本:vs2015社區版(免費)相關工具下載:VS版本vs2015社區版(免費)...
摘要:主要是庫文件頭文件文件不一致的問題。定義模塊函數其中函數參數是模塊自身,是傳遞的參數列表,返回值定義了一個整形數,這里會申請空間增加引用計數,交由來管理這個引用。 C++開發python windows版本的擴展模塊示例測試環境介紹和準備測試環境:操作系統:windows10Python版本:3.7.0VS版本:vs2015社區版(免費)相關工具下載:VS版本vs2015社區版(免費)...
摘要:官方也宣布在停止對的維護。并且在很多面試過程中,面試官都會問與的區別。的版本,常被稱為,或簡稱。與部分地支持這種形式的語法。捕獲異常的語法由改為。在中,表示八進制字面量的方式只有一種,就是。已經支援新的模組。 前言 如果你是剛接觸 Python 的初學者,那你可能是直接學習 Python 3.x 版本。對于 Python 2.x 的版本是不會有所接觸。官方也宣布在 2020 停止對 P...
閱讀 3638·2021-11-25 09:43
閱讀 636·2021-09-22 15:59
閱讀 1742·2021-09-06 15:00
閱讀 1769·2021-09-02 09:54
閱讀 689·2019-08-30 15:56
閱讀 1175·2019-08-29 17:14
閱讀 1838·2019-08-29 13:15
閱讀 879·2019-08-28 18:28