在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 函數(shù)(2)
標準庫 (4)
如何成為 Python 高手
標準庫 (6)
標準庫 (3)
類(2)
Pandas 使用 (2)
xml
用 tornado 做網站 (5)
文件(1)
練習
列表(3)
從小工到專家
除法
錯誤和異常 (2)
函數(shù)(1)
用 tornado 做網站 (7)
為做網站而準備
函數(shù)練習
標準庫 (8)
Pandas 使用 (1)
回顧 list 和 str
字典(1)
用 tornado 做網站 (3)
字符串(1)
函數(shù)(2)
寫一個簡單的程序
將數(shù)據(jù)存入文件
語句(5)
SQLite 數(shù)據(jù)庫
集成開發(fā)環(huán)境(IDE)
集合(1)
類(1)
用 tornado 做網站 (6)
用 tornado 做網站 (2)
自省
語句(4)
錯誤和異常 (1)
用 tornado 做網站 (4)
集合(2)
列表(1)
標準庫 (1)
生成器
mysql 數(shù)據(jù)庫 (1)
第三方庫
實戰(zhàn)
運算符
類(3)
字典(2)
語句(1)
數(shù)和四則運算
語句(2)
文件(2)
MySQL 數(shù)據(jù)庫 (2)
電子表格
迭代器
mongodb 數(shù)據(jù)庫 (1)
特殊方法 (2)
特殊方法 (1)
字符編碼
編寫模塊
用 tornado 做網站 (1)
標準庫 (5)
函數(shù)(4)
類(5)
字符串(2)
關于 Python 的故事
函數(shù)(3)
字符串(4)
處理股票數(shù)據(jù)
常用數(shù)學函數(shù)和運算優(yōu)先級
字符串(3)
為計算做準備
多態(tài)和封裝
類(4)
迭代
語句(3)
錯誤和異常 (3)
分析 Hello
Python 安裝
標準庫 (2)
列表(2)
元組

函數(shù)(2)

在上一節(jié)中,已經明確了函數(shù)的基本結構和初步的調用方法。但是,上一節(jié)中寫的函數(shù),還有點缺憾,不知道讀者是否覺察到了。我把結果是用 print 語句打印出來的。這是實際編程中廣泛使用的嗎?肯定不是。因為函數(shù)在編程中,起到一段具有抽象價值的代碼作用,一般情況下,用它得到一個結果,這個結果要用在其它的運算中。所以,不能僅僅局限在把某個結果打印出來。所以,函數(shù)必須返回一個結果。

結論:函數(shù)要有返回值,也必須有返回值。

返回值

為了能夠說明清楚,先編寫一個函數(shù)。還記得斐波那契數(shù)列嗎?我打算定義一個能夠得到斐波那契數(shù)列的函數(shù),從而實現(xiàn)可以實現(xiàn)任意的數(shù)列。你先想想,要怎么寫?

參考代碼:

#!/usr/bin/env Python
# coding=utf-8

def fibs(n):
    result = [0,1]
    for i in range(n-2):
        result.append(result[-2] + result[-1])
    return result

if __name__ == "__main__":
    lst = fibs(10)
    print lst

把含有這些代碼的文件保存為名為 20202.py 的文件。在這個文件中,首先定義了一個函數(shù),名字叫做 fibs,其參數(shù)是輸入一個整數(shù)。在后面,通過 lst = fibs(10) 調用這個函數(shù)。這里參數(shù)給的是 10,就意味著要得到 n=10 的斐波那契數(shù)列。

運行后打印數(shù)列:

$ python 20202.py
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

當然,如果要換 n 的值,只需要在調用函數(shù)的時候,修改一下參數(shù)即可。這才體現(xiàn)出函數(shù)的優(yōu)勢呢。

觀察 fibs 函數(shù),最后有一個語句 return result,意思是將變量 result 的值返回。返回給誰呢?一般這類函數(shù)調用的時候,要通過類似 lst = fibs(10) 的語句,那么返回的那個值,就被變量 lst 貼上了,通過 lst 就能得到該值。如果沒有這個賦值語句,雖然函數(shù)照樣返回值,但是它飄忽在內存中,我們無法得到,并且最終還被當做垃圾被 Python 回收了。

注意:上面的函數(shù)之返回了一個返回值(是一個列表),有時候需要返回多個,是以元組形式返回。

>>> def my_fun():
...     return 1,2,3
... 
>>> a = my_fun()
>>> a
(1, 2, 3)

