Python在heap中分配的對象分成兩類:可變對象和不可變對象。所謂可變對象是指,對象的內(nèi)容是可變的,例如list。而不可變的對象則相反,表示其內(nèi)容不可變。
我們提供的服務(wù)有:做網(wǎng)站、網(wǎng)站設(shè)計、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、東至ssl等。為數(shù)千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學管理、有技術(shù)的東至網(wǎng)站制作公司
不可變對象:int,string,float,tuple
可變對象 :list,dictionary
所以,如果a,b是可變對象,當b傳給 h(a), a和b就引用了同一個對象,修改了a對象的值,就相當于修改了b對象的值。
如果a,b用的int對象,那a,b不可變的對象的特征沒有變(原對象的值并沒有改變),變的只是創(chuàng)建了新對象,改變了變量的對象引用。
def h(a):
a=123
b=456
h(b)
print b #結(jié)果是456
順便說一下,你這個例子運行后的結(jié)果其實是['456'],不信你可以寫個程序跑一下,因為a=['123]并不是修改對象的內(nèi)容,而是讓a指向了新的對象引用,所以,最后b的內(nèi)容還是['456']。
改成a[0]=123,才是你期望的結(jié)果。
在python中,函數(shù)可以被嵌套定義,也就是說,函數(shù)中可以定義函數(shù)。該函數(shù)還可以將其內(nèi)部定義的函數(shù)作為返回值返回。
閉包的定義:一般來說,我們可以認為,如果一個函數(shù)可以讀取其他函數(shù)中的局部變量,那么它們就構(gòu)成了閉包。
注意 :閉包的定義不是特別清晰,但大體上的意思是這樣的。
我們知道,普通的函數(shù)是可以使用全局變量的
類似的,函數(shù)中定義的函數(shù),也是可以使用外部函數(shù)的變量的。因此,滿足了函數(shù)讀取了其他函數(shù)局部變量的這一條件,他們因此構(gòu)成了閉包。
在閉包的使用中,我們可以先給外部的函數(shù)賦予不同的局部變量,然后再調(diào)用其中內(nèi)部的函數(shù)時,就可以讀取到這些不同的局部變量了。
外部變量的使用 在普通函數(shù)中,雖然可以直接使用全局變量,但是不可以直接修改全局變量。從變量的作用域來說,一旦你嘗試修改全局變量,那么就會嘗試創(chuàng)建并使用一個同名的局部變量。因此,如果你需要在普通函數(shù)中修改全局變量,需要使用global
同樣的,如果你希望通過定義在內(nèi)部的函數(shù)去修改其外部函數(shù)的變量,那么必須使用nonlocal
python函數(shù)的作用是:
1、函數(shù)其實是把某個功能的代碼封裝到一個代碼塊中,用來為某個重復(fù)使用的功能做調(diào)用的一個代碼塊,可以稱為一個函數(shù)的代碼封裝。可以在自定義函數(shù)的小括號中傳入多個參數(shù)。
2、形參:在定義函數(shù)時,小括號中的參數(shù)名稱。實參:在函數(shù)名稱的小括號中,傳入實際的值代替了形參的這個值。函數(shù)可以有返回值(使用return進行返回),也可以沒有返回值。
3、形參可以當做函數(shù)內(nèi)部的一個變量使用,往往只在函數(shù)內(nèi)部進行使用,不影響函數(shù)外部的相同名稱的變量。
4、在函數(shù)內(nèi)部可以返回某個值。直接在函數(shù)內(nèi)部退出來,而不再繼續(xù)執(zhí)行函數(shù)下面的代碼。
更多關(guān)于python函數(shù)的作用,進入:查看更多內(nèi)容
變量的引用
變量和數(shù)據(jù)都是保存在內(nèi)存中的
變量和數(shù)據(jù)是分開存儲的
數(shù)據(jù)保存在內(nèi)存中某個位置,通過地址來標記
變量保存的是數(shù)據(jù)的地址,通過地址可以找到數(shù)據(jù)在內(nèi)存空間的位置
把變量保存數(shù)據(jù)地址的過程稱為引用
變量的重新賦值修改的是變量中引用數(shù)據(jù)的內(nèi)存地址
變量之間的賦值實際是引用的傳遞
函數(shù)參數(shù)的傳遞,本質(zhì)也是引用的傳遞
函數(shù)的返回值本身也是引用的傳遞
可變和不可變類型
不可變類型,內(nèi)存中的數(shù)據(jù)不允許被修改:數(shù)字類型(int,bool,float,complex,long(2,x)、字符串、元組(tuple)
可變類型,內(nèi)存中的數(shù)據(jù)可以被修改:列表list、字典dict
無論是可變還是不可變數(shù)據(jù)類型,通過賦值語句,都會改變變量的引用
Hash函數(shù)只能接收不可變數(shù)據(jù)類型,字典的鍵也只能是不可變數(shù)據(jù)類型,字典的value值可以是任意數(shù)據(jù)類型
局部變量
1.在函數(shù)內(nèi)部定義的變量就是局部變量(作用范圍只能是當前函數(shù)內(nèi)部)
2.在函數(shù)外部無法直接訪問局部變量
3.不同的函數(shù)中可以定義同名的局部變量
4.局部變量的生命周期:從定義變量時開始,到函數(shù)運行結(jié)束
全局變量
1.在所有函數(shù)外邊定義的變量就是全局變量
2.讓所有函數(shù)都能訪問到,可以作為函數(shù)通信的橋梁
3.一般情況下,為了和普通變量的區(qū)別,需要加上g_或gl_前綴
4.全局變量一般放在所有函數(shù)的最上面
5.在函數(shù)內(nèi)部修改全局變量,必須要加上global關(guān)鍵字,如果不加global只是定義了一個同名的局部變量
函數(shù)的多個返回值
一、函數(shù)的定義
函數(shù)是指將一組語句的集合通過一個名字(函數(shù)名)封裝起來,想要執(zhí)行這個函數(shù),只需要調(diào)用函數(shù)名即可
特性:
減少重復(fù)代碼
使程序變得可擴展
使程序變得易維護
二、函數(shù)的參數(shù)
2.1、形參和實參數(shù)
形參,調(diào)用時才會存在的值
實慘,實際存在的值
2.2、默認參數(shù)
定義:當不輸入?yún)?shù)值會有一個默認的值,默認參數(shù)要放到最后
2.3、 關(guān)鍵參數(shù)
定義: 正常情況下,給函數(shù)傳參數(shù)要安裝順序,不想按順序可以用關(guān)鍵參數(shù),只需要指定參數(shù)名即可,(指定了參數(shù)名的就叫關(guān)鍵參數(shù)),但是要求是關(guān)鍵參數(shù)必須放在位置參數(shù)(以位置順序確定對應(yīng)的參數(shù))之后
2.4、非固定參數(shù)
定義: 如你的函數(shù)在傳入?yún)?shù)時不確定需要傳入多少個參數(shù),就可以使用非固定參數(shù)
# 通過元組形式傳遞
# 通過列表形式傳遞
# 字典形式(通過k,value的方式傳遞)
# 通過變量的方式傳遞
三、函數(shù)的返回值
作用:
返回函數(shù)執(zhí)行結(jié)果,如果沒有設(shè)置,默認返回None
終止函數(shù)運行,函數(shù)遇到return終止函數(shù)
四、變量的作用域
全局變量和局部變量
在函數(shù)中定義的變量叫局部變量,在程序中一開始定義的變量叫全局變量
全局變量作用域整個程序,局部變量作用域是定義該變量的函數(shù)
當全局變量與局部變量同名是,在定義局部變量的函數(shù)內(nèi),局部變量起作用,其他地方全局變量起作用
同級的局部變量不能互相調(diào)用
想要函數(shù)里邊的變量設(shè)置成全局變量,可用global進行設(shè)置
五、特殊函數(shù)
5.1、嵌套函數(shù)
定義: 嵌套函數(shù)顧名思義就是在函數(shù)里邊再嵌套一層函數(shù)
提示 在嵌套函數(shù)里邊調(diào)用變量是從里往外依次調(diào)用,意思就是如果需要調(diào)用的變量在當前層沒有就會去外層去調(diào)用,依次內(nèi)推
匿名函數(shù)
基于Lambda定義的函數(shù)格式為: lambda 參數(shù):函數(shù)體
參數(shù),支持任意參數(shù)。
匿名函數(shù)適用于簡單的業(yè)務(wù)處理,可以快速并簡單的創(chuàng)建函數(shù)。
# 與三元運算結(jié)合
5.3、高階函數(shù)
定義:變量可以指向函數(shù),函數(shù)的參數(shù)可以接收變量,那么一個函數(shù)就可以接收另一個函數(shù)作為參數(shù),這種函數(shù)稱之為高階函數(shù) 只需要滿足一下任意一個條件,即是高階函數(shù)
接收一個或多個函數(shù)作為輸入
return返回另一個函數(shù)
5.4、遞歸函數(shù)
定義:一個函數(shù)可以調(diào)用其他函數(shù),如果一個函數(shù)調(diào)用自己本身,這個函數(shù)就稱為遞歸函數(shù)
在默認情況下Python最多能遞歸1000次,(這樣設(shè)計師是為了防止被內(nèi)存被撐死)可以通過sys.setrecursionlimit(1500)進行修改
遞歸實現(xiàn)過程是先一層一層的進,然后在一層一層的出來
必須有一個明確的條件結(jié)束,要不然就是一個死循環(huán)了
每次進入更深層次,問題規(guī)模都應(yīng)該有所減少
遞歸執(zhí)行效率不高,遞歸層次過多會導(dǎo)致站溢出
# 計算4的階乘 4x3x2x1
# 打印數(shù)字從1-100
5.5、閉包現(xiàn)象
定義:內(nèi)層函數(shù)調(diào)用外層函數(shù)的變量,并且內(nèi)存函數(shù)被返回到外邊去了
閉包的意義:返回的函數(shù)對象,不僅僅是一個函數(shù)對象,在該函數(shù)外還包裹了一層作用域,這使得,該函數(shù)無論在何處調(diào)用,優(yōu)先使用自己外層包裹的作用域
Python使用函數(shù)默認值實現(xiàn)函數(shù)靜態(tài)變量的方法,具體方法如下:
一、Python函數(shù)默認值
Python函數(shù)默認值的使用可以在函數(shù)調(diào)用時寫代碼提供方便,很多時候我們只要使用默認值就可以了。 所以函數(shù)默認值在python中用到的很多,尤其是在類中間,類的初始化函數(shù)中一幫都會用到默認值。 使用類時能夠方便的創(chuàng)建類,而不需要傳遞一堆參數(shù)。
只要在函數(shù)參數(shù)名后面加上 ”=defalut_value”,函數(shù)默認值就定義好了。有一個地方需要注意的是,有默認值的參數(shù)必須在函數(shù)參數(shù)列表的最后,不允許將沒有默認值的參數(shù)放在有默認值的參數(shù)后,因為如果你那樣定義的話,解釋器將不知道如何去傳遞參數(shù)。
先來看一段示例代碼:
def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
while True:
ok = raw_input(prompt)
if ok in ('y', 'ye', 'yes'): return True
if ok in ('n', 'no', 'nop', 'nope'): return False
retries = retries - 1
if retries 0: raise IOError, 'refusenik user'
print complaint
你調(diào)用上面的函數(shù)時,可以修改重試次數(shù)和輸出的提示語言,如果你比較懶得話,那么什么都不用改。
二、python使用函數(shù)默認值來實現(xiàn)函數(shù)靜態(tài)變量的功能
Python中是不支持靜態(tài)變量的,但是我們可以通過函數(shù)的默認值來實現(xiàn)靜態(tài)變量的功能。
當函數(shù)的默認值是內(nèi)容是可變的類時,類的內(nèi)容可變,而類的名字沒變。(相當于開辟的內(nèi)存區(qū)域沒有變,而其中內(nèi)容可以變化)。
這是因為python中函數(shù)的默認值只會被執(zhí)行一次,(和靜態(tài)變量一樣,靜態(tài)變量初始化也是被執(zhí)行一次。)這就是他們的共同點。
再來看下面的程序片段:
def f(a, L=[]):
L.append(a)
return L
print f(1)
print f(2)
print f(3)
print f(4,['x'])
print f(5)
其輸出結(jié)果是:
[1]
[1, 2]
[1, 2, 3]
['x', 4]
[1, 2, 3, 5]
前面的好理解,為什么最后 “print f(5)”的輸出是 “[1, 2, 3, 5]”呢?
這是因為 “print f(4,['x'])”時,默認變量并沒有被改變,因為默認變量的初始化只是被執(zhí)行了一次(第一次使用默認值調(diào)用),初始化執(zhí)行開辟的內(nèi)存區(qū)(我們可以稱之為默認變量)沒有被改變,所以最后的輸出結(jié)果是“[1, 2, 3, 5]”。