函數式編程,使代碼簡潔高效。html
函數編程語言最重要的基礎是λ演算(lambda calculus),函數能夠像數值同樣被賦值於變量,還能夠做爲其餘函數的輸入(引數)和輸出(傳出值)進行傳遞。python
函數能夠當作參數來進行傳遞,造成所謂的高階函數,形如 z=g(f(x),y)
,還能像變量同樣被建立和修改。算法
Map函數:編程
map(func, *iterables),做用是將一個列表映射到另外一個列表。設計模式
class map(object): """ map(func, *iterables) --> map object Make an iterator that computes the function using arguments from each of the iterables. Stops when the shortest iterable is exhausted. """
使用方法:數組
def f(x): return x**2 li = range(1,10) res = map(f,li) print(res) print(list(res)) """ <map object at 0x000000000117E2E8> [1, 4, 9, 16, 25, 36, 49, 64, 81] """
map(function, iterable, ...)app
map()函數接收兩個參數,一個是函數,一個是可迭代的對象,map將傳入的函數依次做用到序列的每一個元素,返回一個map對象,不是list。編程語言
基本等價於 [f(x) for x in interable],列表推導比map效率要高一些ide
map(lambda x: x+1, range(1, 3)) => [x+1 for x in range(1,3)]函數式編程
str = ["far","foo","bar"] mp = map(lambda x:x.upper(),str) res = list(mp) print(res) """ ['FAR', 'FOO', 'BAR'] """
Reduce函數
reduce(function, sequence[, initial]),對可迭代對象依次作累計操做,如依次相加或相乘。
reduce()
方法接收一個函數做爲累加器(accumulator),數組中的每一個值(從左到右)開始合併,最終爲一個值。
def reduce(function, sequence, initial=None): # real signature unknown; restored from __doc__ """ reduce(function, sequence[, initial]) -> value Apply a function of two arguments cumulatively to the items of a sequence, from left to right, so as to reduce the sequence to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). If initial is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty. """
直接使用會報錯
reduce(lambda x, y : x + y, [1, 3, 5, 7, 9])
"""
NameError: name 'reduce' is not defined
"""
正確的使用是:reduce是functools中的一個函數,須要引用:from functools import reduce
使用方法:
from functools import reduce res1 = reduce(lambda x, y: x*y, [1, 2, 3]) res2 = reduce(lambda x, y : x + y, [1, 3, 5]) print(res1) print(res2) """ 6 9 """
Python內置的all()
,any()
,sum()
,max()
,min()
等函數都是從reduce()衍生而來。
Filter函數
filter(function or None, iterable),做用是按照所定義的函數過濾掉列表中的一些元素
class filter(object): """ filter(function or None, iterable) --> filter object Return an iterator yielding those items of iterable for which function(item) is true. If function is None, return the items that are true. """
使用方法:
flt = filter(lambda x: x > 5, range(10)) res = list(flt) print(flt) print(res) """ <filter object at 0x0000000000649A58> [6, 7, 8, 9] """
經過列表生成式,能夠直接建立一個列表。但受內存限制,列表容量有限。建立一個包含100萬個元素的列表,會佔用很大的存儲空間,若是咱們僅僅須要訪問其中幾個元素,那絕大多數元素佔用的空間都白白浪費了。
因此,若是列表元素能夠按照某種算法推算出來,那咱們是否能夠在循環的過程當中不斷推算出後續的元素呢?這樣就沒必要建立完整的list,從而節省大量的空間。在Python中,這種一邊循環一邊計算的機制,稱爲生成器:generator。
要建立一個generator,有不少種方法。最簡單的方法是,只要把一個列表生成式的[]
改爲()
,就建立了一個generator:
lis = [x*x for x in range(10)] # list gen = (x*x for x in range(10)) # generator對象,與list的區別,只是最外層的() print(lis) print(gen) """ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] <generator object <genexpr> at 0x000000000118C8E0> """
一個函數調用時返回一個迭代器,那這個函數就叫作生成器(generator);
若是函數中包含yield語法,那這個函數就會變成生成器。
def cube(n): for i in range(n): yield i ** 3 for i in cube(5): print(i) """ 0 1 8 27 64 """
生成器的特色:
1)生成器只有在調用時纔會生成相應的數據;
2)只記錄當前位置;
3)只有一個__next__()方法;
yield 的實現
def simple_yield(start): n = start while True: yield n n += 1 if __name__ == '__main__': for i in simple_yield(5): print(i) if i >= 10: break """ 5 6 7 8 9 10 """
從 simple_yield 中拿數據,拿到數據後,yield 會當即返回(可能有返回值),函數自己並無結束,只是被掛起,直到下次調用(for 循環會調用 next 方法)再從掛起的地方(yield)開始執行。
怎麼打印出generator的每個元素?
一、若是要一個一個打印出來,能夠經過next()
函數得到generator的下一個返回值;
二、for
循環迭代
lis = [x*x for x in range(10)] # list gen = (x*x for x in range(10)) # generator對象,與list的區別,只是最外層的() print(lis) print(gen) print(next(gen)) print(next(gen)) print(next(gen)) for i in gen: print(i) """ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] <generator object <genexpr> at 0x000000000119C8E0> 0 1 4 9 16 25 36 49 64 81 """
斐波拉契數列(Fibonacci)
除第一個和第二個數外,任意一個數均可由前兩個數相加獲得:1, 2, 3, 5, 8, 13, 21, 34, ...
def fib(max): n,a,b = 0,0,1 while n < max: print(b) a,b = b, a + b n += 1
能夠直接做用於for
循環的數據類型有如下幾種:
一類是集合數據類型,如list
、tuple
、dict
、set
、str
等;
一類是generator
,包括生成器和帶yield
的generator function。
這些能夠直接做用於for
循環的對象統稱爲可迭代對象:Iterable
。可使用isinstance()
判斷一個對象是不是Iterable
對象。
from collections import Iterable lt1 = isinstance([],Iterable) lt2 = isinstance({},Iterable) lt3 = isinstance('abc',Iterable) lt4 = isinstance((x for x in range(10)), Iterable) lt5 = isinstance(100, Iterable) print(lt1, lt2,lt3,lt4,lt5) """ True True True True False """
凡是可做用於for
循環的對象都是Iterable
類型;
凡是可做用於next()
函數的對象都是Iterator
類型,它們表示一個惰性計算的序列;
集合數據類型如list
、dict
、str
等是Iterable,
但不是Iterator
,不過能夠經過iter()
函數得到一個Iterator
對象。
Python的for
循環本質上就是經過不斷調用next()
函數實現的,例如:
for
x
in
[
1
,
2
,
3
,
4
,
5
]:
pass
# 首先得到Iterator對象: it = iter([1, 2, 3, 4, 5]) # 循環: while True: try: # 得到下一個值: x = next(it) except StopIteration: # 遇到StopIteration就退出循環 break
本質上是個函數,功能是裝飾其餘函數——就是爲其餘函數添加附加功能。
裝飾器是一個很著名的設計模式,常常被用於有切面需求的場景,較爲經典的有插入日誌、性能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,咱們就能夠抽離出大量函數中與函數功能自己無關的雷同代碼並繼續重用。歸納的講,裝飾器的做用就是爲已經存在的對象添加額外的功能。
裝飾器原則:
1)不能修改被裝飾函數的源代碼;
2)不能修改被裝飾函數的調用方式;
########## 基本裝飾器 ########## def orter(func): #定義裝飾器 def inner(): print("This is inner before.") s = func() #調用原傳入參數函數執行 print("This is inner after.") return s #return原函數返回值 return inner #將inner函數return給name函數 @orter #調用裝飾器(將函數name當參數傳入orter裝飾器) def name(): print("This is name.") return True #name原函數return True ret = name() print(ret) 輸出結果: This is inner before. This is name. This is inner after. True
############ 裝飾器傳參數 ########### def orter(func): def inner(a,b): #接收傳入的2個參數 print("This is inner before.") s = func(a,b) #接收傳入的原函數2個參數 print("This is inner after.") return s return inner @orter def name(a,b): #接收傳入的2個參數,並name總體函數當參數傳入orter裝飾器 print("This is name.%s,%s"%(a,b)) return True ret = name('nick','jenny') #傳入2個參數 print(ret) 輸出結果: This is inner before. This is name.nick,jenny This is inner after. True
########## 萬能參數裝飾器 ########## def orter(func): def inner(*args,**kwargs): #萬能參數接收多個參數 print("This is inner before.") s = func(*args,**kwargs) #萬能參數接收多個參數 print("This is inner after.") return s return inner @orter def name(a,b,c,k1='nick'): #接受傳入的多個參數 print("This is name.%s,%s"%(a,b)) return True ret = name('nick','jenny','car') print(ret) 輸出結果: This is inner before. This is name.nick,jenny This is inner after. True
########### 一個函數應用多個裝飾器 ######### def orter(func): def inner(*args,**kwargs): print("This is inner one before.") print("This is inner one before angin.") s = func(*args,**kwargs) print("This is inner one after.") print("This is inner one after angin.") return s return inner def orter_2(func): def inner(*args,**kwargs): print("This is inner two before.") print("This is inner two before angin.") s = func(*args,**kwargs) print("This is inner two after.") print("This is inner two after angin.") return s return inner @orter #將如下函數總體當參數傳入orter裝飾器 @orter_2 #將如下函數當參數傳入orter_2裝飾器 def name(a,b,c,k1='nick'): print("This is name.%s and %s."%(a,b)) return True ret = name('nick','jenny','car') print(ret) 輸出結果: This is inner one before. This is inner one before angin. This is inner two before. This is inner two before angin. This is name.nick and jenny. This is inner two after. This is inner two after angin. This is inner one after. This is inner one after angin. True
實現裝飾器知識儲備:
函數即「變量」
定義一個函數至關於把函數體賦值給了函數名
1.函數調用順序
與其餘高級語言相似,python不容許在函數未聲明以前,對其進行引用或者調用
錯誤示範:
def foo(): print('in the foo') bar() foo() """ NameError: name 'bar' is not defined """
正確示範:(注意,python爲解釋執行,函數foo在調用前已經聲明瞭bar和foo,因此bar和foo無順序之分)
def foo(): print('in the foo') bar() def bar(): print('in the bar') foo() def bar(): print('in the bar') def foo(): print('in the foo') bar() foo() """ in the foo in the bar in the foo in the bar """
2.高階函數
知足下列條件之一就可稱函數爲高階函數
1.某一函數當作參數傳入另外一個函數中
2.函數的返回值包含n個函數,n>0
高階函數示範:
def bar(): print('in the bar') def foo(func): res=func() return res foo(bar) """ in the bar """
3.內嵌函數和變量做用域
在一個函數體內建立另外一個函數,這種函數就叫內嵌函數。
嵌套函數:
def foo(): def bar(): print('in the bar') bar() foo() """ in the bar """
局部做用域和全局作用域的訪問順序
x = 0 def grandpa(): def dad(): x = 2 def son(): x=3 print(x) son() dad() grandpa() """ 3 """
4.高階函數+內嵌函數 ==》 裝飾器
函數參數固定
def decorartor(func): def wrapper(n): print('starting') func(n) print('stopping') return wrapper def test(n): print('in the test arg is %s' %n) decorartor(test)('alex')
函數參數不固定
def decorartor(func): def wrapper(*args,**kwargs): print('starting') func(*args,**kwargs) print('stopping') return wrapper def test(n,x=1): print('in the test arg is %s' %n) decorartor(test)('alex',x=2222)
1.無參裝飾器
import time def decorator(func): def wrapper(*args,**kwargs): start_time=time.time() func(*args,**kwargs) stop_time=time.time() print("%s" %(stop_time-start_time)) return wrapper @decorator def test(list_test): for i in list_test: time.sleep(0.1) print('-'*20,i) #decorator(test)(range(10)) test(range(10))
2.有參裝飾器
import time def timer(timeout=0): def decorator(func): def wrapper(*args,**kwargs): start=time.time() func(*args,**kwargs) stop=time.time() print('run time is %s ' %(stop-start)) print(timeout) return wrapper return decorator @timer(2) def test(list_test): for i in list_test: time.sleep(0.1) print ('-'*20,i) #timer(timeout=10)(test)(range(10)) test(range(10))
3.終極裝飾器
user,passwd = 'alex','abc123' def auth(auth_type): print('auth func:',auth_type) def outer_wrapper(func): def wrapper(*args,**kwargs): print("wrapper func args:",*args,**kwargs) if auth_type=="local": username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: res = func(*args,**kwargs) print("---after authentication") return res else: exit("\033[31;1mInvalid username or password\033[0m") elif auth_type == "ldap": print('搞毛線ldap,不會......') return wrapper return outer_wrapper def index(): print("welcome to index page") @auth(auth_type="local") #home = wrapper() def home(): print("welcome to home page") return "from home" @auth(auth_type="ldap") def bbs(): print("welcome to bbs page") index() print(home())#wrapper() bbs()
http://www.cnblogs.com/suoning/p/5499812.html