有的函數(shù),沒有 renturn,一樣執(zhí)行完畢,就算也干了某些活兒吧。事實上,不是沒有返回值,也有,只不過是 None。比如這樣一個函數(shù):

>>> def my_fun():
...     print "I am doing somthin."
... 

我在交互模式下構造一個很簡單的函數(shù),注意,我這是構造了一個簡單函數(shù),如果是復雜的,千萬不要在交互模式下做。如果你非要做,是能嘗到苦頭的。

這個函數(shù)的作用就是打印出一段話。也就是執(zhí)行這個函數(shù),就能打印出那段話,但是沒有 return。

>>> a = my_fun()
I am doing somthin.

我們再看看那個變量 a,到底是什么

>>> print a
None

這就是這類只干活兒,沒有 return 的函數(shù),返回給變量的是一個 None。這種模樣的函數(shù),通常不用上述方式調用,而采用下面的方式,因為他們返回的是 None,似乎這個返回值利用價值不高,于是就不用找一個變量來接受返回值了。

>>> my_fun()
I am doing somthin.

特別注意那個 return,它還有一個作用。觀察下面的函數(shù)和執(zhí)行結果,看看能不能發(fā)現(xiàn)它的另外一個作用。

>>> def my_fun():
...     print "I am coding."
...     return
...     print "I finished."
... 
>>> my_fun()
I am coding.

看出玄機了嗎?在函數(shù)中,本來有兩個 print 語句,但是中間插入了一個 return,僅僅是一個 return。當執(zhí)行函數(shù)的時候,只執(zhí)行了第一個 print 語句,第二個并沒有執(zhí)行。這是因為第一個之后,遇到了 return,它告訴函數(shù)要返回,即中斷函數(shù)體內的流程,離開這個函數(shù)。結果第二個 print 就沒有被執(zhí)行。所以,return 在這里就有了一個作用,結束正在執(zhí)行的函數(shù)。有點類似循環(huán)中的 break 的作用。

函數(shù)中的文檔

“程序在大多數(shù)情況下是給人看的,只是偶爾被機器執(zhí)行以下?!彼?,寫程序必須要寫注釋。前面已經有過說明,如果用 # 開始,Python 就不執(zhí)行那句(Python 看不到它,但是人能看到),它就作為注釋存在。

除了這樣的一句之外,一般在每個函數(shù)名字的下面,還要寫一寫文檔,以此來說明這個函數(shù)的用途。

#!/usr/bin/env python
# coding=utf-8

def fibs(n):
    """
    This is a Fibonacci sequence.
    """
    result = [0,1]
    for i in range(n-2):
        result.append(result[-2] + result[-1])
    return result

if __name__ == "__main__":
    lst = fibs(10)
    print lst

在這個函數(shù)的名稱下面,用三個引號的方式,包裹著對這個函數(shù)的說明,那個就是函數(shù)文檔。

還記得在《自省》那節(jié)中,提到的__doc__嗎?對于函數(shù),它的內容就來自這里。

>>> def my_fun():
...     """
...     This is my function.
...     """
...     print "I am a craft."
... 
>>> my_fun.__doc__
'\n    This is my function.\n    '

如果在交互模式中用 help(my_fun) 得到的也是三個引號所包裹的文檔信息。

Help on function my_fun in module __main__:

my_fun()
    This is my function.

參數(shù)和變量

參數(shù)

雖然在上一節(jié),已經知道如何通過函數(shù)的參數(shù)傳值,如何調用函數(shù)等。但是,這里還有必要進一步討論參數(shù)問題。在別的程序員嘴里,你或許聽說過“形參”、“實參”、“參數(shù)”等名詞,到底指什么呢?

在定義函數(shù)的時候(def 來定義函數(shù),稱為 def 語句),函數(shù)名后面的括號里如果有變量,它們通常被稱為“形參”。調用函數(shù)的時候,給函數(shù)提供的值叫做“實參”,或者“參數(shù)”。

其實,根本不用區(qū)分這個,因為沒有什么意義,只不過類似孔乙己先生知道茴香豆的茴字有多少種寫法罷了。但是,我居然碰到過某公司面試官問這種問題。

在本教程中,把那個所謂實參,就稱之為值(或者數(shù)據(jù)、或者對象),形參就籠統(tǒng)稱之為參數(shù)(似乎不很合理,但是接近數(shù)學概念)。

比較參數(shù)和變量

參數(shù)問題就算說明白了,糊涂就糊涂吧,也沒有什么關系。不過,對于變量和參數(shù),這兩個就不能算糊涂賬了。因為它容易讓人糊涂了。

