`
xiaobian
  • 浏览: 588039 次
  • 来自: 北京
社区版块
存档分类
最新评论

apply、map及函数工具、list的再构造

阅读更多
http://hi.baidu.com/peaksst/blog/item/457de91056bfa803213f2e99.html
python(22): apply、map及函数工具、list的再构造(14.2-14.5)
2007-07-28 16:37
首先来复习python中函数的定义。在python中,有两种方式可以用来定义一个函数。用def可以定义有名字的函数。用lambda可以定义匿名函数。由于在实际调用一个函数时,实参的个数可能是一个也可能是两个,还可能是多个。因此在形参前面加上*或**来处理这个情况。比如:
  1. def test(*x):
  2.      if len(x)>0:
  3.         for c in x:
  4.            print c
  5.      else:
  6.         print None
上面定义的函数的功能是把参数一个一个打出来(通过print),这个函数可以使用没有实参的形式调用,比如:test();也可以使用一个实参的形式调用,比如:test(4);还可以以多个实参的形式调用,比如:test(1,2,3,4)。但不管是哪种方式,在调用的时候实际参数的个数都已经确定下来了,一个就是一个,两个就是两个。现在假设在一个程序中有一个list,比如叫userInput,这个list中的成员是由用户在使用程序时交互确定的,在运行中可能有一个成员,也可能有多个成员,这一切都要看用户怎么操作。现在要用test函数把userInput打出来。那么使用下面这个形式是不行的:
  • test(userInput)
这只会把userInput作为一个整体打出来,比如说用户选择后userInput=[1,2],那么打出来的是[1,2],而我们想要的结果是:
1
2
这种形式的。很自然的,可能会想到应该用一个for循环:
  1. for c in userInput:
  2.      test(c)
这当然能实现上面要求的功能。不过,在python中还有更简单的办法,就是使用内置函数apply:
  • apply(test, userInput)
表示把userInput作为test的参数,也就是说比如在程序运行时,userInput得到的值是[1,2,3],那么就相当于test(1,2,3)。如果userInput得到的实际值是[1,2],那么就相当于test(1,2)。

总之,定义函数时在形式参数面前加上*或**是为了,在调用这个函数的时候可以灵活地提供实参的个数。而apply则是为了可以用不定个数的实际参数来调用函数。有点晕。(我也想不到一个更好的表达方式,或更好的例子。书中说,在后面会看到应用apply强大能力的例子)

其实还可以更简单,连apply都不用,直接写成:
  • test(*userInput)
这表示的意思就是apply(test,userInput)。可以把函数定义的中形参前面的*理解为“打包”操作,也就是把多余的实参都打包在一个tuple中;可以把调用时的*理解为“解包”的操作,比如说这里表示:调用test函数,实参是对userInput“解包”后所得的东西。当然对于**也可以以相同的方式理解。在test(**D)的形式中,D必须为一个dictionrary,相当于test(key1=value1,key2=value2...)。
(其实我不知道为什么会在python中出现这种古怪的东西,看这本书的前面几章时,觉得python太棒了,真的是很简洁。不过越往后看,觉得python越来越背离了它“简单”的宗旨)

map函数在前面介绍过了,基本的形式是:
  • map(function, seq1,seq2...)
map实际上是python中一大类函数的一个代表,这类函数可以被称为函数工具。常用的函数中,同类的还有filter和reduce。先来看filter:
  • filter(func or None,seq)
它返回一个序列类型的值。表示把seq中的每个成员依次代入function中,如果为真则它将成为返回序列中的一个成员。filter函数类似于:
  1. res = list()
  2. for x in seq:
  3.      if func(x):
  4.         res.append(x)
  5. res
如果filter的第一个实参为None,则表示把seq的中真值挑出来。

再来看reduce函数:
  • reduce(function, sequence[, initial])
表示把sequence按照function提供的规则进行计算,最后算出一个值来。这个function必须具有两个参数,比如:
  1. L = [1,2,3,4,5]
  2. reduce((lambda x,y: x*y),L) ===> 120
这就相当于把乘法应用于L的各个成员中,也就是1*2*3*4*5。reduce的第三个参数表示一个初始值。即初始值*1*2*3*4*5。python中有一个叫operator的模块,其中提供了很多操作,比如加法叫add,乘法叫mul。上面的这一小段代码可以写成:
  1. import operator
  2. L = range(6)[1:]
  3. reduce(operator.mul, L)

从上面介绍可以看出,map、filter或者reduce实际都是对序列类型数据的成员进行操作。由于这种操作在python是非常普遍的,因此在python 2.0后提供了一种叫"list的再构造"(英文名叫list comprehansions,不知道怎么翻合适)的语法形式来进行类似的操作。假设L = [1,2,3,4],那么:map((lambda x: x**2), L)就可以写成:[x**2 for x in L]。这就是所谓的
"list的再构造"。认真来看看这个:
  • [x**2 for x in L]    ===> [1,4,9,16]
首先,这个表达式用[]括起来了,表示这个表达式返回的结果是一个list。其次,后面一部分,也就是for x in L,很明显是把L中的成员依次取出来。第三,前面一部分,也就是x**2,表示对x的操作是"平方"。然后以每次计算后的值作为目标list的成员。其实可以把这一部分看成是目标list的“通项公式”,通过对这个“通项公式”代入不同的值,可以得到不同的结果。而这个“不同的值”就是由后面的部分,即for x in L,确定的。
  • [(x**2,x**3) for x in L] ===> [(1, 1), (4, 8), (9, 27), (16, 64)]
当然大名顶顶的"list再构造"还有别的功能,它可以加上条件从句(if语句),比如:
  • [x**2 for x in L if x%2==0] ===>[4,16]
"list再构造"还可以嵌套for这一部分,比如:
  • [x*y for x in L for y in L] ===> [1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16]
相当于:
  1. res = []
  2. for x in L:
  3.      for y in L:
  4.         res.append(x*y)
  5. res
当然,嵌套for的"list再构造"也可以加上条件判断。比如:
  • [x*y for x in L if x%2==0 for y in L if y%2 != 0]   ===>[2, 6, 4, 12]
这个式子已经相当复杂,因此在以程序可读性著称的python世界中,最好不要使用这种东西。不过,也可见用“list再构造”也可以实现for或者map和filter的功能,但是list再构造的效率最高,其次map、filter这些内置函数,再次才是for。

 

类别:Python | 添加到搜藏 | 浏览(100) | 评论 (0) <script></script>
 
分享到:
评论

相关推荐

    List<Map<String, List>> data保存到SharedPreference和读取

    在进行序列化和反序列化时,要确保所有相关的类都有默认构造函数,因为Gson在反序列化时会使用这些构造函数。同时,如果数据结构发生变化,应考虑兼容旧版本的数据,避免数据丢失或解析错误。 总之,通过使用Gson库...

    对pandas中Series的map函数详解

    在Python数据分析领域,pandas库是不可或缺的一部分,它提供了丰富的数据处理工具,其中包括Series的map函数。本篇文章将深入解析pandas中Series的map函数,帮助读者理解和掌握其使用方法。 首先,Series的map函数...

    python源码高阶函数应用

    3. **使用`map()`函数**:`map()`函数接受一个函数和一个可迭代对象作为参数,将参数函数应用于可迭代对象的每个元素,并返回一个新的迭代器,这个迭代器的结果通常会被转换为列表。 示例代码: ```python def ...

    Scala的List类方法整合

    val mappedList = list.map(x =&gt; x * 2) // 结果为 List(2, 4, 6) ``` #### 30. `def max: A` 此方法返回列表中的最大元素。 **示例代码:** ```scala val list = List(1, 2, 3, 4, 5) val maxElement = list.max /...

    java 三种将list转换为map的方法详解

    在Java编程中,将列表(List)转换为映射(Map)是一种常见的操作,这有助于数据的快速查找和处理。以下将详细介绍三种不同的方法来实现这个转换,针对一个包含电影排名(rank)和描述(description)的Movie类。 1...

    Mathematica函数大全

    12. **函数编程**:`Map`, `MapThread`, `Apply`应用函数到列表元素,`Composition`组合函数,`Fold`和`FoldList`对列表进行累积操作。 13. **符号编程**:`Symbol`, `Evaluate`, `Defer`处理符号表达式,`Hold`和`...

    Pythont特殊语法filter,map,reduce,apply使用方法

    Python中的`filter`, `map`, `reduce`, 和 `apply` 是四个非常重要的高阶函数,它们在处理数据和实现特定逻辑时提供了强大的功能。这些函数都属于Python的内建函数,能够有效地帮助我们进行序列操作。 1. **lambda ...

    python 基础教程之Map使用方法

    在Python编程语言中,`map()`函数是一个非常实用的内置函数,它允许我们将一个函数应用于一个可迭代对象(如列表)的所有元素上,返回一个新的可迭代对象,其中包含原始元素经过函数处理后的结果。`map()`函数是函数...

    Java使用函数式接口.pdf

    List&lt;Integer&gt; integers = listOfStrings.stream().map(stringToInteger).collect(Collectors.toList()); ``` 通过使用这些函数式接口,我们可以编写更简洁、更易于理解的代码,同时充分利用JVM的优化机制。然而,...

    Scala基础与实践

    11. 集合:Scala标准库提供了丰富的集合类型,包括List、Set、Tuple和Map等。这些集合都是高度优化的,并且是不可变的,这使得函数式编程更加便捷。 通过上述知识点的介绍,我们可以看到Scala结合了OO和FP的精华,...

    Python数据分析学习者-数据分析9个优雅小技巧(测试代码+保姆级api例程)

    3. **map函数映射.py**:`map()`函数接受一个函数和一个可迭代对象,返回一个新的迭代器,其中每个元素是原始迭代器元素经过函数处理后的结果。在数据分析时,map()可用于批量应用某个函数到数据集的每一项。 4. **...

    Python编码风格指南(中文版)

    2.10 使用 apply filter map reduce 2.11 Lambda functions 2.12 默认参数值 2.13 Properties 2.14 布尔内置类型 2.15 String 方法 2.16 静态域 2.17 函数和方法修饰符 2.18 线程 2.19 高级特性 3. Python 编码风格...

    Python Lambda函数使用总结详解

    在处理数据的库如Pandas中,Lambda函数也经常被用在DataFrame或Series对象的map、apply、transform等方法中,用于对数据进行快速操作: ```python import pandas as pd df = pd.DataFrame({ 'Age': [22, 21, 22, ...

    Lambda表达式超详细总结

    例如,`java.util.function.Function,R&gt;` 接口就是一个典型的函数接口,它有一个抽象方法 `R apply(T t)`。 3. **Lambda表达式实例** 假设我们有一个`Function, Integer&gt;`类型的变量`f`,可以这样定义Lambda表达式...

    【电气工控自动化】8 个 Python 高效数据分析的技巧.pdf

    3. **Map和Filter函数**: `map()`函数接受一个函数和一个可迭代对象,将函数应用于可迭代对象的每个元素,返回一个新的可迭代对象。例如,`list(map(lambda var: var*2, seq))`将列表`seq`中的每个元素乘以2。而`...

    Canjs 基础教程

    可以通过调用 `can.Construct.extend` 方法创建自己的构造函数,并传递两个参数,第一个参数是静态属性,第二个参数是对象(原型)属性。 例如,创建一个名为 `PrivateTodo` 的构造函数: ```javascript var ...

    kotlin in action

    - **次构造函数**:当需要多个构造函数时,可以使用次构造函数。 **4.3 编译器生成的方法:数据类和类委托** - **数据类**:通过`data`关键字定义的数据类自动实现了`equals()`、`hashCode()`等方法。 - **类委托*...

    学不会python多线程爬虫的函数调用,也就是面对方法爬虫,求解(csdn)————程序.pdf

    `Pool.apply_async()`方法用于异步执行函数,并可接收一个回调函数处理结果。 在`get_detail`函数中,开发者试图获取每个图片详情页的信息,包括图片链接和名称。这里的问题在于,`url`参数并未被正确传递给`get_...

Global site tag (gtag.js) - Google Analytics