天天看點

十八、深入Python函數

十八、深入Python函數

「@Author:Runsen」

近來,越來越多人使用函數式程式設計(functional programming)。本文對 Python 中的函數式程式設計技術進行了簡單的入門介紹。

@

  • 入門
  • 函數式程式設計
  • 多态
  • 嵌套函數
  • 函數變量作用域
  • 閉包

Python内置了很多有用的函數,我們可以直接調用。

要調用一個函數,需要知道函數的名稱和參數,比如求絕對值的函數abs,隻有一個參數。

也可以在互動式指令行通過help(abs)檢視abs函數的幫助資訊。

調用abs函數:

>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
           

在Python中的函數就是為了實作某一段功能的代碼段,可以重複利用。

就是以後不要重複造輪子,遇到那個場景就用那個函數,就是函數式程式設計。

下面,我定義一個 my_func,傳入一個Hello World,再列印一個Hello World

def my_func(message):
    print('Got a message: {}'.format(message))

# 調用函數 my_func()
my_func('Hello World')
# 輸出
Got a message: Hello World
           

簡單的知識點

  • def是函數的聲明
  • my_func是函數的名稱
  • message 是函數的參數
  • print 是函數的主體部分
  • 在函數的最後 可以傳回調用結果(return 或yield ),也可以不傳回

「定義在前,調用在後」

def my_sum(a, b):
    return a + b

result = my_sum(3, 5)
print(result)

# 輸出
8

           

對于函數的參數可以設定預設值

def func(param = 0):
    pass
           

如果param沒有傳入,那麼參數預設是0,如果傳入了參數,就覆寫預設值

傳入的參數可以接受任何資料類型

比如,清單

print(my_sum([1, 2], [3, 4]))

# 輸出
[1, 2, 3, 4]

           

再比如,字元串

print(my_sum('hello ', 'world'))

# 輸出
hello world


           

當然,如果參數資料類型不同,而兩者無法相加

print(my_sum([1, 2], 'hello'))
TypeError: can only concatenate list (not "str") to list

           

同一個函數可以應用到整數,清單,字元串等等的操作稱為

多态

。這可不是變态。

函數嵌套就是函數中有函數,就叫嵌套函數了。

def f1():
    print('hello')
    def f2():
        print('world')
    f2()
f1()

# 輸出
hello
world

           

函數的嵌套保證了内部函數的調用,内部函數隻能被外部函數所調用,不會作用于全局域中。

合理使用函數嵌套,提高運算速度

比如計算5的階乘。

def factorial(input):
    
    if not isinstance(input, int):
        raise Exception('input must be an integer.')
    if input < 0:
        raise Exception('input must be greater or equal to 0' )
  
    def inner_factorial(input):
        if input <= 1:
            return 1
        return input * inner_factorial(input-1)
    return inner_factorial(input)


print(factorial(5))

120

           

如果變量是izai函數内部定義的,稱為局部變量,隻在函數内部有效,當函數執行完畢,局部變量就會被回收。

全局變量就是寫在函數外面的。

MIN_VALUE = 1
MAX_VALUE = 10
def validation_check(value):
    if value < MIN_VALUE or value > MAX_VALUE:
        raise Exception('validation check fails')

           

這裡的MIN_VELUE 和MAX_VALUE就是全局變量,但是我們不能在函數的内部随意改變全局變量的值

MIN_VALUE = 1
def validation_check(value):
    MIN_VALUE += 1
    
validation_check(5)

報錯:UnboundLocalError: local variable 'MIN_VALUE' referenced before assignment

           

要想改變  必須加上global這個聲明

MIN_VALUE = 1
def validation_check(value):
    global MIN_VALUE  
    MIN_VALUE += 1
    
validation_check(5)

           

global告訴python解析器,函數内部的變量MIN_VALUE就是定義的全局變量,這裡輸入的是2,這樣修改的全局變量的值

MIN_VALUE = 1
MAX_VALUE = 10
def validation_check():
    MIN_VALUE = 3
    print(MIN_VALUE)
validation_check()
print(MIN_VALUE)


# 3
# 1
           

對于嵌套函數來說,内部函數無法修改外部函數定義的變量,可以通路,想要修改就要加上 nonolocal

def outer():
    x = "local"
    def inner():
        nonlocal x # nonlocal 關鍵字表示這裡的 x 就是外部函數 outer 定義的變量 x
        x = 'nonlocal'
        print("inner:", x)
    inner()
    print("outer:", x)
outer()
# 輸出
inner: nonlocal
outer: nonlocal

           

不加就不會覆寫

def outer():
    x = "local"
    def inner():
        x = 'nonlocal' # 這裡的 x 是 inner 這個函數的局部變量
        print("inner:", x)
    inner()
    print("outer:", x)
outer()
# 輸出
inner: nonlocal
outer: local

           

函數的閉包其實和函數的嵌套很相似。和嵌套不同,閉包的外部函數傳回是一個函數,而不是一個具體的值。

閉包就是在函數裡面調用函數,一般用return來執行,return出内部調用的函數名。

我們接下來計算下一個數的n次幂,用閉包寫如下:

def nth_power(exponent):
    def exponent_of(base):
        return base ** exponent
    return exponent_of # 傳回值是 exponent_of 函數

square = nth_power(2) # 計算一個數的平方
cube = nth_power(3) # 計算一個數的立方 
square
# 輸出
<function __main__.nth_power.<locals>.exponent(base)>

cube
# 輸出
<function __main__.nth_power.<locals>.exponent(base)>

print(square(2))  # 計算 2 的平方
print(cube(2)) # 計算 2 的立方
# 輸出
4 # 2^2
8 # 2^3

           

當然,我們也可以通過一個函數來寫這個功能:

def nth_power(base,exponent):
    return base**exponent  
           

但是,使用閉包,可以讓程式變得更加簡潔易懂。

本文已收錄 GitHub,傳送門~[1] ,裡面更有大廠面試完整考點,歡迎 Star。

Reference

[1]

傳送門~:https://github.com/MaoliRUNsen/runsenlearnpy100