在數(shù)學的函數(shù)中 y = 3x + 2,那個x叫做參數(shù),也可以叫做變量。但是,在編程語言的函數(shù)中,與此有異。

先參考一段來自微軟網站的比較高度抽象,而且意義涵蓋深遠的說明。我摘抄過來,看官讀一讀,是否理解,雖然是針對VB而言的,一樣有啟發(fā)。

參數(shù)和變量之間的差異 (Visual Basic)

多數(shù)情況下,過程必須包含有關調用環(huán)境的一些信息。執(zhí)行重復或共享任務的過程對每次調用使用不同的信息。此信息包含每次調用過程時傳遞給它的變量、常量和表達式。

若要將此信息傳遞給過程,過程先要定義一個形參,然后調用代碼將一個實參傳遞給所定義的形參。 您可以將形參當作一個停車位,而將實參當作一輛汽車。 就像一個停車位可以在不同時間停放不同的汽車一樣,調用代碼在每次調用過程時可以將不同的實參傳遞給同一個形參。

形參表示一個值,過程希望您在調用它時傳遞該值。

當您定義 Function 或 Sub 過程時,需要在緊跟過程名稱的括號內指定形參列表。對于每個形參,您可以指定名稱、數(shù)據(jù)類型和傳入機制(ByVal (Visual Basic) 或 ByRef (Visual Basic))。您還可以指示某個形參是可選的。這意味著調用代碼不必傳遞它的值。

每個形參的名稱均可作為過程內的局部變量。形參名稱的使用方法與其他任何變量的使用方法相同。

實參表示在您調用過程時傳遞給過程形參的值。調用代碼在調用過程時提供參數(shù)。

調用 Function 或 Sub 過程時,需要在緊跟過程名稱的括號內包括實參列表。每個實參均與此列表中位于相同位置的那個形參相對應。

與形參定義不同,實參沒有名稱。每個實參就是一個表達式,它包含零或多個變量、常數(shù)和文本。求值的表達式的數(shù)據(jù)類型通常應與為相應形參定義的數(shù)據(jù)類型相匹配,并且在任何情況下,該表達式值都必須可轉換為此形參類型。

看官如果硬著頭皮看完這段引文,發(fā)現(xiàn)里面有幾個關鍵詞:參數(shù)、變量、形參、實參。本來想弄清楚參數(shù)和變量,結果又冒出另外兩個東東,更混亂了。請稍安勿躁,本來這段引文就是有點多余,但是,之所以引用,就是讓列位開闊一下眼界,在編程業(yè)界,類似的東西有很多名詞。下次聽到有人說這些,不用害怕啦,反正自己聽過了。

在 Python 中,沒有這么復雜。

看完上面讓人暈頭轉向的引文之后,再看下面的代碼,就會豁然開朗了。

>>> def add(x):     #x 是參數(shù),準確說是形參
...     a = 10      #a 是變量
...     return a+x  #x 就是那個形參作為變量,其本質是要傳遞賦給這個函數(shù)的值
... 
>>> x = 3           #x 是變量,只不過在函數(shù)之外
>>> add(x)          #這里的 x 是參數(shù),但是它由前面的變量 x 傳遞對象 3
13
>>> add(3)          #把上面的過程合并了
13

至此,看官是否清楚了一點點。當然,我所表述不正確之處或者理解錯誤之處,也請看官不吝賜教,小可作揖感謝。

其實沒有那么復雜。關鍵要理解函數(shù)名括號后面的東東(管它什么參呢)的作用是傳遞值。

全局變量和局部變量

下面是一段代碼,注意這段代碼中有一個函數(shù) funcx(),這個函數(shù)里面有一個變量 x=9,在函數(shù)的前面也有一個變量 x=2

x = 2

def funcx():
    x = 9
    print "this x is in the funcx:-->",x

funcx()
print "--------------------------"
print "this x is out of funcx:-->",x

那么,這段代碼輸出的結果是什么呢?看:

this x is in the funcx:--> 9
--------------------------
this x is out of funcx:--> 2

從輸出看出,運行 funcx(),輸出了 funcx() 里面的變量 x=9;然后執(zhí)行代碼中的最后一行,print "this x is out of funcx:-->",x

特別要關注的是,前一個 x 輸出的是函數(shù)內部的變量 x;后一個 x 輸出的是函數(shù)外面的變量 x。兩個變量彼此沒有互相影響,雖然都是 x。從這里看出,兩個 x 各自在各自的領域內起到作用。

