python之函數

來源:互聯網
上載者:User

標籤:運算式   程式員   防偽   

防偽碼:忘情公子著


函數是Python為了代碼最大程度地重用和最小化代碼冗餘而提供的基本程式結構。

函數是一種設計工具,能讓程式員將複雜的系統分解為可管理的組件,在需要時能夠按需去調用這些組件。

函數用於將相關功能打包並參數化

在Python中可以建立4種函數:

 全域函數:定義在模組中

  局部函數:嵌套於其它函數中

  lambda(匿名)函數:僅是一個運算式,可以出現在任何位置,使用的靈活度比函數強得多。它產生一個函數對象,若想多次調用,則應將其賦予某變數名進行調用

  方法:與特定資料類型關聯的函數,並且只能與資料類型關聯一起使用。說白了就是定義在類(class)中的函數


建立函數,文法如下:

def functionName(parameters):    suite

def是一個可執行語句,因此可以出現在任何能夠使用語句的地方,甚至可以嵌套於其它語句,例如if或while中。

def建立了一個對象並將其賦值給一個變數名(即函數名)。

return用於返回結果對象,其為可選;無return語句的函數自動返回None對象。返回多個值時,彼此間使用逗號分隔,且組合為元組形式返回一個對象。

def語句運行之後,可以在程式中通過函數後附加括弧進行調用。如:

In [1]: def printName():    #定義一個函數printName   ...:     print "hello"   ...: In [2]: printName()         #調用函數printNamehello


Python建立、改變或尋找變數名,都是在名稱空間中進行的。名稱空間(範圍)說白了就是一個變數所能夠生效的範圍。

在Python中,變數名在程式碼中被賦值的位置,決定了其能夠被訪問到的範圍。

函數定義了本地範圍,而模組定義了全域範圍

  每個模組都是一個全域範圍,因此,全域範圍的範圍僅限於單個檔案;

  每次對函數的調用都會建立一個新的本地範圍,賦值的變數除非聲明為全域變數,否則均為本地變數;

  所有的變數名都可以歸納為本地、全域或內建的(由__builtin__模組提供)


變數名引用分三個範圍進行:首先是本地、之後是函數內、接著是全域,最後是內建。

650) this.width=650;" src="http://s2.51cto.com/wyfs02/M02/8B/CB/wKiom1hY6lCzfHQtAAC9gYEXo40352.jpg" title="函數範圍.jpg" width="700" height="467" border="0" hspace="0" vspace="0" style="width:700px;height:467px;" alt="wKiom1hY6lCzfHQtAAC9gYEXo40352.jpg" />

變數名解析遵循由內而外的法則,也即LEGB原則(如)。變數解析時有幾點需要注意:

  先從Local(function)中尋找,找到則返回解析結果,若找不到則到Enclosing function locals中尋找;

  若在Enclosing function locals中找到了則返回解析結果,若找不到則到Global(module)中尋找;

  若在Global(module)中找到了則返回解析結果,若找不到則到Built-in中尋找;

  若在Built-in中找到了則返回解析結果,若找不到則返回“名稱引用錯誤”異常

變數名解析時,範圍越小,其優先順序越高。也就是說,若在Local(function)中找到了,則直接返回其解析結果,而不會再到Enclosing function locals上去尋找了。


全域變數:

  全域變數是模組檔案內部的頂層變數名;

  如果要在函數內部對全域變數進行賦值的話,必須事先使用global進行聲明,global關鍵字後跟一個或多個由逗號隔開的變數名;

  全域變數名在函數內部不經聲明也可以被引用;

  本地變數在函數返回時會消失,而全域變數不會,因此,使用全域變數是儲存函數狀態資訊的最直接辦法;

  盡量避免在函數中使用global聲明全域變數。


內嵌函數:

  Python中函數可以嵌套,也即可以在一個函數內部定義一個函數;

  在函數內部定義的函數僅能由外層函數進行調用;

  而如果外層函數直接把內層函數使用return返回,則調用外層函數時賦值的變數名引用的是一個內層函數對象,且此內層函數能夠記憶其內部引用的外層函數的變數,這種行為叫做工廠函數,也叫閉合函數

In [11]: def maker(N):    ...:     def action(X):    ...:         return X ** N    ...:     return action    ...:In [12]: f = maker(2)In [13]: f(3)Out[13]: 9In [14]: f(4)Out[14]: 16In [15]: type(f)Out[15]: function


參數傳遞:

  參數的傳遞是通過自動將對象賦值給本地變數實現的

650) this.width=650;" src="http://s1.51cto.com/wyfs02/M02/8B/C8/wKioL1hY9h-wG3iAAAAxe5nkG6Y156.jpg" title="參數傳遞.jpg" alt="wKioL1hY9h-wG3iAAAAxe5nkG6Y156.jpg" />

  不可變參數通過“值”進行傳遞,在函數內部改變形參的值,只是讓其引用了另一個對象(如數字)

  可變參數通過“指標”進行傳遞,在函數內部改變形參的值,將直接修改引用的對象(如列表)


