Python函數

0x01 什麼是函數

函數就是一段代碼裡面可重複使用的部分,我們在寫程式的時候常常都會遇到一些需要重用的功能,若將其功能寫成一個函數,那我們就不必要寫多一次該代碼,只需直接套用該函數就可以了。

0x02 函數的定義規則

  • 以def關鍵字眼為開頭,後面接的是你要定義的函數名稱和圓括號()。
  • 任何在這函數裡面會出現的參數和自變量需放在圓括號裡面,因為裡面是讓你來定義參數的。
  • 函數第一行可以選擇性使用文檔字符串對所存放的函數加以說明。
  • 函數內容會以冒號:開始並且在下一行後開始縮進。
  • return [表達式] 代表你會結束該函數,選擇性地返回一個數值給調用方,若沒有表達式return就是說你返回的是None。

格式

1
2
def 函數名(参數列表):
函數体

0x03 例子

比如說我們要生成一個有指定邊界的斐波那契數列的函數:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> def fib(n): # write Fibonacci series up to n
... """Print a Fibonacci series up to n."""
... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> def fib(n): # write Fibonacci series up to n

>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

在上述的函數裡面,所有變量的賦值會存在局部符號表(Local Symbol Table)裡面。變量引用會先檢查局部符號表,接著就是包含函數的局部符號表,跟在後面是全局符號表,最後則是內置名字表。因此,全局變量是不能直接在函數裡面賦值(要用global語句來命名)。

一個函數定義會在當前的符號表裡面引入函數名字。而函數名字的值(函數體)會被Python的解釋器認為是用戶自定義的類型,之後可賦予其他的名字(變量名字以及被當作其他函數來使用。

比如說這樣:

1
2
3
4
5
>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

0x04 深入了解如何定義函數

現在我們就可以開始深入了解3種形式的函數使用方式。方式有這3種類型:

  • 默認參數
  • 關鍵字參數
  • 可變參數列表
  • Lambda形式

默認參數

在Python裡面最常見的默認函數的形式多數含有一個或多個的實際參數,這使到該函數在被呼叫的時候可以使用更少已被定義的實際函數。我們來看看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
while True:
ok = 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 OSError('uncooperative user')
print(complaint)

此函數的調用方式:

  • 只給出必要的参數ask_ok('Do you really want to quit?')
  • 給出一個可選的参數ask_ok('OK to overwrite the file?', 2)
  • 給出所有的參數ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

調用函數的時候,如果沒有傳遞參數,也會使用默認的參數。以下是沒有傳入參數的實際例子。

1
2
3
4
5
6
def printinfo(name,age = 24):
print("Name: ", name)
print("Age: ", age)
return

printinfo(age = 10,name="Bean Bean")

關鍵字參數

也可以把函數裡面的參數設定成某個固定的關鍵字來進行調用(Keyword = Value)。

例子:

1
2
3
4
5
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")

在這例子裡面,可以接受一個必選參數 (voltage) 以及三個可選參數 (state, action, 和 type)。可以用以下任何一個方法來進行調用:

1
2
3
4
5
6
parrot(5000)                                          # 1 positional argument
parrot(voltage=5000) # 1 keyword argument
parrot(voltage=5000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=5000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword

那麼無效的調用例子又是怎樣的呢?

1
2
3
4
parrot()                     # required argument missing
parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor='John Cleese') # unknown keyword argument

另外,關鍵字的參數也必須跟隨在位置參數的後面。在傳遞期間,所有的關鍵字參數必須與函數可接受的某個參數互相匹配。而且任何参数都不可以多次赋值。下面的示例由于這種限制而無法呼叫該函數:

1
2
3
4
5
6
7
>>> def function(a):
... pass
...
>>> function(0, a=0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: function() got multiple values for keyword argument 'a'

在函數調用期間,關鍵字函數可以被使用來確定傳入的參數值。另外調用時候參數的順序與聲明時不一致也沒關係,因為Python解釋器會自動匹配相關參數值。

來看下這個程式:

1
2
3
4
5
6
7
8
9
10
11
#可以解釋函數
def printme(str):
"Print any entered String"
print (str);
return;

#调用printme函數
printme(str = "Pikachu is cute!");

結果
Pikachu is cute!

暫時沒用

在你引入一個像**name的參數時候,它會接收一個字典 Maping Types - dict。該字典包含了所有未出現在形式參數列表中的關鍵字參數。著

该字典包含了所有未出现在形式参数列表中的关键字参数。这里可能还会组合使用一个形如 name (下一小节详细介绍) 的形式参数,它接收一个元组(下一节中会详细介绍),包含了所有没有出现在形式参数列表中的参数值( name 必须在 **name 之前出现)。 例如,我们这样定义一个函数:

1
2
3
4
5
6
7
8
9
def cheeseshop(kind, *arguments, **keywords):
print("-- Do you have any", kind, "?")
print("-- I'm sorry, we're all out of", kind)
for arg in arguments:
print(arg)
print("-" * 40)
keys = sorted(keywords.keys())
for kw in keys:
print(kw, ":", keywords[kw])

可變參數列表

讓函數調用可變個數的參數。這些參數會被包裝進一個元組。

1
2
3
4
5
6
7
8
9
10
11
def write_multiple_items(file, separator, *args):
file.write(separator.join(args))

"""出現在 *args 後面的參數是關鍵字參數"""
>>> def concat(*args, sep="/"):
... return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'

lambda 函數

【暫時沒有用到】

  • 參數列表的分析
  • 函數註解

參考網站

http://www.runoob.com/python3/python3-function.html
http://docs.pythontab.com/python/python3.4/controlflow.html#tut-functions

0%