把那個只在函數(shù)體內(某個范圍內)起作用的變量稱之為局部變量

有局部,就有對應的全部,在漢語中,全部變量,似乎有歧義,幸虧漢語豐富,于是又取了一個名詞:全局變量

x = 2
def funcx():
    global x    #跟上面函數(shù)的不同之處
    x = 9
    print "this x is in the funcx:-->",x

funcx()
print "--------------------------"
print "this x is out of funcx:-->",x

以上兩段代碼的不同之處在于,后者在函數(shù)內多了一個 global x,這句話的意思是在聲明 x 是全局變量,也就是說這個 x 跟函數(shù)外面的那個 x 同一個,接下來通過 x=9 將 x 的引用對象變成了 9。所以,就出現(xiàn)了下面的結果。

this x is in the funcx:--> 9
--------------------------
this x is out of funcx:--> 9

好似全局變量能力很強悍,能夠統(tǒng)帥函數(shù)內外。但是,要注意,這個東西要慎重使用,因為往往容易帶來變量的換亂。內外有別,在程序中一定要注意的。

命名空間

這是一個比較不容易理解的概念,特別是對于初學者而言,似乎它很飄渺。我在維基百科中看到對它的定義,不僅定義比較好,連里面的例子都不錯。所以,抄錄下來,幫助讀者理解這個名詞。

命名空間(英語:Namespace)表示標識符(identifier)的可見范圍。一個標識符可在多個命名空間中定義,它在不同命名空間中的含義是互不相干的。這樣,在一個新的命名空間中可定義任何標識符,它們不會與任何已有的標識符發(fā)生沖突,因為已有的定義都處于其它命名空間中。

例如,設 Bill 是 X 公司的員工,工號為 123,而 John 是 Y 公司的員工,工號也是 123。由于兩人在不同的公司工作,可以使用相同的工號來標識而不會造成混亂,這里每個公司就表示一個獨立的命名空間。如果兩人在同一家公司工作,其工號就不能相同了,否則在支付工資時便會發(fā)生混亂。

這一特點是使用命名空間的主要理由。在大型的計算機程序或文檔中,往往會出現(xiàn)數(shù)百或數(shù)千個標識符。命名空間(或類似的方法,見“命名空間的模擬”一節(jié))提供一隱藏區(qū)域標識符的機制。通過將邏輯上相關的標識符組織成相應的命名空間,可使整個系統(tǒng)更加模塊化。

在編程語言中,命名空間是對作用域的一種特殊的抽象,它包含了處于該作用域內的標識符,且本身也用一個標識符來表示,這樣便將一系列在邏輯上相關的標識符用一個標識符組織了起來。許多現(xiàn)代編程語言都支持命名空間。在一些編程語言(例如 C++ 和 Python)中,命名空間本身的標識符也屬于一個外層的命名空間,也即命名空間可以嵌套,構成一個命名空間樹,樹根則是無名的全局命名空間。

函數(shù)和類的作用域可被視作隱式命名空間,它們和可見性、可訪問性和對象生命周期不可分割的聯(lián)系在一起。

顯然,用“命名空間”或者“作用域”這樣的名詞,就是因為有了函數(shù)(后面還會有類)之后,在函數(shù)內外都可能有外形一樣的符號(標識符),在 Python 中(乃至于其它高級語言),通常就是變量,為了區(qū)分此變量非彼變量(雖然外形一樣),需要用這樣的東西來框定每個變量所對應的值(發(fā)生作用的范圍)。

前面已經講過,變量和對象(就是所變量所對應的值)之間的關系是:變量類似標簽,貼在了對象上。也就是,通過賦值語句實現(xiàn)了一個變量標簽對應一個數(shù)據(jù)對象(值),這種對應關系讓你想起了什么?映射!Python 中唯一的映射就是 dict,里面有“鍵值對”。變量和值得關系就有點像“鍵”和“值”的關系。有一個內建函數(shù) vars,可以幫助我們研究一下這種對應關系。

>>> x = 7
>>> scope = vars()
>>> scope['x']
7
>>> scope['x'] += 1
>>> x
8
>>> scope['x']
8

既然如此,誠如前面的全局變量和局部變量,即使是同樣一個變量名稱。但是它在不同范圍(還是用“命名空間”這個詞是不是更專業(yè)呢?)對應不同的值。


總目錄   |   上節(jié):函數(shù)(1)   |   下節(jié):函數(shù)(3)

如果你認為有必要打賞我,請通過支付寶:qiwsir@126.com,不勝感激。