有兩種方式可避免可變參數被函數修改:

  1、直接傳遞可變對象的副本:

In [16]: L = [1,2,3,4]In [17]: def changer(X):    ...:     X[2]+=10    ...:     return X    ...:In [18]: changer(L[:])Out[18]: [1, 2, 13, 4]In [19]: print L[1, 2, 3, 4]

  2、在函數內部建立可變參數的副本

In [27]: L = [1,2,3,4]In [28]: def changer(X):    ...:     aa = X[:]    ...:     aa[2]+=10    ...:     return aa    ...:In [29]: changer(L)Out[29]: [1, 2, 13, 4]In [30]: print L[1, 2, 3, 4]


參數匹配模型:

預設情況下,參數通過其位置進行傳遞,從左至右,這意味著,必須精確地傳遞和函數頭部參數一樣多的參數

但也可以通過關鍵字參數、預設參數或參數容器等改變這種機制

  位置:從左至右

  關鍵字參數:使用“name=value”的文法通過參數名進行匹配

  預設參數:定義函數時使用“name=value”的文法直接給變數一個值,從而傳入的值可以少於參數個數

  可變參數:定義是為了整合,調用是為了分解

    定義函數時使用*開頭的參數,可用於收集任意多基於位置的參數:

In [31]: def test(*x):    ...:     print x    ...: In [32]: test(1)(1,)In [33]: test(1,2,3)(1, 2, 3)

    定義函數時使用**開頭的參數,可用於收集任意多基於關鍵字參數,並將其轉換成字典:

In [34]: def dict(**x):    ...:     print x    ...: In [35]: dict(x=1,y=2,z=6){‘y‘: 2, ‘x‘: 1, ‘z‘: 6}

   混用位置參數與可變參數:

In [36]: def a(x,*y):    ...:     print x,y    ...: In [37]: a(1,2,3,4)1 (2, 3, 4)
In [38]: def b(*x,**y):    ...:     print x    ...:     print y    ...: In [39]: b(1,2,3,4,5,i=3,j=9,c=5)(1, 2, 3, 4, 5){‘i‘: 3, ‘c‘: 5, ‘j‘: 9}

  可變參數解包:調用函數時,使用*開頭的參數,可用於將參數集合打散,從而傳遞任意多基於位置或關鍵字的參數。可以理解為分解參數。

   變數分解賦值:

In [1]: l1 = [‘Sun‘,‘Mon‘,‘Tue‘]In [2]: x,y,z = l1In [3]: print xSunIn [4]: print yMonIn [5]: print zTue
In [6]: l2 = [‘Sun‘,‘Mon‘,‘Tue‘]In [7]: def a(x,y,z):   ...:     print x,y,z   ...: In [8]: a(*l2)Sun Mon Tue

可變參數與位置參數混合使用時,不論是定義還是調用,均使用以下順序:

  位置參數-->任意位置參數(*)-->關鍵字參數(**)


匿名函數lambda:

文法如下:

lambda args: expression

  args:以逗號分隔的參數列表

  expression:用到args中各參數的運算式

lambda語句定義的代碼必須是合法的運算式,不能出現多條件陳述式(可使用if的三元運算式)和其它非運算式語句,如for和while等。

lambda的首要用途是指定短小的回呼函數。lambda將返回一個函數而不是將函數賦值給某變數名。

注意:

  lambda是一個運算式而非語句;

  lambda是一個單個運算式,而不是一個代碼塊

In [9]: lambda x,y: print x,y    #不能是語句,只能是運算式  File "<ipython-input-9-323c5186b793>", line 1    lambda x,y: print x,y                    ^SyntaxError: invalid syntaxIn [10]: lambda x,y: x + y        #返回的是一個函數Out[10]: <function __main__.<lambda>>

因為lambda返回的是一個函數,所以如果要調用它的話,則要將lambda運算式賦予一個變數名,通過變數名來調用:

In [11]: a = lambda x,y: x + yIn [12]: a(5,6)Out[12]: 11

正因為lambda函數調用時必須賦予給某個變數名,通過變數名來調用,而這個變數名又不固定,故此稱之為匿名函數。

def語句建立的函數將賦值給某變數名,而lambda運算式則直接返回函數。lambda也支援使用預設參數。

In [13]: def testFunc(x,y,z):    ...:     return x + y + z    ...:In [14]: testFunc(4,5,6)Out[14]: 15In [15]: f = lambda x,y,z: x+y+zIn [16]: f(4,5,6)Out[16]: 15In [17]: f2 = (lambda x,y,z=10: x+y+z)In [18]: f2(4,5)Out[18]: 19

在對某個資料對象作出多種不同處理時,可以把每一種處理機制定義成一個lambda,而後對這個資料對象調用這多個lambda運算式。

In [1]: l3 = [ (lambda x: x*2),(lambda y: y*3) ]In [2]: for i in l3:        #i取到的是lambda運算式,而不是x和y的值   ...:     print i(4)   ...: 812


本文出自 “忘情博” 部落格,請務必保留此出處http://itchentao.blog.51cto.com/5168625/1884653

python之函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.