Python學習(四)

高階函數

把函數作為參數傳入,這樣的函數稱為高階函數

from math import sqrt

def test(x, *func):
    ret = list(f(x) for f in func)
    return ret

print(test(4, abs, sqrt))       # [4, 2.0]

map函數

map函數接收兩個參數,第一個是一個函數,第二個是Iterable,map將傳入的函數依次作用到Iterable中的每個元素,并把結果作為新的Iterator返回

# 將名字變為首字母大寫,其他小寫
def test(elem):
return elem.capitalize()

print(list(map(test, ['adam', 'LISA', 'barT'])))        # ['Adam', 'Lisa', 'Bart']

reduce函數

reduce函數接收兩個參數,第一個是一個函數,第二個是一個序列,reduce將傳入的函數依次作用到Iterable中的每個元素,并把每一個元素的結果與下一個元素作累積計算

from functools import reduce

def str2int(s):
    def char2num(c):
        # 根據dict中的key來獲取value
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[c]

    def f(x, y):
        return x * 10 + y

    return reduce(f, map(char2num, s))


print(str2int("13579"))             # 13579
print(type(str2int("13579")))       # <class 'int'>

上面是我們自己寫的一個str轉int的函數,雖然系統給我們提供了。我們還可以寫一個str轉float的函數來加強reduce與map的理解

def str2float(s):
    # 獲取小數點的位置
    point = s.index(".")
    # 整數部分
    num1 = map(int, s[:point])
    # 小數部分
    num2 = map(int, s[point + 1:])
    # 算出小數有多少位
    num3 = 1 / 10 ** len(s[point + 1:])

    def f(x, y):
        return x * 10 + y

    return reduce(f, num1) + reduce(f, num2) * num3


print(str2float("126.789"))                 # 126.789
print(type(str2float("126.789")))           # <class 'float'>

filter函數

filter()也接收一個函數和一個序列,把傳入的函數依次作用于每一個序列的元素,然后根據返回值是True還是False來決定保留還是丟棄該元素。filter()函數返回的是一個Iterator

def func(elem):
return elem % 2 == 0


print(list(filter(func, list(range(1, 11)))))       # [2, 4, 6, 8, 10]

sorted函數

sorted()可以對一個序列進行排序,也可以接收一個key來實現自定義的排序

l = [36, 5, -12, 9, -21]
print(sorted(l))                            # [-21, -12, 5, 9, 36]  從小到大
print(sorted(l, reverse=True))            # [36, 9, 5, -12, -21]    從大到小
print(sorted(l, key=abs))                  # [5, 9, -12, -21, 36]   按絕對值的大小排序

對字符串進行排序。對字符串排序是按照ASCII大小比較的,由于'Z'<'a',大寫字母Z會排在小寫字母a的前面,所以可以過字符串的lower方法將先把字符串都變成小寫(也可以都變成大寫),再比較

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88), ('Zoo', 40)]
def by_name(item):
    return item[0].lower()
print(sorted(L, key=by_name))       # [('adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Zoo', 40)]

返回函數

上面學習了將函數作為參數的高階函數,也可以把函數作為結果值返回

def test(*args):
    def f():
        ret = 0
        for item in args:
            ret += item
        return ret
    return f
result = test(1, 3, 5, 7, 9)
# 返回回來的是一個函數,必須調用才能獲取到返回值
print(result())         # 25
print(result)           # <function test.<locals>.f at 0x101a7ac80>

我們在函數test中定義了函數f,內部函數f可以引用外部函數test的的參數和局部變量;當函數test返回函數f時,相關參數和變量都保存在返回的函數中,這種稱為閉包(Closure)。但這里有一個問題需要注意:

def test2():
    fs = []
    for i in range(1, 4):
        def f():
            return i * i

        fs.append(f)
    return fs
f1, f2, f3 = test2()
print(f1())     # 9
print(f2())     # 9
print(f3())     # 9

這里的結果為什么都是9?

原因在于返回的函數引用了變量i,但它并非立即執行,等到3個函數都返回時,它們所引用的變量i已經變成了3,因此最終結果都是9。

所以,返回閉包時牢記一點:返回函數不要引用任何循環變量,或者后續會發生變化的變量

若一定要引用循環變量怎么辦呢?可以這樣做:

def test3():
    fs = []

    def f(x):
        def g():
            return x * x

        return g

    for i in range(1, 4):
        fs.append(f(i))         # f(i)立即被執行,因此當前i的值被傳入到f()函數中
    return fs
f4, f5, f6 = test3()
print(f4())         # 1
print(f5())         # 4
print(f6())         # 9

重新創建了一個函數,用該函數的參數與循環變量當前的值進行綁定,無論后緒循環變量如何變,已綁定的函數參數的值不變

匿名函數

結構:

lambda 參數名 : 表達式    或者  lambda : 表達式

如:

print(list(map(lambda x: x * x, [1, 2, 3])))        # [1, 4, 9]
def test(x, y):
    return lambda: x + y
print(test(1, 2)())                              # 3

裝飾器

在代碼運行期間動態增加功能的方式稱之為裝飾器(Decorator)

# 調用函數time時,輸出log日志

import functools

def log(func):
    # 把原始函數的__name__等屬性復制到wrapper()函數中,否則返回出去的__name__屬性值為wrapper
    @functools.wraps(func)      
    def wrapper(*args, **kw):
        print("call %s():" % func.__name__)
        return func(*args, **kw)

    return wrapper
    
# 這里相當于執行:time = log(time)    
@log 
def time():
    print("2017-2-5")
       
time()                  # call time():  2017-2-5
print(time.__name__)      # time

自定義一個輸出log文本的裝飾器

def log2(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print("%s ,%s():" % (text, func.__name__))
            return func(*args, **kw)

        return wrapper

    return decorator

# 這里相當于執行:time2 = log("execute")(time2)
@log2("execute")   
def time2():
    print("2017-1-5")
    
time2()                 # execute ,time2(): 2017-1-5
print(time2.__name__)     # time2

首先執行的是log("execute"),返回decorator,再調用返回的函數,參數就是time2,返回值最終是wrapper函數

偏函數

在學習函數參數類型的時候,為了降低函數的調用難度,我們可以設置默認參數。而偏函數也可以做到。
偏函數的作用就是:把一個函數的某些參數給固定住(也就是設置默認值),返回一個新的函數,調用這個新函數會更簡單

def test(x, sqrt=2):
return x ** sqrt

test2 = functools.partial(test, sqrt=3)
print(test2(3))         # 27
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容