python-函數式編程

# 高階函數: 變量能夠指向函數-> 函數名也是變量:把函數做爲參數傳入,這樣的函數稱爲高階函數,函數式編程就是指這種高度抽象的編程範式。
# *args 和 **kw
# *args是可變參數,args接收的是一個tuple;
# **kw是關鍵字參數,kw接收的是一個dict。
# 以及調用函數時如何傳入可變參數和關鍵字參數的語法:
# 可變參數既能夠直接傳入:func(1, 2, 3),又能夠先組裝list或tuple,再經過*args傳入:func(*(1, 2, 3));
# 關鍵字參數既能夠直接傳入:func(a=1, b=2),又能夠先組裝dict,再經過**kw傳入:func(**{'a': 1, 'b': 2})。
# 使用*args和**kw是Python的習慣寫法,固然也能夠用其餘參數名,但最好使用習慣用法。
 
 
# 1.map
L = [1,2,3,4,5,6,7,8,9]
def f1(x):
    return x ** 2
R = list(map(f1,L)) # 讓map的結果轉換爲list
print("map結果:",R) # == > map結果: [1, 4, 9, 16, 25, 36, 49, 64, 81]

# 1.2 map把元素爲int的轉化爲字符串
S = list(map(str,L))
print("元素類型爲int的轉爲字符串:",S) # == > 元素類型爲int的轉爲字符串: ['1', '2', '3', '4', '5', '6', '7', '8', '9']


# 2.reduce
# 2.1 把序列[1, 3, 5, 7, 9]變換成整數13579
from functools import reduce
def fn(x, y):
    return x * 10 + y
a = reduce(fn, [1, 3, 5, 7, 9])
print("reduce結果爲:",a) # == > reduce結果爲: 13579

# 練習

# 1.利用map()函數,把用戶輸入的不規範的英文名字,變爲首字母大寫,其餘小寫的規範名字。輸入:['adam', 'LISA', 'barT'],輸出:['Adam', 'Lisa', 'Bart']:
def formating(name):
    return name.title()
     
L = list(map(formating,['adam', 'LISA', 'barT']))
print("練習1的答案:",L) # == > 練習1的答案: ['Adam', 'Lisa', 'Bart']

# 2.Python提供的sum()函數能夠接受一個list並求和,請編寫一個prod()函數,能夠接受一個list並利用reduce()求積:
def prod(L1=[]):
    def fn(x,y):
        return x * y
    return reduce(fn,L1)
P = prod([1,2,3,4,5,6,7,8])
print("練習2乘積的答案:",P) # == > 練習2乘積的答案: 40320

# 3.利用map和reduce編寫一個str2float函數,把字符串'123.456'轉換成浮點數123.456

def str2float(s):
    dot = 0
    num = 0
    if "." in s:
        for i,x in enumerate(s):
            if x == ".":
                dot = len(s) - i - 1
                s = s.replace('.','')
                break
    else:
        s = s
    print("s=",s)
    def fn(x,y):
        return x * 10 + y
    def char2num(s):
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
    return reduce(fn,map(char2num,s)) / (10**dot)
A = str2float("123.45")
print("練習3的結果:",A) # == > 練習3的結果: 123.45

# 3.filter:用於過濾序列和map()相似,filter()也接收一個函數和一個序列。和map()不一樣的是,filter()把傳入的函數依次做用於每一個元素,而後根據返回值是True仍是False決定保留仍是丟棄該元素。
def is_odd(n):
    return n % 2 == 1
L1 = list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
print(L1) # ==> [1, 5, 9, 15]

# 3.1 把一個序列中的空字符串刪掉,能夠這麼寫:
def not_empty(s):
    return s and s.strip()
L2 = list(filter(not_empty, ['A', '', 'B', None, 'C', '  '])) # == > # 結果: ['A', 'B', 'C']

