zoukankan      html  css  js  c++  java
  • 步入函数式编程的大门

    注:本人用Python3.4作为学习版本,以下学习心得只适用于Python3.4。

    写下这篇博客,意味着我即将步入函数式编程的大门。

    说起函数,首先想到的莫过于读书至今依然围绕在我身边的那个“函数”。数学计算中的函数,简单地说,就是对给定数的一种人为约定的运算法则,将给定的数通过某种变化得到一个新的结果。Python中的函数有内置函数,简单的说和数学上的函数功能类似,比如说abs,就是将给定的值取绝对值,验证如下:

    # Author: Lucas w
    res = abs(-10)
    print(res)

    运行结果如下所示:

    10
    
    Process finished with exit code 0

    类似的函数在Python中有好多,函数式编程和数值运算中的函数有着相同的灵魂,作为初级入门,我暂且将函数式编程定义为:将一段代码封装起来,就变成一个函数,起个名字,就是函数名,当需要调用这段代码时,直接调用函数名即可。以下是验证程序:

    # Author: Lucas w
    #一段代码
    a=1
    b=2
    c=a+b
    print(c)
    #将代码封装变成一个简单函数
    def res():
        a=1
        b=2
        c=a+b
        print(c)
    res()

    结果如下:

    3
    3
    
    Process finished with exit code 0

    说了这么多,接下来谈一下函数的基本形式,代码如下:

    # Author: Lucas w
    def test(x):
        x+=1
        print(x)
        return 0
    test(1)

    运行结果如下:

    2
    
    Process finished with exit code 0

    其中test表示函数名,x为形式参数,return为函数的返回值,这就是函数最简单的标准形式。接下来我们对函数进行全面的剖析。

    首先我们来探讨函数的返回值return。

    当我们需要接收函数返回值时,我们需要将函数赋给一个变量。验证程序如下:

    # Author: Lucas w
    def test():
        return 0
    y= test()
    print(y)

    运行结果如下:

    0
    
    Process finished with exit code 0

    接下来要考虑的问题是,return都可以返回什么样的值。经过学习,初步确定为三种:当没有定义返回值时,返回空值None;当定义为对象时,返回该对象;当定义不止一个对象时,返回一个元组。验证程序如下:

    # Author: Lucas w
    def test1():
        return
    x= test1()
    def test2():
        return 1
    y= test2()
    def test3():
        return 1,2,3,4,5
    z= test3()
    print(x)
    print(y)
    print(z)

    运行结果如下:

    None
    1
    (1, 2, 3, 4, 5)
    
    Process finished with exit code 0

    至此,我们已经熟悉了函数return都可以返回的值,至于定义函数为什么要加return这个返回值,大概是某些特定的时候,需要得到函数的计算结果,所以return才应运而生,我们姑且这么理解,毕竟刚入门,不可能追究过深。

    接下来,我们来挖掘一下函数的参数所蕴含的秘密。

    说起参数,我们都知道函数有形式参数,有实际参数。至于这两者的区别,一句话概括:实际参数占用内存空间,而形式参数不占用内存空间。这里我们用查询内存地址函数id来验证,程序如下:

    # Author: Lucas w
    def test(x):
        print(x)
        print(id(x))
        return
    test(1)
    print(id(1))

    运行结果如下:

    1
    1755480256
    1755480256
    
    Process finished with exit code 0

    可以看出,当函数运行时形式参数和实际参数有相同的内存地址。但是当函数运行后,形式参数被释放,不占用内存;而实际参数依然在内存中存在。验证如下:

    # Author: Lucas w
    def test(x):
        print(x)
        return
    test(1)
    print(id(1))
    print(id(x))

    运行如下:

    1
    1755480256
    Traceback (most recent call last):
        print(id(x))
    NameError: name 'x' is not defined
    
    Process finished with exit code 1

    可以看出,并没有在内存中找到x。这就看出了形式参数和实际参数的区别。形式参数用时占用内存,不用时释放内存;而实际参数,只要定义了,就一直在内存中存在。

    接下来,我们来探讨参数的调用。这里主要有两种调用方式:位置参数调用,顾名思义就是按照函数定义时参数的位置,采用一一对应的原则进行调用;另一种是关键字调用,这种调用方式更加灵活。验证程序如下:

    # Author: Lucas w
    def test(x,y,z):
        print(x)
        print(y)
        print(z)
        return
    print("位置参数调用")
    test(1,2,3)
    print("关键字调用")
    test(x=1,z=3,y=2)

    运行结果如下:

    位置参数调用
    1
    2
    3
    关键字调用
    1
    2
    3
    
    Process finished with exit code 0

    另外需要注意的是,关键字参数只能写在位置参数后边,不然程序就会报错。验证如下:

    # Author: Lucas w
    def test(x,y,z):
        print(x)
        print(y)
        print(z)
        return
    print("位置参数在关键字参数前,可以调用")
    test(1,y=2,z=3)

    运行结果如下:

    位置参数在关键字参数前,可以调用
    1
    2
    3
    
    Process finished with exit code 0

    位置参数在关键字参数后,则不能完成函数调用,验证程序如下:

    # Author: Lucas w
    def test(x,y,z):
        print(x)
        print(y)
        print(z)
        return
    print("位置参数在关键字参数后,不可以调用")
    test(x=1,2,3)

    运行结果如下:

        test(x=1,2,3)
                ^
    SyntaxError: non-keyword arg after keyword arg
    
    Process finished with exit code 1

    因此,在调用函数时只要记住一句话:位置参数在前,关键字参数在后。

    当我们需要定义函数的参数,不只局限于x,y...登有限个参数时。Python提供了两种方式:一种是元组存储法;一种是字典存储法。

    接下来我们来看元组存储法,程序如下:

    # Author: Lucas w
    def test(*args):
        print(args)
        return
    test(1,2,3,4,5,6,7,8,9,0)

    运行结果如下:

    (1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
    
    Process finished with exit code 0

    以此可知,我们输入的参数,都存储在了args这个tuple中,并且并不限制参数数目。

    接下来我们来验证第二种方法,字典存储法。验证程序如下:

    # Author: Lucas w
    def test(**args):
        print(args)
        return
    test(name="Wang",age="18",sex="men")

    运行结果如下:

    {'sex': 'men', 'name': 'Wang', 'age': '18'}
    
    Process finished with exit code 0

    因此,当我们需要定义的函数有未知个参数时,可以采取两种方法。一种是定义为元组,采用*args;一种是定义为字典,采用**args。

    至此,函数式编程基本形式,我们已经有了大概的了解。接下来明确一下局部变量和全局变量的关系。

    在Python中,

    全局变量指的是:除函数内定义的变量之外,其余程序中所有该变量都代表同一个变量。全局变量一般在程序一开始定义。

    局部变量指的是:函数内定义的变量,生效范围只在函数内,当函数不运行时,该变量不生效。

    另外需要注意的是,如果同时将一个变量定义为全局变量和局部变量,那么程序在执行时,函数内将其作为局部变量,函数外将其作为全局变量。实际运行时,也就是同名,实际代表的功能并不一样。这就好比老王有个儿子叫小王,而班里还有一个同学叫小王,我们并不能说这两个小王都是老王的儿子,也仅仅只是同名而已。慢慢体会,似乎同名的全局变量和局部变量也是一样的道理。验证程序如下:

    # Author: Lucas w
    XiaoWang = "小王的同学"
    def test(x):
        XiaoWang = "老王的儿子"
        print("局部变量")
        print(XiaoWang)
        return
    test(XiaoWang)
    print("全局变量")
    print(XiaoWang)

    运行结果如下:

    局部变量
    老王的儿子
    全局变量
    小王的同学
    
    Process finished with exit code 0

    这个全局变量和局部变量重名一般不会出现,之所以拿出来比较,也仅仅是加深理解概念罢了,并没有实际意义。另一个更加鸡肋的功能,将局部变量转换为全局变量。

    这个用法,在Python中存在,但是实际用处并不大,只能将我等入门级程序员弄的满脸蒙蔽。转换方法如下所示:

    # Author: Lucas w
    XiaoWang = "小王的同学"
    def test(x):
        global XiaoWang
        XiaoWang = "老王的儿子"
        print("转换为全局变量的局部变量")
        print(XiaoWang)
        return
    test(XiaoWang)
    print("全局变量")
    print(XiaoWang)

    运行结果如下:

    转换为全局变量的局部变量
    老王的儿子
    全局变量
    老王的儿子
    
    Process finished with exit code 0

    这个global功能,暂且知道用法,不进行细究。接下来我们进入递归函数的学习。

    所谓递归函数,字面意思可以理解为函数自身来调用自身,需要注意的是,Python中默认递归次数为999,虽然说我们可以通过设置来增加递归次数,但这显然不是最理想的做法,因为我们打破了Python对系统的一种保护机制。因此,我们在使用递归函数时必须明确指定一个结束条件,以免造成对系统损坏。以下是一种简单的递归函数:

    # Author: Lucas w
    def test(x):
        print(x)
        x-=1
        if x>0:
            return test(x)
    test(5)

    运行结果如下:

    5
    4
    3
    2
    1
    
    Process finished with exit code 0

    了解完递归函数之后,进入最后一个知识点:高阶函数。

    所谓高阶函数,就是将运算法作为参数引入函数的定义中,通过以下例子,我们就可以直观的看到。验证程序如下:

    # Author: Lucas w
    def test(x,y,f):
        return f(x)+f(y)
    res=test(1,-3,abs)
    print(res)

    运行结果如下:

    4
    
    Process finished with exit code 0

    自此,我们对Python中函数的概念有了一个大致的了解,算作是小小的入门吧,毕竟只是了解了一些概念,随着学习的深入,慢慢进步,共勉。

  • 相关阅读:
    一名中国联络官的来信
    中国女性出席1899年伦敦世界妇女大会
    曾在九江同文任教的中外人士若干
    金韵梅大夫略传
    为何高于四次的方程没有根式解?
    日军进攻九江的影像资料
    美以美会在九江
    九江同文中学与宝洁公司的甘布尔家族
    九江生命活水医院
    微信小程序获取用户信息签名解密C#
  • 原文地址:https://www.cnblogs.com/lucas0625/p/7577005.html
Copyright © 2011-2022 走看看