這一次主要是學習了一下Python3函數式編程思想,介紹了3個表明性高階函數:map(), reduce(), filter()。像 sorted() 其實也是高階函數,能夠接受函數做爲參數。這篇學習筆記中編寫了大量高階函數,同時介紹了Python中的閉包,裝飾器。這些思想和方法很美妙,我受益不淺。固然這些都須要進一步運用和學習。javascript
運行環境:Python3.6 + Jupyter notebookcss
def add(x, y, f):
return f(x) + f(y)
add(-1, 1, abs)
map()做爲高階函數,它將運算規則抽象了。html
r = map(lambda x: x*x, [1, 2, 3, 4])
list(r)
from functools import reduce
def prod(List,f):
return reduce(f, List)
def f(x, y):
return x * y
prod([1,2,3], f)
from functools import reduce
num = {}
for i in range(10):
num[str(i)] = i
def str2int(string:str) -> int:
return reduce(lambda x, y: x*10 + y, map(char2num, string))
def char2num(s):
return num[s]
str2int('123')
type(str2int('123'))
from functools import reduce
num = {}
for i in range(10):
num[str(i)] = i
def char2num(s):
return num[s]
def str2float(string):
s = string.split('.')
f1 = lambda x, y: x * 10 + y
f2 = lambda x, y: x * 0.1 + y
return reduce(f1, map(char2num, s[0])) + 0.1 * reduce(f2, map(char2num, s[-1][::-1]))
str2float('1.234')
type(str2float('1.234'))
利用filter() 求素數(埃氏篩法)html5
def odd_iter():
n = 1
while True:
n += 2
yield n
def prime():
yield 2
it = odd_iter()
while True:
n = next(it)
yield n
it = filter(lambda x: x % n > 0, it)
for i in prime():
if i < 20:
print(i, end=' ')
else:
break
def lazy_sum(*args):
def sum():
ax = 0
for arg in args:
ax += arg
return ax
return sum
f = lazy_sum(1, 2, 3)
f
f()
咱們在函數lazy_sum中又定義了函數sum,而且,內部函數sum能夠引用外部函數lazy_sum的參數和局部變量,當lazy_sum返回函數sum時,相關參數和變量都保存在返回的函數中,這種稱爲「閉包(Closure)」的程序結構擁有極大的威力。java
def count():
fs = []
for i in range(1, 4):
def f():
return i * i
fs.append(f)
return fs
f1, f2, f3 = count()
f1(), f2(), f3()
注:閉包返回的函數並無馬上執行,而是直到調用了f()才執行。python
<font color = red>返回函數不要包含任何循環變量,或者後續會發生變化的變量。</font>jquery
若是必定要引入循環變量呢?方法是在 count() 中調用 f(),從而綁定循環變量當前值。linux
def count():
def f(j):
def g():
return j * j
return g
fs = []
for i in range(1, 4):
fs.append(f(i))
return fs
f1, f2, f3 = count()
f1(), f2(), f3()
def creat_counter():
def g():
n = 1
while True:
yield n
n += 1
it = g()
def counter():
return next(it)
return counter
counterA = creat_counter()
counterA()
counterA()
注:creat_counter() 做爲一個計數器函數。android
class sample:
def __init__(self,value):
self.value = value
def func(self):
print('n = ', self.value)
def get_value(self):
return self.value
def set_value(self,new_value):
self.value = new_value
test = sample(1)
test.func()
def sample(n):
value = n
def func():
print('n = ', value)
def get_value():
return value
def set_value(new_value):
nonlocal value
value = new_value
func.get_value = get_value
func.set_value = set_value
return func
test = sample(1)
test()
test.get_value()
test.set_value(5)
test()
注:將 get_value() 和 set_value() 做爲函數 func()的屬性,而後利用閉包返回 func() 函數css3
參考:訪問閉包中定義的變量,裏面有進一步內容。
def now():
print('2018/2/20')
now.__name__
如今但願增長 now() 函數的功能,但不改變他的定義,這種在代碼運行期間動態增長功能的方式,稱之爲裝飾器(Decorator)。
本質上,decorator 就是一個返回函數的高階函數。下面,咱們定義一個打印日誌的 decorator。
def log(func):
print('call {}'.format(func.__name__))
log(now)
可是這樣就顯式調用了 log(),說白了是兩個函數
def log(func):
def wrapper(*args, **kw):
print('call {}'.format(func.__name__))
return func(*args, **kw)
return wrapper
now = log(now)
now()
以上就實現了打印日誌的 now() 函數,同時會調用 now() 函數實現功能。
@log
def now():
print('2018/2/20')
now()
注:@log 至關於執行語句:
now = log(now)
log()就是一個 decorator,它返回 wrapper() 函數,執行 @log 後,wrapper 賦值給 now,再次執行 now() 後,咱們會執行 wrapper() 函數,打印日誌,而後執行原來的 now() 函數。
下面進一步。自定義日誌內容
大體思想是下面兩條語句:
now = log('text')(now)
now()
寫一個3層嵌套的 decorator:log('text') 返回一個函數,返回至關於上一個例子的 log() 函數。
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('{0}{1}():'.format(text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
def now():
print('2018/2/20')
now = log('execute')(now)
now()
用法以下:
@log('execute')
def now():
print('2018/2/20')
now()
可是有一個問題:
now.__name__
因爲最後返回的是 wrapper 函數,所以 now 的 __name__ 屬性就是 'wrapper'。
完整代碼:
例一:
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call {}'.format(func.__name__))
return func(*args, **kw)
return wrapper
@log
def now():
print('2018/2/20')
now()
now.__name__
例二:
import functools
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('{0}{1}():'.format(text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('execute')
def now():
print('2018/2/20')
now()
now.__name__
最後,寫一個打印函數執行時間的decorator
import time, functools
def meric(func):
@functools.wraps(func)
def wrapper(*args, **kw):
start = time.time()
result = func(*args, **kw)
end = time.time()
print('{} executed in {} ms'.format(func.__name__, end - start))
return result
return wrapper
@meric
def test(x, y):
time.sleep(0.1)
return x + y
test(1,2)