# 練習回數是指從左向右讀和從右向左讀都是同樣的數,例如12321,909。請利用filter()濾掉非回數:
def is_palindrome(x):
    if str(x) == str(x)[::-1]: # 本題只須要正順序和反順序相等就知足回數的條件了
        return x 
output = filter(is_palindrome, [x for x in range(1,100)])
print("---->",list(output)) # == > ----> [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99]

# 4.sorted 排序算法
sorter1 = sorted([1,3,6,-20,34])
print("升序排列:",sorter1)
# 4.1 sorted()函數也是一個高階函數,它還能夠接收一個key函數來實現自定義的排序
sorter2 = sorted([1,3,6,-20,-70],key=abs)
print("自定義排序:",sorter2)
sorter2 = sorted([1,3,6,-20,-70],key=abs,reverse=True)
print("自定義反向排序:",sorter2)
# 4.2 字符串排序依照ASCII
sorter3 = sorted(["ABC","abc","D","d"])
print("字符串排序:",sorter3)
# 4.3 忽略大小寫排序
sorter4 = sorted(["ABC","abc","D","d"],key=str.lower)
print("忽略字符串大小寫排序:",sorter4)
# 4.4 要進行反向排序,沒必要改動key函數,能夠傳入第三個參數reverse=True:
sorter5 = sorted(["ABC","abc","D","d"],key=str.lower,reverse=True)
print("忽略字符串大小寫反向排序:",sorter5)

# 練習假設咱們用一組tuple表示學生名字和成績:L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)] 請用sorted()對上述列表分別按名字排序:
L = [('Bob', 75),('Adam', 90), ('Adam', 92), ('Bart', 66), ('Lisa', 88),('Bart', 100), ('Bart', 88)]
print("名字列表L=",L)
def by_name(t):
    return t[0]
L2 = sorted(L, key=by_name)
print("按照名字排序(默認升序,名字相同的狀況下誰的名字在前誰排在前方):",L2) 

# 擴展1:若是名字相同,按照分數排序(默認升序)
def by_name_score(t):
    return (t[0],t[1])
L3 = sorted(L, key=by_name_score)
print("名字相同,按照分數升序排序:",L3)

# 擴展2:若是名字相同,按照分數升序排列
def by_name_score_asc(t):
    return (t[0],t[1])
L4 = sorted(L,key=by_name_score_asc)
print("名字相同,按照分數升序序排列:",L4) # == > [('Adam', 90), ('Adam', 92), ('Bart', 66), ('Bart', 88), ('Bart', 100), ('Bob', 75), ('Lisa', 88)]

from operator import itemgetter, attrgetter

# 擴展3:若是名字相同,按照分數降序排列(答案待補充)
def by_name_score_desc(t):
        return (t[0], t[1])
L4 = sorted(L,key=by_name_score_desc)
print("名字相同,按照分數降序排列(答案待補充):",L4)

# 5.返回函數
# 5.1 不須要馬上求和返回求和的函數:
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum
f = lazy_sum(1, 3, 5, 7, 9)
print("返回函數:",f()) # ==> 25

# 6.匿名函數:lambda
L6 = list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
print("匿名函數:",L6) # ==> [1, 4, 9, 16, 25, 36, 49, 64, 81]

# 7.裝飾器(Decorator):在函數調用先後自動打印日誌,但又不但願修改now()函數的定義,這種在代碼運行期間動態增長功能的方式

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
@log
def now():
    print('2015-3-25')
print("now函數:",now())

def log(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
@log('execute')
def now():
    print('2015-3-25')
print("傳入參數的裝飾器的now函數:",now.__name__)

# 7.偏函數:當函數的參數個數太多,須要簡化時,使用functools.partial能夠建立一個新的函數,這個新函數能夠固定住原函數的部分參數,從而在調用時更簡單
import functools
int2 = functools.partial(int, base=2) # 經過偏函數聲明一個函數名爲int2的函數,實現轉換成int類型而且參數要和base保持一致最後的結果是10進制的類型
print("二進制的數:",int2("1000")) # ==> 8
相關文章
相關標籤/搜索