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)
>>> f()
注意到返回的函式在其定義內部引用了區域性變數如果一定要引用迴圈變數怎麼辦?方法是再建立乙個函式,用該函式的引數繫結迴圈變數當前的值,無論該迴圈變數後續如何更改,已繫結到函式引數的值不變:args
,所以,當乙個函式返回了乙個函式後,其內部的區域性變數還被新函式引用,所以,閉包用起來簡單,實現起來可不容易。返回閉包時牢記一點:返回函式不要引用任何迴圈變數,或者後續會發生變化的變數。
def count():
def f(j):
def g():
return j*j
return g
fs =
for i in range(1, 4):
return fs
1.計算f(x)=x2時,除了定義乙個f(x)
的函式外,還可以直接傳入匿名函式:
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
關鍵字2.也可以把匿名函式賦值給乙個變數,再利用變數來呼叫該函式:lambda
表示匿名函式,冒號前面的x
表示函式引數。匿名函式有個限制,就是只能有乙個表示式,不用寫
return
,返回值就是該表示式的結果。
>>> f = lambda x: x * x
>>> f
at 0x101c6ef28>
>>> f(5)
25
3.也可以把匿名函式作為返回值返回,比如:
def build(x, y):
return lambda: x * x + y * y
1.函式也是乙個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式
2.函式物件有乙個__name__
屬性,可以拿到函式的名字:
def now():
... print('2015-3-25')
f = now
>>> f()
2015-3-25
>>> now.__name__
'now'
>>> f.__name__
'now'
3.我們要增強now()
函式的功能,比如,在函式呼叫前後自動列印日誌,但又不希望修改now()
函式的定義,這種在**執行期間動態增加功能的方式,稱之為「裝飾器」(decorator)。本質上,decorator就是乙個返回函式的高階函式。所以,我們要定義乙個能列印日誌的decorator
def log(func):
print('call %s():' % func.__name__)
return func(*args, **kw)
觀察上面的log,因為它是乙個decorator,所以接受乙個函式作為引數,並返回乙個函式。我們要借助python的@語法,把decorator置於函式的定義處
@log
def now():
print('2015-3-25')
呼叫now()
函式,不僅會執行now()
函式本身,還會在執行now()
函式前列印一行日誌:
call now():
2015-3-25
4.如果decorator本身需要傳入引數,那就需要編寫乙個返回decorator的高階函式,寫出來會更複雜。比如,要自定義log的文字:
def log(text):
def decorator(func):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return decorator
這個3層巢狀的decorator用法如下:
@log('execute')
def now():
print('2015-3-25')
執行結果:
>>> now()
execute now():
2015-3-25
>>> now.__name__
import functoolsdef log(text): #該函式主要作用是傳參
def decorator(func): #該函式是裝飾器
@functools.wraps(func) #該語句的作用是:不讓原函式名改變
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return decorator
import time, functools
def metric(fn):
@functools.wraps(fn)
start=time.time()
re=fn(*args,**kw)
end=time.time()
print('%s executed in %s ms' % (fn.__name__, end-start))
return fn(*args,**kw)
@metric
def fast(x, y):
time.sleep(0.0012)
return x + y;
s = fast(56, 23)
print (s)
5.總結:在物件導向(oop)的設計模式中,decorator被稱為裝飾模式。oop的裝飾模式需要通過繼承和組合來實現,而python除了能支援oop的decorator外,直接從語法層次支援decorator。python的decorator可以用函式實現,也可以用類實現。decorator可以增強函式的功能,定義起來雖然有點複雜,但使用起來非常靈活和方便。
1.functools.partial
的作用就是,把乙個函式的某些引數給固定住(也就是設定預設值),返回乙個新的函式,呼叫這個新函式會更簡單。建立偏函式時,實際上可以接收函式物件、*args
和**kw
這3個引數
import functools
int2 = functools.partial(int, base=2)
max2 = functools.partial(max, 10)
函式式程式設計(五)
如果你前面都看完了跟到了這裡,我只能說你很棒棒,不過我不得不說,這才剛剛開始。前面我們已經知道如何書寫函式式的程式了,但是我們還沒提到控制流 control flow 異常處理 error handling 非同步操作 asynchronous actions 和狀態 state 呢?容器為函式式程...
函式式程式設計總結
尾遞迴解決的是棧的記憶成本,更好防止堆疊溢位。遞迴在兩種情況下會掛 一是沒有結束條件 二是堆疊記憶體超過了最大限制。1 柯里化 柯里化是一種 預載入 函式的方法,通過傳遞較少的引數,得到乙個已經記住了這些引數的新函式,某種意義上講,這是一種對引數的 快取 是一種非常高效的編寫函式的方法。2 高階函式...
函式式程式設計總結
函式式程式設計是圍繞高階函式進行的,設計的核心在於高階函式的設計。1 函式式程式設計通過函式的復合生成更大的結構 2 函式的操作分為分解和復合 分解即為柯里化,可以分為偏函式分解和徹底分解。復合即為待定係數和呼叫約定。3 函式的運算最終轉化為代數運算。4 monad的本質是簡化版的物件,與閉包類似 ...