python学习笔记(三)运行环境、函数式

python可以用很多方式运行起来:
1. 使用控制台,键入python,即可进入python解释器,然后每一句都会被解释执行
2. 使用IDE,同样是解释器形式
3. 使用文本编辑器写一系列代码保存,并在控制台进入保存的目录,键入 python xxx.py,翻译并执行
4. 用IDE提供的编辑器,写完之后run,效果与3一样。

如果一个文件里面全部只有定义的函数,如果执行该程序,会有什么效果呢?

#test1.py
def compare_boy(b1,b2):
    if(b1[0]<b2[0]):
        return -1
    elif(b1[0]>b2[0]):
        return 1
    return 0    

如果使用方式1、方式2执行,该函数的定义会被存储下来,之后的语句可以使用,而使用3、4方式,运行结束后没有任何效果。

开始

函数式编程是一种编程范式,其主要内涵是只有函数没有变量的抽象编程思想。python不是函数式编程语言,但是也支持一些函数式编程的功能。
1. 函数作为参数——高阶函数
函数在定义后,函数名可以作为变量使用,也可以作为参数传递到另外一个函数中。接受函数作为参数的函数称之为高阶函数。

def cut(list_b,cmp,pos):
    l = []
    n = len(list_b)
    b = list_b[pos]
    l = list_b[0:pos]+list_b[pos+1:]
    left = [i for i in l if(cmp(b,i)<0)]
    right = [i for i in l if(cmp(b,i)>=0)]
    left.append(b)
    return left+right

这个函数功能是把列表list_b的pos位置处元素提出来,然后比它小的放在右边,比它大的放在左边。

[i for i in l if(cmp(b,i)<0)]:是生成列表的一种方式,方法是对l进行遍历,取出满足if中条件的元素。
left+right:列表重载了+运算符,可以作为连接操作。

这里把cmp视为一个函数使用,我们可以传入之前的函数与参数进行测试:

boy1 = [3,'Jack','m',15]
boy2 = [1,'Mark','m',19]
boy3 = [2,'Tim','m',25]
boys = (boy1,boy2,boy3)
print cut(boys,compare_boy,0)

2. 函数作为返回值——闭包
函数能作为参数传入,也自然能作为返回值返回,但不是说返回函数的函数就是闭包。
看一个例子来理解闭包的概念:

def addlistfun(cho):
    list = []
    def add(it):
        list.append(it)
        print list
        return list

    if(cho==1):
        list = list + ['this list is for fun']
        return add
    else:
        list = list + ['this is another']
        return add

这里在函数的内部定义了函数,在python中这是允许的,在c++中在函数中定义函数是未定义行为(匿名函数除外)。
这个函数内部的函数使用了其外部函数的变量list,这种看似奇怪的程序结构称为闭包。
当这个内部函数被作为返回值返回时,其所有使用的外部函数的变量会绑定在该函数上,其初始值为返回时的值,而且每次函数返回的值是相互独立的。因此上面程序的测试结果中,选择cho参数不同的会有不同的表头。

3 . 匿名函数与偏函数
匿名函数的名字是lambda,使用方法如下:

addf = lambda(list,item):list.append(item)

匿名函数只能写一句表达式,且该表达式的值就是其返回值。(append()方法的返回值是None)
偏函数神似c++中的bind函数,作用是将一个值绑定在函数的参数上。使用前需要import functools

import functools
l = []
addf2 = functools.partial(addf,list = l)
addf2(12)

但这句话会发生错误,经过反复测试推理,有两个错误:
1. 参数是不能绑定在非绑定参数之前,即上面的list要放在item之后。这个可以理解,相当于c++中缺省参数不能放在非缺省之前。
2. 匿名函数不能用这种方法绑定,原因未知。
修改:改为一般定义的函数,调换参数位置。测试成功。


其他的推理(错误):
传递的是字面值——通过传递默认参数的方式推翻
参数值需要特殊标识——并不需要
……

参考资料:
JS中的闭包:
http://kb.cnblogs.com/page/110782/
廖雪峰教程:
http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819893624a7edc0e3e3df4d5d852a352b037c93ec000
python传递值还是传递引用:
http://www.cnblogs.com/loleina/p/5276918.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章