zoukankan      html  css  js  c++  java
  • Python 函数式编程 闭包

    AstralWind 的博客上有对函数式编程很好地讲解,一下做一些节选

    1.1. 什么是函数式编程?
    函数式编程使用一系列的函数解决问题。函数仅接受输入并产生输出,不包含任何能影响产生输出的内部状态。任何情况下,使用相同的参数调用函数始终能产生同样的结果。

      在一个函数式的程序中,输入的数据“流过”一系列的函数,每一个函数根据它的输入产生输出。函数式风格避免编写有“边界效应”(side effects)的函数:修改内部状态,或者是其他无法反应在输出上的变化。完全没有边界效应的函数被称为“纯函数式的”(purely functional)。避免边界效应意味着不使用在程序运行时可变的数据结构,输出只依赖于输入。

      可以认为函数式编程刚好站在了面向对象编程的对立面。对象通常包含内部状态(字段),和许多能修改这些状态的函数,程序则由不断修改状态构成;函数式编程则极力避免状态改动,并通过在函数间传递数据流进行工作。但这并不是说无法同时使用函数式编程和面向对象编程,事实上,复杂的系统一般会采用面向对象技术建模,但混合使用函数式风格还能让你额外享受函数式风格的优点。

    1.2. 为什么使用函数式编程?
    函数式的风格通常被认为有如下优点:

    • 逻辑可证
    • 模块化      函数式编程推崇简单原则,一个函数只做一件事情,将大的功能拆分成尽可能小的模块。小的函数更易于阅读和检查错误。
    • 组件化      小的函数更容易加以组合形成新的功能。
    • 易于调试   细化的、定义清晰的函数使得调试更加简单。当程序不正常运行时,每一个函数都是检查数据是否正确的接口,能更快速地排除没有问题的代码,定位到出现问题的地方。
    • 易于测试    不依赖于系统状态的函数无须在测试前构造测试桩,使得编写单元测试更加容易。
    • 更高的生产率   函数式编程产生的代码比其他技术更少(往往是其他技术的一半左右),并且更容易阅读和维护。

    1.3. 如何辨认函数式风格?
    支持函数式编程的语言通常具有如下特征,大量使用这些特征的代码即可被认为是函数式的:

    • 函数是一等公民   函数能作为参数传递,或者是作为返回值返回。
    • 匿名函数(lambda)  lambda表达式定义一个匿名的函数,如果这个函数仅在编码的位置使用到,你可以现场定义、直接使用:

      lst.sort(lambda o1, o2: o1.compareTo(o2))

    • 封装控制结构的内置模板函数 

    在Python里,过滤由一个名为filter的内置函数实现。有了这个函数,解释器就学会了如何“过滤”,而我们只需要把规则告诉它:
    lst2 = filter(lambda n: n > 0, lst)
    这个函数带来的好处不仅仅是少写了几行代码这么简单。
    封装控制结构后,代码中就只需要描述功能而不是做法,这样的代码更清晰,更可读。因为避开了控制结构的干扰,第二段代码显然能让你更容易了解它的意图。
    另外,因为避开了索引,使得代码中不太可能触发下标越界这种异常,除非你手动制造一个。
    函数式编程语言通常封装了数个类似“过滤”这样的常见动作作为模板函数。唯一的缺点是这些函数需要少量的学习成本,但这绝对不能掩盖使用它们带来的好处。

      部分内建函数介绍

        1.reduce(function, iterable[, initializer])

    1 def reduce_(function, lst, initial):
    2     result = initial
    3     for num in lst:
    4         result = function(result, num)
    5     return result

    它的第二个参数可以是任何可迭代的对象(实现了__iter__()方法的对象);
    如果不指定第三个参数,则第一次调用function将使用iterable的前两个元素作为参数。
    由reduce和一些常见的function组合成了下面列出来的内置函数:

    all(iterable) == reduce(lambda x, y: bool(x and y), iterable)
    any(iterable) == reduce(lambda x, y: bool(x or y), iterable)
    max(iterable[, args...][, key]) == reduce(lambda x, y: x if key(x) > key(y) else y, iterable_and_args)
    min(iterable[, args...][, key]) == reduce(lambda x, y: x if key(x) < key(y) else y, iterable_and_args)
    sum(iterable[, start]) == reduce(lambda x, y: x + y, iterable, start)

    2.map(function, iterable, ...)

    def map_(function, lst):
        result = []
        for item in lst:
            result.append(function(item))
        return result 

    map还可以接受多个iterable作为参数,在第n次调用function时,将使用iterable1[n], iterable2[n], ...作为参数。
    3.filter(function, iterable)
      这个函数的功能是过滤出iterable中所有以元素自身作为参数调用function时返回True或bool(返回值)为True的元素并以列表返回
    4.zip(iterable1, iterable2, ...)
      这个函数返回一个列表,每个元素都是一个元组,包含(iterable1[n], iterable2[n], ...)。
      例如:zip([1, 2], [3, 4]) --> [(1, 3), (2, 4)]
      如果参数的长度不一致,将在最短的序列结束时结束;如果不提供参数,将返回空列表。

    • 闭包(closure)

    闭包是绑定了外部作用域的变量(但不是全局变量)的函数。大部分情况下外部作用域指的是外部函数。
    闭包包含了自身函数体和所需外部函数中的“变量名的引用”。引用变量名意味着绑定的是变量名,而不是变量实际指向的对象;如果给变量重新赋值,闭包中能访问到的将是新的值。
    闭包使函数更加灵活和强大。即使程序运行至离开外部函数,如果闭包仍然可见,则被绑定的变量仍然有效;每次运行至外部函数,都会重新创建闭包,绑定的变量是不同的,不需要担心在旧的闭包中绑定的变量会被新的值覆盖。

    传送门:闭包详解 

  • 相关阅读:
    IXmlSerializable With WCFData Transfer in Service Contracts
    Difference Between XmlSerialization and BinarySerialization
    Using XmlSerializer (using Attributes like XmlElement , XmlAttribute etc ) Data Transfer in Service Contracts
    Introducing XML Serialization
    Version Tolerant Serialization
    Which binding is bestWCF Bindings
    Data Transfer in Service Contracts
    DataContract KnownTypeData Transfer in Service Contracts
    Using the Message ClassData Transfer in Service Contracts
    DataContract POCO SupportData Transfer in Service Contracts
  • 原文地址:https://www.cnblogs.com/tangr206/p/3056868.html
Copyright © 2011-2022 走看看