1. 程式人生 > >python學習筆記(二)---高階特性

python學習筆記(二)---高階特性

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

r'''
    高階知識
    lrn_higher_list: 切片、迭代、列表生成式、生成器、迭代器
    lrn_higher_func: 函數語言程式設計,修飾器、匿名函式、篩選器等
'''

__author__ = 'Kingrumn'

'''
    第1行和第2行是標準註釋,第1行註釋可以讓這個.py檔案直接在Unix/Linux/Mac上執行,第2行註釋表示.py檔案本身使用標準UTF-8編碼;

    第4行是一個字串,表示模組的文件註釋,任何模組程式碼的第一個字串都被視為模組的文件註釋;

    第10行使用__author__變數把作者寫進去,這樣當你公開原始碼後別人就可以瞻仰你的大名;
'''
from collections import Iterable from collections import Iterator from functools import reduce import functools # 高階特性--切片、迭代、列表生成式、生成器、迭代器 def lrn_higher_list(): # 切片Slice lst = list(range(100)) # 取前N個元素,也就是索引為0-(N-1)的元素 # list[a:b:c]: c>0, a<b; c<0, a>b, >指位置靠後 print(lst[0
:3]) # [0, 1, 2] print(lst[:3]) # [0, 1, 2] # 後N個元素 print(lst[-2:]) # [98, 99] # 帶步長取 print(lst[10:20:2]) # [10, 12, 14, 16, 18] print(lst[::15]) # [0, 15, 30, 45, 60, 75, 90] # 逆序取列表 print(lst[20:10:-2]) # [20, 18, 16, 14, 12] print(lst[-10:80:-2]) # [20, 18, 16, 14, 12]
# 迭代 # dict迭代方法 d = {"a": 1, "b": 2, "c": 3} # 按key迭代 for key in d: print(d[key]) # 按value迭代 for value in d.values(): print(value) # 同時迭代 for k, v in d.items(): print(k, v) # 判斷物件是否可迭代 # from collections import Iterable print(isinstance('abc', Iterable)) # enumerate可將list變為索引-元素對 for k, v in enumerate(['a', 'b', 'c']): print(k, v) # 列表生成式List Comprehensions # range: range(start, stop[, step]) print(list(range(1, 11, 2))) # [1, 3, 5, 7, 9] print([x * x for x in range(1, 5)]) # [1, 4, 9, 16] print([x * x for x in range(1, 11) if x % 2 == 0]) # [4, 16, 36, 64, 100] print([m + n for m in 'ABC' for n in 'XYZ']) # ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'] d = {'x': '1', 'y': '2'} print([k + '=' + v for k, v in d.items()]) # ['x=1', 'y=2'] lst = ['A', 'B', 'C'] print([s.lower() for s in lst]) # ['a', 'b', 'c'] # 生成器 # 在迴圈的過程中不斷推算出後續的元素,不必建立完整的list # 一邊迴圈一邊計算的機制,稱為生成器:generator # 方法一:列表生成式的[]改成() lst = (x * x for x in range(10)) print(lst) # <generator object lrn_higher.<locals>.<genexpr> at 0x0322C8B0> print(next(lst)) # 0 print(next(lst)) # 1 print(next(lst)) # 4 # 沒有更多的元素時,丟擲StopIteration的錯誤 # generator也是可迭代物件, 用for迴圈才是正確的做法 for n in lst: print(n) # 方法二:利用yield 構造; # 一個函式定義中包含yield關鍵字,那麼這個函式就不再是一個普通函式,而是一個generator # 函式是順序執行,遇到return語句或者最後一行函式語句就返回; # 而變成generator的函式,在每次呼叫next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行; # 用for迴圈呼叫generator時,發現拿不到generator的return語句的返回值, # 如果想要拿到返回值,必須捕獲StopIteration錯誤,返回值包含在StopIteration的value中 # 斐波那契數列 def fib(m): n, a, b = 0, 0, 1 while n < m: yield b a, b = b, a + b n = n + 1 return 'done' next(fib(10)) # 楊輝三角 print(u"楊輝三角") def yt(): a = [1] yield a b = [1, 1] yield b while True: index = 0 a = b b = [1, 1] while index < len(a) - 1: at = a[index] + a[index+1] b.insert(-1, at) index += 1 yield b n = 0 results = [] for t in yt(): print(t) results.append(t) n = n + 1 if n == 10: break # 迭代器 # 可以被next()函式呼叫並不斷返回下一個值的物件稱為迭代器:Iterator # 可以使用isinstance()判斷一個物件是否是Iterator物件 # 生成器都是Iterator物件,但list、dict、str雖然是Iterable,卻不是Iterator # 可以使用iter()函式把list、dict、str等Iterable變成Iterator print(isinstance((x for x in range(10)), Iterator)) # True print(isinstance(iter([]), Iterator)) # True print(isinstance([], Iterator)) # False # 函數語言程式設計 def lrn_higher_func(): def p(x): return x def pa(x): return -x # 變數可以指向函式 f = p(-10) print(f) # -10 f = p print(f) # <function lrn_function_higher.<locals>.p at 0x036348E8> # 函式名也是變數,可以進行賦值,這麼做是危險的 print(pa(-10)) # 10 pa = p print(pa(-10)) # -10 # 高階函式 # 一個函式就可以接收另一個函式作為引數,這種函式就稱之為高階函式 def add(x, y, func): return func(x) + func(y) print(add(-5, 4, abs)) # 9 # map # map()函式接收兩個引數,一個是函式,一個是Iterable # map將傳入的函式依次作用到序列的每個元素,並把結果作為新的Iterator返回 def f(x): return x * x r = map(f, [1, 2, 3, 4, 5]) print(list(r)) # [1, 4, 9, 16, 25] print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))) # ['1', '2', '3', '4', '5', '6', '7', '8', '9'] # reduce # reduce把一個函式作用在一個序列[x1, x2, x3, ...]上,這個函式必須接收兩個引數,reduce把結果繼續和序列的下一個元素做累積計算 # from functools import reduce def add(a, b): return a * 10 + b print(reduce(add, [1, 3, 5, 7, 9])) # 13579 digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9} def char2num(s): return digits[s] # str2int 函式: ’13579‘ ---> 13579 def str2int(s): def fn(x, y): return x * 10 + y return reduce(fn, map(char2num, s)) print(str2int('13579')) # 13579 # 用lambda函式簡化寫法 def str2int(s): return reduce(lambda x, y: x * 10 + y, map(char2num, s)) print(str2int('13579')) # 13579 # str2float def str2float(s): index = s.find('.') return reduce(lambda x, y: x * 10 + y, map(char2num, s[:index])) \ + reduce(lambda x, y: x * 0.1 + y, map(char2num, s[-1:index:-1]+'0')) print(str2float('0.123')) # filter # filter()也接收一個函式和一個序列 # filter()把傳入的函式依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素 # filter()函式返回的是一個Iterator def is_odd(x): return x % 2 == 1 print(list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))) # [1, 5, 9, 15] # 利用埃氏篩法求所有素數 # 依次從第一個篩掉所有能被整除的數 def odd_iter(): n = 1 while True: n += 2 yield n def not_divisible(n): return lambda x: x % n > 0 # 此處返回的是個函式 def primes(): yield 2 it = odd_iter() # 初始序列 while True: n = next(it) # 返回序列的第一個數 yield n it = filter(not_divisible(n), it) # 構造新序列 mn = 0 ml = [] for i in primes(): ml.append(i) mn += 1 if mn > 10: break print(ml) # sorted # 可以對list進行排序 # sorted()函式也是一個高階函式,它還可以接收一個key函式來實現自定義的排序 ''' sorted(iterable[, cmp[, key[, reverse]]]),後面的可選引數為命名關鍵字引數 iterable -- 可迭代物件。 cmp -- 比較的函式,這個具有兩個引數,引數的值都是從可迭代物件中取出,此函式必須遵守的規則為,大於則返回1,小於則返回-1,等於則返回0 key - - 主要是用來進行比較的元素,只有一個引數,具體的函式的引數就是取自於可迭代物件中,指定可迭代物件中的一個元素來進行排序。 reverse -- 排序規則,reverse = True 降序 , reverse = False 升序(預設)。 返回重新排序的列表, 保持原列表不變 ''' print(sorted([36, 5, -12, 9, -21], key=abs)) # 函式作為返回值 def lazy_sum(*args): def s(): ax = 0 for n in args: ax = ax + n return ax return s f1 = lazy_sum(1, 3, 5, 7, 9) f2 = lazy_sum(1, 3, 5, 7, 9) print(f1 == f2) # 此時才真正進行計算 # 閉包 # 返回函式不要引用任何迴圈變數,或者後續會發生變化的變數。 def count(): def func(j): def g(): return j * j return g fs = [] for i in range(1, 4): fs.append(func(i)) # func(i)立刻被執行,因此i的當前值被傳入func() return fs f1, f2, f3 = count() print(f1()) # 1 print(f2()) # 4 print(f3()) # 9 # 匿名函式 # 函式沒有名字,不必擔心函式名衝突 # 也可以把匿名函式賦值給一個變數,再利用變數來呼叫該函式 def build(x, y): return lambda: x * x + y * y print(build(1,2)()) # 裝飾器 # 函式有個內建的__name__屬性,可以拿到函式的名字 # decorator就是一個返回函式的高階函式 def log(func): @functools.wraps(func) # functools模組,用於修改wrapper的__name__為func.__name__ def wrapper(*args, **kw): print('call %s():' % func.__name__, end=' ') # 增加end=''防止換行 return func(*args, **kw) return wrapper @log # 相當於執行了now = log(now) def now(): print('2015-3-25') now() # call now(): 2015-3-25 # 偏函式 # 把一個函式的某些引數給固定住(也就是設定預設值),返回一個新的函式,呼叫這個新函式會更簡單 # import functools # functools.partial int2 = functools.partial(int, base=2) print(int2('1010101')) # 85 # main ''' 當我們在命令列執行hello模組檔案時,Python直譯器把一個特殊變數__name__置為__main__, 而如果在其他地方匯入該hello模組時,if判斷將失敗, 因此,這種if測試可以讓一個模組通過命令列執行時執行一些額外的程式碼,最常見的就是執行測試 ''' if __name__ == "__main__": lrn_higher_list() lrn_higher_func()

更多更及時的部落格更新請戳—> KingRumn