普通的數學運算用這個純抽象的符號演算來定義,計算結果只能在腦子裡存在。所以寫了點代碼,來驗證文章中介紹的演算規則。
我們來驗證文章裡介紹的自然數及自然數運算規則。說到自然數,今天還百度了一下,據度娘說,1993年後國家規定0是屬於自然數。先定義自然數及自然數的運算規則:
用lambda運算式定義自然數(邱齊數)
0 := λf.λx.x1 := λf.λx.f x2 := λf.λx.f (f x)3 := λf.λx.f (f (f x))...
上面定義直觀的意思就是數字n, 是f(x)的n階函數。1就是f(x), 2就是f(f(x))....,嚴格來說,這樣表述並不準確。其實每個邱奇數都是一個二階函數,它有兩個變數f和x。用二元命名函數來表達就是:
0 -> num0(f,x)=x1 -> num1(f, x)=f(x)2 -> num2(f,x)=f(f(x))3 -> num3(f,x)=f(f(f(x)))...
其中參數f是一個函數。這一段有點繞,但是不能理解這個,對後面的lambda演算理解會比較困難。
首先用遞迴法,定義邱齊數(自然數)
0是自然數, 度娘說1993年後,國家規定0是屬於自然數。
每個自然數,都有一個後續。
用代碼錶達就是:
NUM0=lambda f: lambda x:xSUCC=lambda n: lambda f: lambda x: f(n(f)(x))
後面則是定義運算子,包括加法,乘法,減法和冪。維基文章裡沒有介紹除法,估摸著除法定義比較複雜,一時講不清楚。那我們也不驗證了。
#################################################define number calculus rules################################################ #define Church numeral inductively.#0 := λf.λx.x#1 := λf.λx.f x#2 := λf.λx.f (f x)#3 := λf.λx.f (f (f x))#...NUM0=lambda f: lambda x:xSUCC=lambda n: lambda f: lambda x: f(n(f)(x)) #define OperatorPLUS=lambda m: lambda n: m(SUCC)(n)MULT= lambda m: lambda n: m(PLUS(n))(NUM0)#define predecessor to obtain the previous number.PRED= lambda n: lambda f: lambda x: n(lambda g: lambda h: h(g(f)))(lambda u:x)(lambda u:u)SUB=lambda m: lambda n: n(PRED)(m)POW=lambda b: lambda e: e(b)
定義完了什麼是自然數和自然數的運運算元。那麼自然數的運算,就可以用lambda演算的方式計算了。
問題是上面的定義都是抽象的符號演算,我們需要有一個編碼器來把上面的抽象的Church numeral符號編碼成可以人來閱讀的形式,還需把人輸入的數字解碼成抽象符號。
#################################################create encoder to input/output Church numeral################################################ class LambdaEncoding: @staticmethod def encoding(exp,encoder): return encoder().encoding(exp) @staticmethod def decoding(s, decoder): return decoder().decoding(s) class NumEncoder: def encoding(self,num): f=lambda x:x+1 return str(num(f)(0)) def decoding(self,s): n=int(s) num=NUM0 for i in range(n): num=SUCC(num) return num
嗯,有了編碼器,就可以方便的來驗證了。
#################################################calculus demo################################################print("demo number calculus.\n" "don't input large number," "it will cause to exceed maximum recursion depth!\n") n1=input('input a number: ')n2=input('input anohter number: ')#decode string to Church numeralnum1=LambdaEncoding.decoding(n1,NumEncoder)num2=LambdaEncoding.decoding(n2,NumEncoder) #addresult=PLUS(num1)(num2) print('{0} + {1} = {2}'.format( n1, n2, LambdaEncoding.encoding(result, NumEncoder))) #multresult=MULT(num1)(num2)print('{0} X {1} = {2}'.format( n1, n2, LambdaEncoding.encoding(result, NumEncoder)))#subresult=SUB(num1)(num2)print('{0} - {1} = {2}'.format( n1, n2, LambdaEncoding.encoding(result, NumEncoder))) #POWresult=POW(num1)(num2)print('{0} ^ {1} = {2}'.format( n1, n2, LambdaEncoding.encoding(result, NumEncoder)))
測試結果如下:
>>> demo number calculus.don't input large number,it will cause to exceed maximum recursion depth! input a number: 4input anohter number: 34 + 3 = 74 X 3 = 124 - 3 = 14 ^ 3 = 64>>>
神奇吧。
lambda和def的區別
python lambda是在python中使用lambda來建立匿名函數,而用def建立的方法是有名稱的,除了從表面上的方法名不一樣外,python lambda還有哪些和def不一樣呢?
1 python lambda會建立一個函數對象,但不會把這個函數對象賦給一個標識符,而def則會把函數對象賦值給一個變數。
2 python lambda它只是一個運算式,而def則是一個語句。
下面是python lambda的格式,看起來好精簡阿。
lambda x: print x
如果你在python 列表解析裡用到python lambda,我感覺意義不是很大,因為python lambda它會建立一個函數對象,但馬上又給丟棄了,因為你沒有使用它的傳回值,即那個函數對象。也正是由於lambda只是一個運算式,它可以直接作為python 列表或python 字典的成員,比如:
info = [lamba a: a**3, lambda b: b**3]
在這個地方沒有辦法用def語句直接代替。因為def是語句,不是運算式不能嵌套在裡面,lambda運算式在“:”後只能有一個運算式。也就是說,在def中,用return可以返回的也可以放在lambda後面,不能用return返回的也不能定義在python lambda後面。因此,像if或for或print這種語句就不能用於lambda中,lambda一般只用來定義簡單的函數。
下面舉幾個python lambda的例子吧
1單個參數的:
g = lambda x:x*2print g(3)
結果是6
多個參數的:
m = lambda x,y,z: (x-y)*zprint m(3,1,2)
結果是4