建立函數(shù)抽象

什么是好的抽象?

比如這樣一個(gè)函數(shù):

def accumulate(combiner, base, n, term):
    total, k=base, 1
    while k<=n:
        total,k = combiner(total, term(k)), k+1
    return total

利用這個(gè)函數(shù)能夠構(gòu)建出不同的符合這個(gè)抽象的函數(shù)。

比如 將0-x間的不同特征的數(shù)相加:

term函數(shù)可以是平方,立方
def summation_using_accumulate(n, term):
    return accumulate(add, 0, n, term)

相乘:

def product_using_accumulate(n, term):
    return accumulate(mul, 1, n, term)

將0-x間的數(shù)過(guò)濾出來(lái)相加可以這樣子做:

def filtered_accumulate(combiner, base, pred, n,term):
    def combiner_if(x,y):
        if pred(y):
            return combiner(x,y)
        else:
            return x
    return accumulate(combiner_if, base, n, term)

利用一個(gè)高階函數(shù),pred是過(guò)濾的規(guī)則
比如只要偶數(shù)
odd = lambda x: x%2==1
filtered_accumulate(add, 0, odd, x, term)

再比如對(duì)一個(gè)函數(shù)多次調(diào)用

repeated(square, 2)(5) = square(square(5))
利用高階函數(shù)能夠很簡(jiǎn)單實(shí)現(xiàn)。
def repeated(f, n):
    def inner(x):
        nonlocal n
        if n == 0:
            return x
        result = x
        while n > 0:
            result = f(result)
            n -= 1
        return result
    return inner
但是仔細(xì)想想,似乎能夠用上面的那個(gè)函數(shù)來(lái)寫(xiě) 可以這樣做:
定義一個(gè)高階函數(shù)
def compose(f, g):
    def h(x):
        return f(g(x))
    return h
def repeated(f, n):
    return accumulate(compose, lambda x:x, n,lambda k:f)

發(fā)現(xiàn) 要進(jìn)行0-n次term計(jì)算,用compose來(lái)組合起來(lái) 都可以用accumuldate這個(gè)抽象
比如上面這個(gè)例子 對(duì)x進(jìn)行term計(jì)算,然后組合.

lambda 表達(dá)式,注意它是運(yùn)行時(shí)綁定的。

>>> a=3
>>> b=2
>>> c = lambda a,b:a+b
>>> b-=a
>>> c(a,b)
2

遞歸:

以常見(jiàn)的斐波那契數(shù)列來(lái)說(shuō)
樹(shù)形遞歸,復(fù)雜度最高,有很多的重復(fù)計(jì)算。
從f(1)=1開(kāi)始的。
def fib(n):
    if n<2:
        return n
    return fib(n-1)+fib(n-2)
我們可以這樣子寫(xiě),利用數(shù)來(lái)保存中間變量,不用重復(fù)計(jì)算。
def fib2(a,b,n):
    if n > 0:
        return fib2(b,a+b,n-1)
    return a

裝飾器:

@decorator
def func
相當(dāng)于decorator(func)
能夠用裝飾器做很多事情。比如:
定義一個(gè)memo緩存函數(shù),來(lái)優(yōu)化上面的fib
def memo(f):
    cache = {}
    def helper(*args):
        if args not in cache:
            cache[args]=f(args)
        return cache[args]
    return helper
利用了一個(gè)緩存來(lái)保存變量。

總結(jié) 要多思考建立好的函數(shù)抽象。

函數(shù)編碼原則:

  1. 函數(shù)名 稱應(yīng) 該小寫(xiě) , 以下劃 線分隔。 提倡描述性的名 稱。
  2. 函數(shù)名 稱通常反映解釋器 向參數(shù)應(yīng) 用 的操作( 例如 print 、 add 、 square ) , 或者結(jié)
    果( 例 如 max 、 abs 、 sum ) 。
  3. 參數(shù)名 稱應(yīng) 小寫(xiě) , 以下劃 線分隔。 提倡單個(gè)詞的名 稱。
  4. 參數(shù)名 稱應(yīng) 該反映參數(shù)在函數(shù)中 的作用 , 并不僅僅是滿足的值的類型 。
  5. 當(dāng) 作用 非常明 確時(shí), 單個(gè)字母的參數(shù)名 稱可以接受, 但是永遠(yuǎn)不要使用 l ( 小寫(xiě) 的 L )
    和 O ( 大寫(xiě) 的 o ) , 或者 I ( 大寫(xiě) 的 i ) 來(lái)避免和數(shù)字混淆。

函數(shù)設(shè)計(jì)原則

一個(gè)函數(shù)只完成一個(gè)功能,遵循dry原則。
寫(xiě)函數(shù)幫助文檔,利用doctest進(jìn)行測(cè)試。
調(diào)試的一些原則:
逐步測(cè)試,隔離錯(cuò)誤,追蹤到最小的代碼片。檢查假設(shè)。

來(lái)自http://www.97up.cn/post/83

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容