python复杂函数表达_Python高阶函数和推导式

本文介绍了Python中的一些高级特性,包括列表推导式、生成器表达式、lambda匿名函数以及reduce函数的使用。通过实例展示了如何利用这些特性简化代码,提高代码的可读性和效率。
摘要由CSDN通过智能技术生成

今天遇到一个曾经学 C 语言时的一个问题, 求水仙花数水仙花数是指一个 3 位数,它的每个位上的数字的 3 次幂之和等于它本身

我给出这样一个答案

from functools import reduce

[ i for i in range(100, 1000) if reduce(lambda n1, n2: n1+n2**3,(int(j) for j in str(i)), 0 )==i]

其实这个答案并不简洁, 一点也不 pythonic. 但是涉及到了一些 python 的语法(奇巧淫技?)和知识点列表推导式

列表推导式配合其他的东西

生成器表达式

字符串是个 sequence 类型

lambda 匿名函数

reduce 函数

列表推导式

# 一个0到9的列表

[i for i in range(10)]

简言之, 列表推导式可以从一个可迭代对象得到一个列表.

列表推导式非常顺手, 舒服!!!

首先, 平常我们可以使用上面的例子得到可以迅速的得到一个列表.

好像也没什么用啊, 但是搭配其他的东西, 威力还是很大的

filter

# 得到所有的奇数

[i for i in range(10) if i%2]

过滤, 配合if语句, 完全代替filter函数 当然判断的地方我们可以更复杂, 也可以使用一个函数(那就是 filter 了), 甚至几个函数(比 filter 要强, 不过也没必要, pythonic).

map

# 平方一下

[i*i for i in range(10)]

# 一起使用

[i*i for i in range(10) if i%2]

在 i 的位置, 我们可以做些操作, 简单的平方, 或者执行一个函数foo(i), 这就代替了 map

map?

# 也算是map了

[True if i%2 else False for i in range(10)]

# 当然也可这样

[i**2 if i%2 else False for i in range(10)]

# 配合后面的if(filter)

[True if i%2 else False for i in range(10) if i ]

也算是 map 了, 其实这里用到的式 if/else 的三元表达式

v = a if a>b else b

生成器表达式

生产器表达式, 将[]换成()就可以了, 其他一样, 生成器一般就是三个应用:减少内存占用, 提升性能

函数挂起, 实现异步

无限的生成器?

当然, 这里的生成器没什么用, 没必要

生产器表达式就是这些内容, 但是生成器的其他内容留个坑吧 包括生成器函数

yield from 语句

继续生成器: next send for

...

reduce

一般我们入门 python 的时候, 经常把 map filter reduce 当作高阶函数作为进阶学习

其实现在看也不高, 当然, reduce 应该是三个里最高的吧 hh

它在functools里

# reduce函数

reduce(function, sequence[, initial]) -> value

# 从1加到100

def foo(n1, n2):

return n1+n2

reduce(foo, range(101))

reduce? 减少? 我们看下上面的计算的过程参数 function 必须有两个参数, 必须返回一个值

现在 range(101)相当于 0~100首先把 0,1 给 foo, 计算得一个值 1

把计算获得的值(这里是 1)和下一个值(这里是 2), 分别传给 foo 第一个参数和第二个参数, 再返回一个值, 作为下一次调用 foo 的第一个参数

这样, foo 依次调用的情况是(0, 1)->1, (1, 2)->3, (3, 3)->6, (6, 4)->10, (10, 5)->15, ...

最后得到的是一个结果(并不是说一个值, 应该说是最后一次 foo 调用的结果)

描述 reduce 的作用: 函数会对参数序列中元素进行累积

几乎是废话, 不如思考一下上面的计算过程(foo 被调用的过程和传递的参数)

最后一个可选参数initial是一个初始化值, 就是相当于把这个值放在序列最前面, 如果上面的例子给一个 initial, 那么调用情况就是

(initial, 0)->initial, (initial, 0)->initial, (initial, 1)->initial+1, (initial+1, 2)->initial+3, ...

lambda 匿名函数

对于一个简单的函数, 我们不需要def定义, 甚至这个函数都没有名字, 但是 lambda 函数一般不能写的太复杂, 甚至不能换行(要用\)

一般用在我们需要这样一个简单的函数, 而且还不需要名字(不需要引用, 用一次就不用了), 没错, 典型的就是上面map filter reduce

它们都需要一个函数作为参数(所以这是高阶?)

# 改写上面的例子

# lambda 参数: 表达式

# 表达式的返回值即函数的返回值

reduce(lambda n1, n2: n1+n2, range(101))

# 其实函数也可被赋值

foo = lambda v: v*2

[foo(i) for i in range(10)]

sequence

字符串是序列 sequence 类型, 再 reduce 那里我们可以看到 range 也是 当我们说到这类是...类型时, 就是说这个对象实现了一些魔术方法(应该说实现了该类型的协议), 具有了一些操作

就序列类型来说, 常见的有 list, str, tuple, bytes, range, generator等

实现了__getitem__, 实现整数索引(字典不是用整数, 是映射类型)

__len__, 支持 len, 返回长度(字典也实现了)

__contains__, 支持in关键字

...

挖的坑有点大了, 以后再说

其实坑还可以更大, 比如水仙花数中的int(i)**2为什么要 int 呢, 直接i**2不就行了吗?

你在 JavaScript 里就行, 这就涉及到 python 强类型的特点了.

不说了不说了, 坑估计填不了了

水平有限, 如果有误, 欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值