python的函數(shù)參數(shù)傳遞是"引用傳遞(地址傳遞)"。
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:域名申請、虛擬主機、營銷軟件、網(wǎng)站建設(shè)、新密網(wǎng)站維護、網(wǎng)站推廣。
python中賦值語句的過程(x = 1):先申請一段內(nèi)存分配給一個整型對象來存儲數(shù)據(jù)1,然后讓變量x去指向這個對象,實際上就是指向這段內(nèi)存(這里有點和C語言中的指針類似)。
在Python中,會為每個層次生成一個符號表,里層能調(diào)用外層中的變量,而外層不能調(diào)用里層中的變量,并且當外層和里層有同名變量時,外層變量會被里層變量屏蔽掉。函數(shù)? 調(diào)用 ?會為函數(shù)局部變量生成一個新的符號表。
局部變量:作用于該函數(shù)內(nèi)部,一旦函數(shù)執(zhí)行完成,該變量就被回收。
全局變量:它是在函數(shù)外部定義的,作用域是整個文件。全局變量可以直接在函數(shù)里面應用,但是如果要在函數(shù)內(nèi)部改變?nèi)肿兞浚仨毷褂胓lobal關(guān)鍵字進行聲明。
注意 :默認值在函數(shù)? 定義 ?作用域被解析
在定義函數(shù)時,就已經(jīng)執(zhí)行力它的局部變量
python中不可變類型是共享內(nèi)存地址的:把相同的兩個不可變類型數(shù)據(jù)賦給兩個不同變量a,b,a,b在內(nèi)存中的地址是一樣的。
這里來給大家演示一下,函數(shù)的定義或構(gòu)造,并調(diào)用函數(shù)來實現(xiàn)封裝后的效果。
首先我們來看看想實現(xiàn)下面的這個效果,如果不使用函數(shù)應該怎么實現(xiàn)。
以上兩種返回結(jié)果都是1-9這幾個數(shù)字。
以上兩種方法,第一種代碼重復率太高,代碼美觀效果太差,雖然能實現(xiàn)效果,但是因為數(shù)量比較少,還能手工打出來這幾行代碼,如果是打印1-100000就很難實現(xiàn)了。這時候for循環(huán)還是可以實現(xiàn)的,但是for循環(huán)只能實現(xiàn)類似的數(shù)字和變量循環(huán),無法進行復雜的功能開發(fā)。鑒于此,函數(shù)這個概念就被python引入了,下面先來看看函數(shù)是怎么實現(xiàn)上面的效果的,還是兩種方法。
這時候如果想實現(xiàn)上面的打印結(jié)果就直接使用函數(shù)名+小括號調(diào)用函數(shù)就可以了,這種類型的語法,不僅可以反復使用,而且封裝后的代碼更美觀。
剛學用Python的時候,特別是看一些庫的源碼時,經(jīng)常會看到func(*args, **kwargs)這樣的函數(shù)定義,這個*和**讓人有點費解。其實只要把函數(shù)參數(shù)定義搞清楚了,就不難理解了。
先說說函數(shù)定義,我們都知道,下面的代碼定義了一個函數(shù)funcA
def funcA():
pass
顯然,函數(shù)funcA沒有參數(shù)(同時啥也不干:D)。
下面這個函數(shù)funcB就有兩個參數(shù)了,
def funcB(a, b):
print a
print b
調(diào)用的時候,我們需要使用函數(shù)名,加上圓括號擴起來的參數(shù)列表,比如 funcB(100, 99),執(zhí)行結(jié)果是:
100
99
很明顯,參數(shù)的順序和個數(shù)要和函數(shù)定義中一致,如果執(zhí)行funcB(100),Python會報錯的:
TypeError: funcB() takes exactly 2 arguments (1 given)
我們可以在函數(shù)定義中使用參數(shù)默認值,比如
def funcC(a, b=0):
print a
print b
在函數(shù)funcC的定義中,參數(shù)b有默認值,是一個可選參數(shù),如果我們調(diào)用funcC(100),b會自動賦值為0。
OK,目前為止,我們要定義一個函數(shù)的時候,必須要預先定義這個函數(shù)需要多少個參數(shù)(或者說可以接受多少個參數(shù))。一般情況下這是沒問題的,但是也有在定義函數(shù)的時候,不能知道參數(shù)個數(shù)的情況(想一想C語言里的printf函數(shù)),在Python里,帶*的參數(shù)就是用來接受可變數(shù)量參數(shù)的。看一個例子
def funcD(a, b, *c):
print a
print b
print "length of c is: %d " % len(c)
print c
調(diào)用funcD(1, 2, 3, 4, 5, 6)結(jié)果是
1
2
length of c is: 4
(3, 4, 5, 6)
我們看到,前面兩個參數(shù)被a、b接受了,剩下的4個參數(shù),全部被c接受了,c在這里是一個tuple。我們在調(diào)用funcD的時候,至少要傳遞2個參數(shù),2個以上的參數(shù),都放到c里了,如果只有兩個參數(shù),那么c就是一個empty tuple。
好了,一顆星我們弄清楚了,下面輪到兩顆星。
上面的例子里,調(diào)用函數(shù)的時候,傳遞的參數(shù)都是根據(jù)位置來跟函數(shù)定義里的參數(shù)表匹配的,比如funcB(100, 99)和funcB(99, 100)的執(zhí)行結(jié)果是不一樣的。在Python里,還支持一種用關(guān)鍵字參數(shù)(keyword argument)調(diào)用函數(shù)的辦法,也就是在調(diào)用函數(shù)的時候,明確指定參數(shù)值付給那個形參。比如還是上面的funcB(a, b),我們通過這兩種方式調(diào)用
funcB(a=100, b=99)
和
funcB(b=99, a=100)
結(jié)果跟funcB(100, 99)都是一樣的,因為我們在使用關(guān)鍵字參數(shù)調(diào)用的時候,指定了把100賦值給a,99賦值給b。也就是說,關(guān)鍵字參數(shù)可以讓我們在調(diào)用函數(shù)的時候打亂參數(shù)傳遞的順序!
另外,在函數(shù)調(diào)用中,可以混合使用基于位置匹配的參數(shù)和關(guān)鍵字參數(shù),前題是先給出固定位置的參數(shù),比如
def funcE(a, b, c):
print a
print b
print c
調(diào)用funcE(100, 99, 98)和調(diào)用funcE(100, c=98, b=99)的結(jié)果是一樣的。
好了,經(jīng)過以上鋪墊,兩顆星總算可以出場了:
如果一個函數(shù)定義中的最后一個形參有 ** (雙星號)前綴,所有正常形參之外的其他的關(guān)鍵字參數(shù)都將被放置在一個字典中傳遞給函數(shù),比如:
def funcF(a, **b):
print a
for x in b:
print x + ": " + str(b[x])
調(diào)用funcF(100, c='你好', b=200),執(zhí)行結(jié)果
100
c: 你好
b: 200
大家可以看到,b是一個dict對象實例,它接受了關(guān)鍵字參數(shù)b和c。
函數(shù)是組織好,可重復使用的,用來實現(xiàn)相關(guān)功能的代碼段
函數(shù)提高了代碼的重復利用率和應用的模塊性。
除Python自帶的函數(shù)之外,也可以自己創(chuàng)建函數(shù),叫做自定義函數(shù)
語法:
函數(shù)代碼塊以 def 開頭
參數(shù)為 輸入值 ,放于函數(shù)名后口號里面,
函數(shù)內(nèi)容以冒號:開始,函數(shù)體縮進, return 返回 輸出值
函數(shù)調(diào)用使用關(guān)鍵字參數(shù)來確定傳入的參數(shù)值,此時,如果多個函數(shù)則不需要按照指定順序。
在定義函數(shù)時,指定參數(shù)默認值。調(diào)用時如果不傳入?yún)?shù),則使用默認值
不定長部分如果沒有指定參數(shù),傳入是一個空元組
加了 兩個星號 ** 的參數(shù)會以字典的形式導入
/ 用來指明函數(shù)形參必須使用指定位置參數(shù),不能使用關(guān)鍵字參數(shù)的形式。
3.8版本之后的才能使用
不使用 def 定義函數(shù),沒有函數(shù)名
lamdba主體時一個表達式,而不是代碼塊,函數(shù)體比def簡單很多
定義在函數(shù)內(nèi)部的為局部變量,僅能在函數(shù)內(nèi)部使用
定義在函數(shù)外部的為全局變量,可在全局使用
模塊是將包含所有定義的函數(shù)和變量的文件,一般將同類功能的函數(shù)組和在一起稱為模塊。
模塊需要導入后,在調(diào)用相應函數(shù)進行使用
模塊導入的方法:
從模塊中導入一個指定的部分
把一個模塊的所有內(nèi)容全都導入
在前面已經(jīng)多次提到函數(shù)這個概念,之所以沒有解釋什么是函數(shù),是因為程序中的函數(shù)和數(shù)學中的函數(shù)差不多,如input()、range()等都是函數(shù),這些都是Python的標準函數(shù),直接使用就可以了。根據(jù)需要,用戶也可以自定義函數(shù)。
12.1 函數(shù)
函數(shù)的結(jié)構(gòu):
def 函數(shù)名(參數(shù)):
函數(shù)體
return 返回值
例如:數(shù)學中的函數(shù)f(x)=2x+5在Python中可以定義如下:
def f(x):
y=2*x+5
return(y)
如果x取值為3,可以使用如下語句調(diào)用函數(shù):
f(3)
下面給出完整的程序代碼:
def f(x):
y=2*x+5
return(y)
res=f(3)
print(res)
運行結(jié)果:11
如上例中的x是函數(shù)f(x)的參數(shù),有時也被稱為形式參數(shù)(簡稱形參),在函數(shù)被調(diào)用時,x被具體的值3替換y就是函數(shù)的返回值,這個值3也被稱為實際參數(shù)(簡稱實參)。
上例中的y是函數(shù)f(x)的返回值。并不是所有的函數(shù)都有參數(shù)和返回值。如下面的函數(shù):
def func():
print('此為無參數(shù)傳遞、無返回值的函數(shù)')
func()
輸出結(jié)果:此為無參數(shù)傳遞、無返回值的函數(shù)
可以看出,該函數(shù)func()無參數(shù),故調(diào)用時不用賦給參數(shù)值。
函數(shù)也可以有多個參數(shù),如f(x,y)=x2+y2,可用Python語言定義如下:
def f(x,y):
z=x**2+y**2
return z
print(f(2,3)) #調(diào)用函數(shù)f(x,y)
輸出結(jié)果:13
也可以通過直接給參數(shù)列表中的參數(shù)賦值的方法,為參數(shù)添加默認值,如果用戶賦予參數(shù)值,則按照用戶賦值執(zhí)行,否則使用默認值。例如:
def f(x,y=3):
z=x**2+y**2
return z
若調(diào)用時參數(shù)列表為(2,1),即x賦值為2,y賦值為1:
print(f(2,1))
輸出結(jié)果為:5
若調(diào)用時參數(shù)列表為(2),即x賦值為2,y賦值省缺,則y使用默認值:
print(f(2))
輸出結(jié)果為:13
回調(diào)函數(shù),又稱函數(shù)回調(diào),是將函數(shù)作為另一函數(shù)的參數(shù)。
例如:
def func(fun,m,n):
fun(m,n)
def f_add(m,n):
print('m+n=',m+n)
def f_mult(m,n):
print('m*n=',m*n)
func(f_add,2,3)
func(f_mult,2,3)
輸出結(jié)果:
m+n= 5
m*n= 6
在f_add(m,n)和f_mult(m,n)被定義前,func(fun,m,n)中的fun(m,n)就已經(jīng)調(diào)用了這兩個函數(shù),即“先調(diào)用后定義”,這也是回調(diào)函數(shù)的特點。
如果無法預知參數(shù)的個數(shù),可以在參數(shù)前面加上*號,這種參數(shù)實際上對應元組類型。譬如,參會的人數(shù)事先不能確定,只能根據(jù)與會人員名單輸入:
def func(*names):
print('今天與會人員有:')
for name in names:
print(name)
func('張小兵','陳曉梅','李大海','王長江')
運行后,輸出結(jié)果為:
今天與會人員有:
張小兵
陳曉梅
李大海
王長江
參數(shù)為字典類型,需要在參數(shù)前面加上**號。
def func(**kwargs):
for i in kwargs:
print(i,kwargs[i])
func(a='a1',b='b1',c='c1')
輸出結(jié)果為:
a a1
b b1
c c1
一個有趣的實例:
def func(x,y,z,*args,**kwargs):
print(x,y,z)
print(args)
print(kwargs)
func('a','b','c','Python','is easy',py='python',j='java',ph='php')
輸出結(jié)果:
a b c # 前三個實參賦給前三個形參
('Python', 'is easy') # *args接收元組數(shù)據(jù)
{'py': 'python', 'j': 'java', 'ph': 'php'} # **kwargs接收字典數(shù)據(jù)
12.2 變量的作用域
變量的作用域即變量的有效范圍,可分為全局變量和局部變量。
局部變量
在函數(shù)中定義的變量就是局部變量,局部變量的作用域僅限于函數(shù)內(nèi)部使用。
全局變量
在主程序中定義的變量就是全局變量,但在函數(shù)中用關(guān)鍵字global修飾的變量也可以當做全局變量來使用。
全局變量的作用域是整個程序,也就是說,全局變量可以在整個程序中可以訪問。
下面通過實例去討論:
程序1:
a=1 # a為全局變量
def a_add():
print('a的初值:',a) # 在函數(shù)中讀取a的值
a_add() # 調(diào)用函數(shù)a_add()
a+=1 # 主程序語句,a增加1
print('a現(xiàn)在的值是:',a) # 主程序語句,讀取a的值
運行結(jié)果:
a的初值: 1
a現(xiàn)在的值是: 2
這個結(jié)果和我們想象的一樣,全局變量a既可以在主程序中讀取,也可以在子程序(函數(shù))中讀取。
程序2:
a=1
def a_add():
a+=1
print('a的初值:',a)
a_add()
print('a現(xiàn)在的值是:',a)
運行程序1時出現(xiàn)如下錯誤提示:
UnboundLocalError: local variable 'a' referenced before assignment
意思是:局部變量'a'在賦值之前被引用。
從語法上來講,該程序沒有錯誤。首先定義了一個全局變量a并賦值為1,又定義了一個函數(shù)a_add(),函數(shù)內(nèi)的語句a+=1就是出錯的根源,雖然我們的初衷是想讓全局變量a的值增加1,但從錯誤提示看,這個語句中的a并不是全局變量,而是局部變量。看來,在函數(shù)中讀取全局變量的值是沒有問題的(在程序1中已經(jīng)得到了驗證),但要在函數(shù)中改變?nèi)肿兞康闹凳遣恍械模ㄔ诔绦?的錯誤提示a+=1中的a 是局部變量,而非全局變量)。
怎樣解決這個問題?
程序3:
a=1
def a_add(x):
x+=1
return x
print('a的初值:',a)
a=a_add(a)
print('a現(xiàn)在的值是:',a)
運行結(jié)果:
a的初值: 1
a現(xiàn)在的值是: 2
結(jié)果的確是正確的,但在函數(shù)a_add(x)中沒有調(diào)用變量a(沒有出現(xiàn)變量a)。
程序4:
a=1
def a_add(a):
a+=1
return a
print('a的初值:',a)
a=a_add(a)
print('a現(xiàn)在的值是:',a)
運行結(jié)果:
a的初值: 1
a現(xiàn)在的值是: 2
對比程序4和程序3不難發(fā)現(xiàn),其實程序4只是簡單的把函數(shù)的參數(shù)x變成了a,這個a的實質(zhì)和程序3中的x還是一樣的。這進一步證實,函數(shù)中的a是局部變量,與主程序的全局變量a有著本質(zhì)的區(qū)別。
程序5:
a=1
def a_add():
global a
a+=1
print('a的初值:',a)
a_add()
print('a現(xiàn)在的值是:',a)
運行結(jié)果:
a的初值: 1
a現(xiàn)在的值是: 2
程序5和程序2相比較,僅僅是在函數(shù)中添加了一個定義“global a”,此時的局部變量a就可以當做全局變量使用,由于它和全局變量a同名,自然也就不用區(qū)分a究竟是全局變量還是局部變量了,在主程序和該函數(shù)內(nèi)都可以訪問、修改變量a的值了。
雖然使用global可使變量使用起來非常方便,但也容易引起混淆,故在使用過程中還是謹慎為好。
12.3 函數(shù)的遞歸與嵌套
遞歸,就是函數(shù)調(diào)用它自身。遞歸必須設(shè)置停止條件,否則函數(shù)將無法終止,形成死循環(huán)。
以計算階乘為例:
def func(n):
if n==1:
return 1
else:
return n*func(n-1) #func( )調(diào)用func( )
print(func(5))
運行結(jié)果為:120
嵌套,指在函數(shù)中調(diào)用另外的函數(shù)。這是程序中常見的一種結(jié)構(gòu),在此不再贅述。
匿名函數(shù)
Python中可以在參數(shù)前加上關(guān)鍵字lambda定義一個匿名函數(shù),這樣的函數(shù)一般都屬于“一次性”的。
例如:
程序1:這是一個常規(guī)的函數(shù)定義和調(diào)用。
def f_add(x,y):
return x+y
print(f_add(2,3))
輸出結(jié)果:5
程序2:使用lambda定義匿名函數(shù)。
f_add=lambda x,y:x+y
print(f_add(2,3))
輸出結(jié)果:5
從上面的代碼可以看出,使用lambda僅僅減少了一行代碼。f_add=lambda x,y:x+y中的f_add不是變量名,而是函數(shù)名。程序1和程序2的print( )語句中的參數(shù)都是一樣的——調(diào)用函數(shù)f_add( )。所以,匿名函數(shù)并沒有太多的優(yōu)點。
網(wǎng)頁名稱:python函數(shù)變量調(diào)用,python 調(diào)用變量
文章鏈接:http://www.yijiale78.com/article32/hcsesc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、、虛擬主機、動態(tài)網(wǎng)站、靜態(tài)網(wǎng)站、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)