day11-python-函数-进阶

day11-python-函数-进阶

编程语言支持通过以下几种方式来解构具体问题:

  • 大多数的编程语言都是 过程式 的,所谓程序就是一连串告诉计算机怎样处理程序输入的指令。C、Unix shells 都是过程式语言。
  • 声明式 语言中,你编写一个用来描述待解决问题的说明,并且这个语言的具体实现会指明怎样高效的进行计算。 SQL 可能是你最熟悉的声明式语言了。 一个 SQL 查询语句描述了你想要检索的数据集,并且 SQL 引擎会决定是扫描整张表还是使用索引,应该先执行哪些子句等等。
  • 面向对象(OOP) 程序会操作一组对象。 对象拥有内部状态,并能够以某种方式支持请求和修改这个内部状态的方法。Smalltalk 和 Java 都是面向对象的语言。 C++ 和 Python 支持面向对象编程,但并不强制使用面向对象特性。
  • 函数式 编程则将一个问题分解成一系列函数。 理想情况下,函数只接受输入并输出结果,对一个给定的输入也不会有影响输出的内部状态。 著名的函数式语言有 scala和 Haskell。

python 是支持多范式编程的语言,支持OOP编程又支持函数式编程。

输入会流经一系列函数。每个函数接受输入并输出结果。函数式风格反对使用带有副作用的函数,这些副作用会修改内部状态,或者引起一些无法体现在函数的返回值中的变化。完全不产生副作用的函数被称作“纯函数”。消除副作用意味着不能使用随程序运行而更新的数据结构;每个函数的输出必须只依赖于输入。

模块化

函数式编程的一个更实用的优点是,它强制你把问题分解成小的方面。因此程序会更加模块化。相对于一个进行了复杂变换的大型函数,一个小的函数更明确,更易于编写, 也更易于阅读和检查错误。

Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

惰性计算:

惰性求值是一种求值策略,它将表达式的求值延迟到需要它的值时,并且避免重复求值。它通常被认为是优化代码的一种策略。它的工作方式是每次处理一个对象,而不是一口气处理和构造整个数据结构,这样做的潜在优点是可以节省大量的内存

与立即求值不同之处在于,Lazy evaluate不会立即对表达式求值,而只在需要结果时才执行。这有点像一个懒惰的学生,只在需要提交作业的时候才做作业。

惰性计算可以提高代码的执行效率,节约内存资源

import sys

a = range(10)
b = range(10000000000000000)
print(sys.getsizeof(a), sys.getsizeof(b)) #48 48

a,b所占空间都是48。这是因为range()从python3就实现了惰性计算,rang()只存储开始、停止、步骤值,并在需要时计算每个项的值,而不是一次就生成所有的值。

其实实现惰性计算的关键就是实现一个生成器(generator

生成器

generator是一个函数用于返回一个可迭代对象[可迭代对象,是指一个对象拥有__next__方法与__iter__方法],generator函数就有点像普通函数中将return 替换成 yield,可以使用next()方法获取生成器对象中的值,直到生成器对象中的值被用尽,抛出StopIteration的异常

创建生成器有两种方式

#方式一
g1 = (num for num in range(1000))

#方式二 yield
def fun1():
    for num in range(1000):
        yield num

g2 = fun1()
print(next(g1), next(g2)) #0 0
print(next(g1), next(g2)) #1 1
print(next(g1), next(g2)) #2 2
print(next(g1), next(g2)) #3 3

注意生成器表达式和列表推导式的区别:生成器表达式两边使用圆括号 "()",而列表推导式则使用方括号 "[]"

g1 = (num for num in range(4))
l1=[num for num in range(4)]
print(type(g1),g1) #<class 'generator'> <generator object <genexpr> at 0x000002ADD2F84270>
print(type(l1),l1) #<class 'list'> [0, 1, 2, 3]

生成器:

import time
import sys
start_time = time.perf_counter()
g1 = (num for num in range(100000000))
end_time = time.perf_counter()
print(end_time-start_time) #1.800013706088066e-06
print(sys.getsizeof(g1)) #104

推导式:

import time
import sys
start_time = time.perf_counter()
g1 = [num for num in range(100000000)]
end_time = time.perf_counter()
print(end_time-start_time) #3.485051600029692
print(sys.getsizeof(g1)) #835128600

从上面的对比可以看出,其实生成器就是惰性求值,而列表推导式是一口气处理和构造整个数据结构的

其他的惰性求值函数

1.zip()

合并两个可以迭代对象用于生成一个元组列表。

2.with open()

with open 它不会读取整个文件内容到内存中,而是返回一个可以遍历的文件对象。正因为它的惰性求值属性,所以它能够有效地读取大的文件,而不会产生内存溢出。

3.lambda 表达式

python lambda

根据python 官网的 Python design Q&A:

Python lambdas are only a shorthand notation if you’re too lazy to define a function.
#如果您懒得定义函数,那么Python lambdas只是一种速记符号。

python 中的 lambda本质还是一个函数,只不过它是一个匿名函数而已

python lambda语法

lambda arguments: expression

语法由三部分组成:lambda关键字 、arguments 函数的输入参数、expression 表达式,相当于函数体,但这里的表达式只支持一个。表达式的输出结果就是函数的返回值。

需要注意的是lambda表达式中不能包含任意的语句 类如:return, try, assert, if, for, raise等

示例:

l1 = lambda x, y: x + y
l2 = lambda x, y=3: x + y
l3 = lambda *args: sum(args)
print(type(l1)) # <class 'function'>
print(l1(1, 3))		#4
print((lambda x, y: x + y)(1, 3))	#4
print(l2(1))		#4
print(l3(1, 3, 4))	#8

高阶函数

如果一个函数包含其他函数作为参数或返回函数,则称为高阶函数。它是函数式编程的一个重要概念。Python作为一种非常灵活的编程语言,支持使用高阶函数。Python中有一些内置的高阶函数,我们也可以自己定义高阶函数。

常用高阶函数:

Map

Map()函数接受两个参数:一个函数和一个可迭代对象。映射函数将应用于可迭代对象中的每个元素。函数返回一个包含映射元素的迭代器。

例子:

def fun1(x):
    return x*2
r=map(fun1,[1,2,3,4])
print(list(r)) #输出[2, 4, 6, 8]

上面列子等价于lambda表达式

r1=map(lambda x:x*2,[1,2,3,4])
print(list(r1))

reduce

reduce()函数来自Python内置模块functools。它的本质是将一个函数累积地应用到可迭代对象中的所有元素上,并生成一个单一值。Reduce()函数接受3个参数:一个输入函数,一个可迭代函数和一个可选初始化表达式。返回一个单一的值。

reduce()函数的结果与对Iterable反复使用函数是一样的。

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

示例:

nums = [1, 2, 3, 4]
to_str = reduce(lambda x, y: x + y, nums)
print(to_str) #10

filter

filter与map类似也接受两个参数一个函数一个是可迭代对象,筛选函数将应用于每个元素,filter()函数返回一个包含筛选过的元素的迭代器。

示例:

nums = [1, 2, 3, 4, 5, 6, 7, 8]
to_str = filter(lambda x: x % 2 == 0, nums)
print(list(to_str)) #[2, 4, 6, 8]

sorted

Python的内置排序方法是一个高阶函数,它有一个接收函数的关键参数,该函数定义了如何比较元素。

示例,按照字符长度比较元素

names = ['HELLO', 'python', 'hi', 'wow']
names = sorted(names, key=len)
print(names) #['hi', 'wow', 'HELLO', 'python']
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值