變量的引用
創(chuàng)新互聯(lián)長期為數(shù)千家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為蒙山企業(yè)提供專業(yè)的成都網(wǎng)站制作、網(wǎng)站建設、外貿網(wǎng)站建設,蒙山網(wǎng)站改版等技術服務。擁有十多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
變量和數(shù)據(jù)都是保存在內存中的
變量和數(shù)據(jù)是分開存儲的
數(shù)據(jù)保存在內存中某個位置,通過地址來標記
變量保存的是數(shù)據(jù)的地址,通過地址可以找到數(shù)據(jù)在內存空間的位置
把變量保存數(shù)據(jù)地址的過程稱為引用
變量的重新賦值修改的是變量中引用數(shù)據(jù)的內存地址
變量之間的賦值實際是引用的傳遞
函數(shù)參數(shù)的傳遞,本質也是引用的傳遞
函數(shù)的返回值本身也是引用的傳遞
可變和不可變類型
不可變類型,內存中的數(shù)據(jù)不允許被修改:數(shù)字類型(int,bool,float,complex,long(2,x)、字符串、元組(tuple)
可變類型,內存中的數(shù)據(jù)可以被修改:列表list、字典dict
無論是可變還是不可變數(shù)據(jù)類型,通過賦值語句,都會改變變量的引用
Hash函數(shù)只能接收不可變數(shù)據(jù)類型,字典的鍵也只能是不可變數(shù)據(jù)類型,字典的value值可以是任意數(shù)據(jù)類型
局部變量
1.在函數(shù)內部定義的變量就是局部變量(作用范圍只能是當前函數(shù)內部)
2.在函數(shù)外部無法直接訪問局部變量
3.不同的函數(shù)中可以定義同名的局部變量
4.局部變量的生命周期:從定義變量時開始,到函數(shù)運行結束
全局變量
1.在所有函數(shù)外邊定義的變量就是全局變量
2.讓所有函數(shù)都能訪問到,可以作為函數(shù)通信的橋梁
3.一般情況下,為了和普通變量的區(qū)別,需要加上g_或gl_前綴
4.全局變量一般放在所有函數(shù)的最上面
5.在函數(shù)內部修改全局變量,必須要加上global關鍵字,如果不加global只是定義了一個同名的局部變量
函數(shù)的多個返回值
選中需要查看的函數(shù)(光標移到函數(shù)所在的位置),然后使用eclipse快捷鍵Ctrl+Shift+G,然后就會在search窗口中看到函數(shù)調用的樹狀結構圖。
以最簡單的一個代碼為例:
class A:
s="hello"
def p(self):
? print(self.s)
if __name__ == '__main__':
a=A()
a.p()
光標移到第4行p的位置,然后Ctrl+Shift+G,得到如下所示:
這里來給大家演示一下,函數(shù)的定義或構造,并調用函數(shù)來實現(xiàn)封裝后的效果。
首先我們來看看想實現(xiàn)下面的這個效果,如果不使用函數(shù)應該怎么實現(xiàn)。
以上兩種返回結果都是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)上面的打印結果就直接使用函數(shù)名+小括號調用函數(shù)就可以了,這種類型的語法,不僅可以反復使用,而且封裝后的代碼更美觀。
如果你用C給Matlab寫過MEX程序,那么這個問題是很容易理解的(好像每次討論Python問題時我總是把Matlab搬了出來…… 《在Matlab中把struct當成Python中的Dictionary使用》《Matlab和Python的幾種數(shù)據(jù)類型的比較》)。
既然提到了MEX,就簡單說一下:
一個Matlab可能形如
function ret=add3(a,b,c)
如果在C的層面實現(xiàn)這個函數(shù),就會看到另一種景象:
void mexFunction(int nlhs,mxArray * plhs[],int nrhs,const mxArray * prhs[])
a,b,c三個參數(shù)的地址放在一個指針數(shù)組里,然后把這個指針數(shù)組的首地址作為參數(shù)prhs傳遞給函數(shù),這說明Matlab函數(shù)的參數(shù)是傳遞指針的,而不是值傳遞。
縱然是傳遞的指針,但是卻不能在函數(shù)里改變實參的值,因為標記為“const”了。
Python是開放源碼的,我沒有看。所以下面很多東西是猜的。
Python在函數(shù)的參數(shù)傳遞時用的什么手法?實驗一下(使用ActivePython2.5):
首先介紹一個重要的函數(shù):
help(id)
Help on built-in function id in module __builtin__:
id(...)
id(object) - integer
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
看最后括號里那句:Hint:it's the object's address.(它是對象的地址)
有了這個函數(shù),下面的事情就方便多了。
a=0
id(a)
3630228
a=1
id(a)
3630216
可以看出,給a賦一次值,a的address就改變了。在C的層面看,(也許真實情況不是下面的樣子,但作為一個類比應該還是可以的):
void * pa;
pa=malloc(sizeof(int));
*(int *)pa=0;
free(pa);
pa=malloc(sizeof(int));
*(int *)pa=1;
Python中每次賦值會改變變量的address,分配新的內存空間,所以Python中對于類型不像C那樣嚴格要求。
下面看看Python函數(shù)參數(shù)傳遞時到底傳的什么:
有一個函數(shù):
def changeA(a):
... print id(a)
... a=100
... print id(a)
設定一個變量var1:
var1=10
id(var1)
3630108
changeA(var1)
3630108
3631012
var1
10
調用函數(shù)后,從兩次print的結果可以看出,傳遞確實是地址。但是即便如此,在函數(shù)內對形參的修改不會對實參造成任何實質的影響,因為對形參的重新賦值,只是改變了形參所指向的內存單元(changeA里兩次調用print id(a)得到不同的結果),卻沒有改變實參的指向。在C的層面看也許類似下面的情節(jié):
void changeA(void * pa)
{
pa=malloc(sizeof(int));
*(int *)pa=100;
free(pa);
}
精通C的你一眼就看出這個函數(shù)永遠也改變不了它外面的世界。
也就是說雖然傳遞的是地址,但像changeA這樣的函數(shù)改變不了實參的值。
也許會感到困擾?不,我已經(jīng)在Matlab中習慣了。
一個最典型的例子就是Matlab中刪除結構體成員的rmfield函數(shù)(參見《Matlab筆記三則》),
(Matlab版本7.0.1)
如果想刪除結構體patient的name成員,用
rmfield(patient, 'name');
是永遠達不到目的的(就像試圖用雙手抓住自己的領子,把自己提到空中);
迷途知返的做法是:
patient = rmfield(patient, 'name');
python函數(shù)的作用是:
1、函數(shù)其實是把某個功能的代碼封裝到一個代碼塊中,用來為某個重復使用的功能做調用的一個代碼塊,可以稱為一個函數(shù)的代碼封裝。可以在自定義函數(shù)的小括號中傳入多個參數(shù)。
2、形參:在定義函數(shù)時,小括號中的參數(shù)名稱。實參:在函數(shù)名稱的小括號中,傳入實際的值代替了形參的這個值。函數(shù)可以有返回值(使用return進行返回),也可以沒有返回值。
3、形參可以當做函數(shù)內部的一個變量使用,往往只在函數(shù)內部進行使用,不影響函數(shù)外部的相同名稱的變量。
4、在函數(shù)內部可以返回某個值。直接在函數(shù)內部退出來,而不再繼續(xù)執(zhí)行函數(shù)下面的代碼。
更多關于python函數(shù)的作用,進入:查看更多內容