繁簡切換您正在訪問的是FX168財經網,本網站所提供的內容及信息均遵守中華人民共和國香港特別行政區當地法律法規。

FX168财经网>人物频道>帖子

Python提高(2)- 函数式编程和列表生成式

作者/sjfddsj 2019-08-24 16:31 0 来源: FX168财经网人物频道

【Python提高(2)】函数式编程和列表生成式¶

迭代器和解析是一种神奇的东西,学会他们可以大大加快我们的工作速度,下面开始

一、常见的几种迭代器¶

迭代器在python中是以C语言的速度运行的,而while循环版本则是通过Python虚拟机运行Python字节码的。

  1. range

  2. zip 可以让我们使用for循环来并行使用多个序列,zip会取得一个或多个序列为参数,然后返回元组的列表,将这些序列中的并排的元素配成对。

  3. enumerate 可以获得元素和元素的偏移值

  4. map map会对一个序列对象中的每一个元素应用被传入的函数,并且返回一个包含所有函数调用结果的一个列表。

  5. filter 基于某一测试函数过滤出一些元素

  6. reduce 对每对元素都应用函数并运行到最后结果

1、 range¶

X = 'spam'
for i in range(len(X)):
    print (X[i])
s
p
a
m
S = 'abcdefghijk'
for i in range(0,len(S),2):
    print S[i]
a
c
e
g
i
k

下面方法更容易理解,但是会复制一个字符串,如果字符串很大,占用内存较大¶

S = 'abcdefghijk'
for c in S[::2]:
    print c   
a
c
e
g
i
k

2、 zip¶

结合zip实现并行遍历

L1 = [1,2,3,4]
L2 = [5,6,7,8]
for (x,y) in zip(L1,L2):
    print (x,y,x+y)
(1, 5, 6)
(2, 6, 8)
(3, 7, 10)
(4, 8, 12)

使用zip构造字典

keys = ['a','b','c']
vals = [1,3,5]
D2 = {}
for (k,v) in zip(keys,vals): D2[k]=v
D2
{'a': 1, 'b': 3, 'c': 5}

3、 enumerate¶

可以获得元素和元素的偏移值

seasons = ['Spring', 'Summer', 'Fall', 'Winter']
dict(enumerate(seasons, start=3))
{3: 'Spring', 4: 'Summer', 5: 'Fall', 6: 'Winter'}

4、 map¶

map会对一个序列对象中的每一个元素应用被传入的函数,并且返回一个包含所有函数调用结果的一个列表。

map对每一个元素都应用了函数调用而不是任意的表达式,所以不太通用,但是在某些情况下,map比列表解析运行起来速度更快

S1 = 'abc'
S2 = 'xyz123'
map(None,S1,S2)
[('a', 'x'), ('b', 'y'), ('c', 'z'), (None, '1'), (None, '2'), (None, '3')]
map(pow,[1,2,3],[2,3,4])
[1, 8, 81]
map((lambda x: x+3),[1,2,3,4])
[4, 5, 6, 7]
def inc(x):
    return x+10
map(inc,[1,2,3])
[11, 12, 13]
import math
list(map(math.sqrt,(x ** 2 for x in range(4))))
[0.0, 1.0, 2.0, 3.0]

5、 filter¶

基于某一测试函数过滤出一些元素

list(filter((lambda x:x>0),range(-5,5)))
[1, 2, 3, 4]

6、reduce¶

对每对元素都应用函数并运行到最后结果

reduce((lambda x,y:x+y),[1,2,3,4])
10
import operator,functools
functools.reduce(operator.add,[2,4,6])
12

二、列表推导式¶

列表推导式为从序列中创建列表提供了一个简单的方法。普通的程序通过将一些操作应用于序列的每个成员并通过返回的元素创建列表,或者通过满足特定条件的元素创建子序列。

例如,假设我们创建一个 squares 列表,可以像下面方式:

squares = []
for x in range(10):
     squares.append(x**2)
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

我们同样能够达到目的采用下面的方式:

squares = [x**2 for x in range(10)]
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

这也相当于 squares = map(lambda x: x**2, range(10)),但是上面的方式显得简洁以及具有可读性。

列表推导式由包含一个表达式的括号组成,表达式后面跟随一个 for 子句,之后可以有零或多个 for 或 if 子句。结果是一个列表,由表达式依据其后面的 for 和 if 子句上下文计算而来的结果构成。

例如,如下的列表推导式结合两个列表的元素,如果元素之间不相等的话:

[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
combs = []
for x in [1,2,3]:
    for y in [3,1,4]:
         if x != y:   
            combs.append((x, y))
combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
vec = [-4, -2, 0, 2, 4]
[x*2 for x in vec]
[-8, -4, 0, 4, 8]
[x for x in vec if x >= 0]
[0, 2, 4]
[abs(x) for x in vec]
[4, 2, 0, 2, 4]
freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
[weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
[(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
vec = [[1,2,3], [4,5,6], [7,8,9]]
[num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

列表推导式可使用复杂的表达式和嵌套函数:

from math import pi
[str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

三、嵌套的列表推导式¶

列表推导式可以嵌套。

考虑以下的 3x4 矩阵,一个列表中包含三个长度为4的列表:

matrix = [
     [1, 2, 3, 4],
     [5, 6, 7, 8],
     [9, 10, 11, 12],
 ]

现在,如果你想交换行和列,可以用嵌套的列表推导式:

[[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

像前面看到的,嵌套的列表推导式是对 for 后面的内容进行求值,所以上例就等价于:

transposed = []
for i in range(4):
    transposed.append([row[i] for row in matrix])
transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

反过来说,如下也是一样的:

transposed = []
for i in range(4):
    transposed_row = []
    for row in matrix:
        transposed_row.append(row[i])
    transposed.append(transposed_row)
transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

在实际中,可以使用内置函数组成复杂流程语句。对此种情况 zip() 函数将会做的更好:

list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

代码中使用的星号的说明,参数列表的分拆。 当要传递的参数已经是一个列表,但要调用的函数却只接受分开一个个的参数值。这时候需要把已有的列表拆开来。例如内建函数 range() 需要独立的 start ,stop 参数,可以在调用函数时加一个 * 操作符来自动把参数列表拆开

 
分享到:
举报财经168客户端下载

全部回复

0/140

投稿 您想发表你的观点和看法?

更多人气分析师

  • 张亦巧

    人气2184文章4145粉丝45

    暂无个人简介信息

  • 梁孟梵

    人气2176文章3177粉丝39

    qq:2294906466 了解群指导添加微信mfmacd

  • 指导老师

    人气1864文章4423粉丝52

    暂无个人简介信息

  • 李冉晴

    人气2320文章3821粉丝34

    李冉晴,专业现贷实盘分析师。

  • 王启蒙现货黄金

    人气296文章3134粉丝8

    本人做分析师以来,并专注于贵金属投资市场,尤其是在现货黄金...

  • 张迎妤

    人气1896文章3305粉丝34

    个人专注于行情技术分析,消息面解读剖析,给予您第一时间方向...

  • 金泰铬J

    人气2328文章3925粉丝51

    投资问答解咨询金泰铬V/信tgtg67即可获取每日的实时资讯、行情...

  • 金算盘

    人气2696文章7761粉丝125

    高级分析师,混过名校,厮杀于股市和期货、证券市场多年,专注...

  • 金帝财神

    人气4760文章8329粉丝119

    本文由资深分析师金帝财神微信:934295330,指导黄金,白银,...

FX168财经

FX168财经学院

FX168财经

FX168北美