Python黑帽編程2.5 函數

寫了幾節的基礎知識,真心感覺有點力不從心。這塊的內容說實話,看文檔是最好的方式,本人的寫作水平,真的是找不出更好的寫法,頭疼。簡單帶過和沒寫一樣,寫詳細了和本系列教程又不搭。思考再三,最後還是決定簡明扼要為主,我們把主要的精力投入到核心內容。更詳細的資料留給各位同學自行搜索補充和閱讀相關書籍和文檔。

2.5.1 什麼是函數

函數是可復用的代碼塊。它們允許你給一塊代碼一個名稱,然後你可以在你的程序的任何地方使用這個名稱任意多次地運行這個代碼塊,這個過程稱之為函數調用。

雖然才正式接觸函數的概念,但是我們已經調用過很多次函數了,比如print。

下面我們來了解下函數的定義。

2.5.2 函數定義

函數通過def關鍵字定義。def關鍵字後跟一個函數的 標識符 名稱,然後跟一對圓括弧。圓括弧之中可以包括一些變數名,該行以冒號結尾。接下來是一塊語句,它們是函數體。下面是一個簡單的示例:

#!/usr/bin/pythondef sayHello(): print Hello World! sayHello()

我們使用def關鍵字定義了一個稱為sayHello的函數。這個函數不使用任何參數,因此在圓括弧中沒有聲明任何變數。函數體調用了print函數列印字元串。最後通過函數名加括弧的方式類調用函數。運行結果如下:

圖2

那麼如何定義和調用帶參數的函數呢?

2.5.3 函數形參

從黑盒的角度看函數,盒子有兩個管道,一個是輸入,一個是輸出,盒子內部是函數體。輸出是返回值,輸入就是函數的參數。

參數在函數定義的圓括弧對內指定,用逗號分割。當我們調用函數的時候,我們以同樣的方式提供值。注意我們使用過的術語——函數中的參數名稱為 形參 而你提供給函數調用的值稱為 實參

看下面的示例:

def printMax(a, b): if a > b: print a, is maximum else: print b, is maximumprintMax(3, 4) x = 5y = 7 printMax(x, y)

這裡,我們定義了一個稱為printMax的函數,這個函數需要兩個形參,叫做a和b。我們使用if..else語句找出兩者之中較大的一個數,並且列印較大的那個數。

在第一個printMax調用中,我們直接把數,即實參,提供給函數。在第二個使用中,我們使用變數調用函數。printMax(x, y)使實參x的值賦給形參a,實參y的值賦給形參b。在兩次調用中,printMax函數的工作完全相同。

運行結果如下:

圖3

2.5.4 局部變數

當你在函數定義內聲明變數的時候,它們與函數外具有相同名稱的其他變數沒有任何關係,即變數名稱對於函數來說是 局部 的。這稱為變數的 作用域 。所有變數的作用域是它們被定義的塊,從它們的名稱被定義的那點開始。

例如:

#!/usr/bin/python def func(x): print x is, x x = 2 print Changed local x to, x x = 50func(x)print x is still, x

在上面這段代碼中,首先函數定義了形參x,相當於函數的局部變數。在函數調用的時候,傳入了外部x,外部x值為50。在函數內部將x值改為2,改變的是局部變數x,外部x不受影響,從最後的輸出結果可以驗證。

圖4

如果你想要為一個定義在函數外的變數賦值,那麼你就得告訴Python這個變數名不是局部的,而是 全局 的。我們使用global語句完成這一功能。沒有global語句,是不可能為定義在函數外的變數賦值的。

例如:

#!/usr/bin/python def func(): global x print x is, x x = 2 print Changed local x to, x x = 50func()print Value of x is, x

global語句被用來聲明x是全局的——因此,當我們在函數內把值賦給x的時候,這個變化也反映在我們在主塊中使用x的值的時候。

運行結果如下:

圖5

2.5.5 默認參數值

對於一些函數,你可能希望它的一些參數是 可選 的,如果用戶不想要為這些參數提供值的話,這些參數就使用默認值。這個功能藉助於默認參數值完成。你可以在函數定義的形參名後加上賦值運算符(=)和默認值,從而給形參指定默認參數值。

例如:

#!/usr/bin/python def say(message, times = 1): print message * times say(Hello)say(World, 5)

名為say的函數用來列印一個字元串任意所需的次數。如果我們不提供一個值,那麼默認地,字元串將只被列印一遍。我們通過給形參times指定默認參數值1來實現這一功能。

在第一次使用say的時候,我們只提供一個字元串,函數只列印一次字元串。在第二次使用say的時候,我們提供了字元串和參數5,表明我們想要列印這個字元串消息5遍。

運行結果如下:

圖6

