Python与Erlang函数性的对比(一)

PythonErlang函数性的对比(一)

1. 列表推导式:

Python

Erlang

基本的

[n*n for n in [1,2,3,4]]

[N*N || N <-[1,2,3,4]].

带条件判断的

[n*n for n in [1,2,3,4] if n%2 == 0]

[N*N || N <-[1,2,3,4], N rem 2 =:= 0].

多变量

[(x,y) for x in [1,2,3,4] for y in [1,2,3,4] if x%2==0 and y%2==0]

[{X,Y} || X<-[1,2,3,4], Y<-[1,2,3,4], X rem 2 =:=0Y rem 2 =:=0].

 

上面是列表推导式在PythonErlang中的区别。为了看懂上面的表达式,我做几点说明,也算科普下基本知识。

1. 关于变量的说明:

共同点:变量不用声明类型,都是动态类型绑定。

区别:Erlang中变量名大写,小写的是原子,而Python中没有要求,但建议变量名使用驼峰标示;Python中可以修改变量的值,而Erlang中变量的值一旦赋值,则不能再改变。

2. 关于元组的说明:

共同点:二者都是不可改变的,一经定义,不再可变,常用于函数的返回值,元组可以嵌套定义;另外取值的时候都可以模式匹配取值。

区别:定义方式不同:Python中定义元组使用()Erlang中定义元组使用{}

3. 列表的说明:

共同点:列表的定义方式一样都是[]

区别:Python中队列表的操作取值方法很多,Erlang中也有一些方法,比如++ -- 二者是不同的。

4. 关于相等符号:

Python中是常规的==, Erlang中有== =:=两种,

5. 关于列表推导式:

列表推导式是为了简化命令式编程的循环,Python中使用for关键字,而Erlang中使用||符号

2.map, filter函数:

Python

Erlang

map

map(lambda x: 2*x, [1,2,3,4])

lists:map(fun(X-> 2*X end,[1,2,3,4]).

filter

map(lambda x: 2*x, [1,2,3,4])

lists:filter(fun(X-> X rem 2 =:= 0 end, [1,2,3,4]).

关于上面的几点说明:

1. 匿名函数的说明:

相同点: 函数没有名字(这是废话)

区别:python中使用lambda创建匿名函数,格式为lambda arg1, arg2: <expression> 

Erlang中匿名函数的格式为fun(Args1) -> Exp1, Exp2, ....ExpN; (Args2) -> Exp1, Exp2,... End

2. 关于Map Reduce函数

Map函数是将函数应用于列表中的每一个元素,完成后返回一个新的保存了每个列表中元素经过函数处理后的值。

Filter函数式将函数应用于列表中的每一个元素,完成后返回一个新的使元列表应用于函数值为true的元素组成的列表。

3. 递归与尾递归

递归的定义相信学过编程语言的都知道,尾递归是针对传统递归算法而言的,尾递归是从最后开始计算,每递归一次就算出相应的结果,也就是说,函数调用出现在调用者函数的尾部,因为是尾部,所以根本没有必要保存任何局部变量,直接让被调用的函数返回时越过调用者,返回到调用者的调用者

Erlang中例子

%% 尾递归调用

sum(Total0-> Total;

sum(TotalX->

sum(Total+XX-1).

s(X-> 

sum(XX-1).

%% 递归调用

se(0-> 0;

se(X-> X + se(X-1)

Python 中例子

尾递归调用

def sum(total, x):

    if (x == 0):

        return total

    else:

        return sum(total+x, x-1)

def s(x):

    return sum(x, x-1)

递归调用

def se(x):

    if (x == 0):

        return 0

    else:

        return x + se(x-1)

测试结果:

python中尾递归并没有转换为循环,依然会报RuntimeError: maximum recursion depth exceeded,在erlang中正常,这种尾递归在Oracle jdk中一样会报堆栈溢出错误。

4. 闭包

闭包简单来说就是在一个函数中包括了另一个函数,关于闭包的价值有两点:

1. 保护函数内的变量安全性和可访问性

2. 在内存中维持一个变量

Erlang中的闭包的定义是通过fun函数:

base(A->

B = A + 1,

F = fun() ->

A * B

end,

F().

简洁版的:

base(A->

B = A + 1,

(fun() ->

A * B

end)().

由于Erlang中变量的不变形,匿名函数的上下文也是不变的

Python

def base(a):

    b = a+1

    def iner():

        return b

return iner()

Python中有一个有意思的问题,看看下面的代码

def base(a):

    b = a+1

    def iner():

        b = b+1

        return b

    return iner()

这段代码会报一个UnboundLocalError: local variable 'b' referenced before assignment

奇怪吧?

Python3.0以前,闭包能访问外部函数的局部变量,但是不能修改外部函数的局部变量,

Python3.0为此引入了nonlocal关键字,完善了闭包访问外部变量的机制

def base(a):

    b = a+1

    def iner():

        nonlocal b

        b = b+1

        return b

return iner()

这样在python3.0中就不会报异常了,注意和global关键字是区别,这个关键字是在函数内部引用并重新绑定(修改)全局变量

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值