Python之高級函數-高級程序員與普通程序員的區別

目錄

python的高階函數

1、假如你想從一個考試分數的列表中刪除所有的0分,怎麼辦?

普通程序員:

高級程序員:

2、filter函數

3、給定一個數列[1,3,5,6,7,9,10,435],求數列中每一項相乘的結果

普通程序員

高級程序員:

4、函數的遞歸和嵌套

通過生成菲波那切數列來演示:


python的高階函數

1、假如你想從一個考試分數的列表中刪除所有的0分,怎麼辦?

普通程序員:

第一步:定義一個函數

def remove_zero(yourList):
    newlist = []
    for number in yourList:
        if number > 0:
            newlist.append(number)
    return newlist

第二步:在用到該功能的地方調用之

if __name__ == '__main__':
    mylist = [12,4,0,23]
    print(remove_zero(mylist))

高級程序員:

只有一步,直接上lambda表達式

if __name__ == '__main__':
    mylist = [12,4,0,23]
    new_l =  list(filter(lambda number: number > 0, mylist))
    print(new_l)

科普一下,lambda表達式。

lambda表達式不是python的獨有武功,java8中也有。說簡單點就是你可以把一個匿名函數作爲參數傳遞給另一個函數(方法)。在Python中Lambda的語法是這樣的:

lambda <argument list> : <expression>

java8中lambda表達式的語言是這樣的:

(parameters) -> expression

沒有比較就沒有傷害,python的寫法依舊是延用":",而且前面的lambda是必須有的,否者會報錯。

2、filter函數

filter(isPositive,oldList), 該函數接受2個參數,第一個參數接受一個布爾函數,第二個參數接受一個可迭代對象。所以我們可以給filter函數傳入一個lambda表達式。

lambda number: number > 0

filter函數的源代碼:

class filter(object):
    """
    filter(function or None, iterable) --> filter object
    
    Return an iterator yielding those items of iterable for which function(item)
    is true. If function is None, return the items that are true.
    """
    def __getattribute__(self, *args, **kwargs): # real signature unknown
        """ Return getattr(self, name). """
        pass

    def __init__(self, function_or_None, iterable): # real signature unknown; restored from __doc__
        pass

    def __iter__(self, *args, **kwargs): # real signature unknown
        """ Implement iter(self). """
        pass

    @staticmethod # known case of __new__
    def __new__(*args, **kwargs): # real signature unknown
        """ Create and return a new object.  See help(type) for accurate signature. """
        pass

    def __next__(self, *args, **kwargs): # real signature unknown
        """ Implement next(self). """
        pass

    def __reduce__(self, *args, **kwargs): # real signature unknown
        """ Return state information for pickling. """
        pass

可迭代對象的每一項都傳遞給布爾函數,如果該函數返回True,這一項就保留在返回的可迭代對象中;否則的話,刪除該項。

 

3、給定一個數列[1,3,5,6,7,9,10,435],求數列中每一項相乘的結果

普通程序員

第一步:定義一個方法

def list_element_multiplication(oldList):
    ret=1
    for e in oldList:
        ret *= e
    return ret

第二步:調用這個方法

    # 第一種方法 定義一個函數
    list1=[1,2,3,4,5]
    print(list_element_multiplication(list1))

高級程序員:

    # 第二種方法
    print(functools.reduce(lambda x,y: x*y, list1))

 高級程序員熟悉python的內建模塊和常用的方法,所以他已經將問題與functools.reduce方法相聯繫,傳入lambda表達式和用戶列表就輕鬆完成了工作。

4、函數的遞歸和嵌套

通過生成菲波那切數列來演示:

# 菲波那切數列 演示函數的遞歸調用和函數嵌套
def fibonacci(n, product = 1):
    if n == 1:
        return product
    elif n == 2:
        return product
    else:           # 函數的遞歸調用
        return fibonacci(n - 1) + fibonacci(n - 2)


def fibonacci_sequence(n):
    f_sequence = []
    for x in range(1,n):
        f_sequence.append(fibonacci(x))     # 函數的嵌套
    return f_sequence


if __name__ == '__main__':
    print(fibonacci_sequence(10))

非遞歸方式生成斐波那契額數列:

# 非遞歸條用實現斐波那契額數列
def fib(n):
    sum = 1
    first = 1
    second = 1
    count =3
    while count <= n:
        sum = first + second
        first = second
        second = sum
        count +=1
    return sum


def fib_sequence(n):
    fib_s_list = []
    for y in range(1,n):
        fib_s_list.append(fib(y))
    return fib_s_list

if __name__ == '__main__':
        print(fib_sequence(10))
    

總結:遞歸方式生成斐波那契數列代碼簡單,而且優雅,但是存在一個嚴重的問題,該算法的複雜度是指數階的。當問題規模比較大時,該算法性能非常差勁。所以計算機科學家設計了另一類實現算法,不需要採用遞歸的方式進行,該算法的複雜度是線性階的。

測試:

import time


# 菲波那切數列 演示函數的遞歸調用和函數嵌套
def fibonacci(n, product = 1):
    if n == 1:
        return product
    elif n == 2:
        return product
    else:           # 函數的遞歸調用
        return fibonacci(n - 1) + fibonacci(n - 2)


def fibonacci_sequence(n):
    start = time.time()
    f_sequence = []
    for x in range(1,n):
        f_sequence.append(fibonacci(x))     # 函數的嵌套
    end = time.time() - start
    print(end)
    return f_sequence


# 非遞歸條用實現斐波那契額數列
def fib(n):
    sum = 1
    first = 1
    second = 1
    count =3
    while count <= n:
        sum = first + second
        first = second
        second = sum
        count +=1
    return sum


def fib_sequence(n):
    start = time.time()
    fib_s_list = []
    for y in range(1,n):
        fib_s_list.append(fib(y))
    end = time.time() - start
    print(end)
    return fib_s_list

if __name__ == '__main__':
    print(fibonacci_sequence(10))
    print(fib_sequence(10))

5.316734313964844e-05
[1, 1, 2, 3, 5, 8, 13, 21, 34]
2.09808349609375e-05
[1, 1, 2, 3, 5, 8, 13, 21, 34]

當問題規模是10,遞歸調用所耗費的時間就已經是非遞歸調用的2倍多;

當問題規模是40是,測試結果如下:

63.553478956222534
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986]
8.20159912109375e-05
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986]

這性能差別也太大了,記住指數級別的增長確實是非常厲害的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章