只有在形參表末尾的那些參數可以有默認參數值,即你不能在聲明函數形參的時候,先聲明有默認值的形參而後聲明沒有默認值的形參。

這是因為賦給形參的值是根據位置而賦值的。例如,

def func(a, b=5)

是有效的,但是

def func(a=5, b)

是 無效 的。

2.5.6 關鍵字傳參

如果你的某個函數有許多參數,而你只想指定其中的一部分,那麼你可以通過命名來為這些參數賦值——這被稱作 關鍵參數 ——我們使用名字(關鍵字)而不是位置(我們前面所一直使用的方法)來給函數指定實參。

這樣做有兩個優勢:

一、由於我們不必擔心參數的順序,使用函數變得更加簡單了。

二、假設其他參數都有默認值,我們可以只給我們想要的那些參數賦值。

例如:

#!/usr/bin/python def func(a, b=5, c=10): print a is, a, and b is, b, and c is, c func(3, 7)func(25, c=24)func(c=50, a=100)

在上面的代碼中,名為func的函數有一個沒有默認值的參數,和兩個有默認值的參數。在第一次使用函數的時候, func(3, 7),參數a得到值3,參數b得到值7,而參數c使用默認值10。在第二次使用函數func(25, c=24)的時候,根據實參的位置變數a得到值25。根據命名,即關鍵參數,參數c得到值24。變數b根據默認值,為5。在第三次使用func(c=50, a=100)的時候,我們使用關鍵參數來完全指定參數值。注意,儘管函數定義中,a在c之前定義,我們仍然可以在a之前指定參數c的值。

運行結果如下:

圖7

2.5.7 RETURN

return語句用來從一個函數返回,即跳出函數。我們也可選從函數返回一個值。

例如:

#!/usr/bin/python def maximum(x, y): if x > y: return x else: return y print maximum(2, 3)

在上面的代碼中,maximum函數返回參數中的最大值,在這裡是提供給函數的數。它使用簡單的if..else語句來找出較大的值,然後返回那個值。

運行結果如下:

圖8

注意,沒有返回值的return語句等價於return None。None是Python中表示沒有任何東西的特殊類型。例如,如果一個變數的值為None,可以表示它沒有值。

除非你提供你自己的return語句,每個函數都在結尾暗含有return None語句。通過運行print someFunction(),你可以明白這一點,函數someFunction沒有使用return語句,如:

def someFunction(): passprint someFunction()

運行結果如下:

圖9

2.5.8 DOCSTRINGS

Python有一個很奇妙的特性,稱為 文檔字元串 ,它通常被簡稱為 docstrings 。DocStrings是一個重要的工具,由於它幫助你的程序文檔更加簡單易懂,你應該盡量使用它。

先看下面的例子,之後在做解釋:

#!/usr/bin/python def printMax(x, y): Prints the maximum of two numbers. The two values must be integers. x = int(x) # convert to integers, if possible y = int(y) if x > y: print x, is maximum else: print y, is maximum printMax(3, 5)print printMax.__doc__

在上面的代碼中,在函數的第一個邏輯行的字元串是這個函數的文檔字元串 。文檔字元串的慣例是一個多行字元串,它的首行以大寫字母開始,句號結尾。第二行是空行,從第三行開始是詳細的描述。 強烈建議你在你的函數中使用文檔字元串時遵循這個慣例。你可以使用__doc__(注意雙下劃線)調用printMax函數的文檔字元串屬性(屬於函數的名稱)。請記住Python把 每一樣東西 都作為對象,包括這個函數。

代碼運行結果如下:

圖10

如果你已經在Python中使用過help(),那麼你已經看到過DocStings的使用了!它所做的只是抓取函數的__doc__屬性,然後整潔地展示給你。

自動化工具也可以以同樣的方式從你的程序中提取文檔。因此,我強烈建議 你對你所寫的任何正式函數編寫文檔字元串。

2.5.9 小結

函數有關的關鍵內容都已經解釋完畢了,下一節為大家介紹模塊。

2.6節《模塊》已經在微信訂閱號搶先發布,心急的同學進入訂閱號(二維碼在下方),從菜單網路安全」—>」Python黑帽編程進入即可。

由於教程仍在創作過程中,在整套教程完結前,感興趣的同學請關注我的微信訂閱號(xuanhun521,下方二維碼),我會第一時間在訂閱號推送圖文教程和視頻教程。問題討論請加qq群:Hacking (1群):303242737 Hacking (2群):147098303。

· 點擊打開二維碼


推薦閱讀:

《機器學習實戰》學習總結(四)——貝葉斯分類
怎樣用五十行Python代碼自造比特幣?
[23] Python模塊和引入
python中的時間處理大總結

TAG:Python | 网络安全 | 玄魂工作室 |