Python

本章内容

  1. 高阶函数
  2. 装饰器
  3. 闭包
  4. 递归函数
  5. 迭代器和生成器

前言

  接着上一篇函数进行整理。。

一、高阶函数

高阶函数就是将一个函数以参数的形式传入另一个函数

 1 def main_func(func):
 2 # 定义一个主函数,并设置一个参数func
 3 
 4     return func
 5     # 返回func的值,因为我需要传入一个函数,即返回func的返回值
 6 
 7 def func():
 8 # 定义一个函数作为参数传入主函数
 9 
10     return "Lyon"
11     # 返回 "Lyon" 给func()
12 
13 res = main_func(func())
14 # res接收main_func的返回值,将func()的返回值作为参数传入main_func函数
15 
16 print(res)
17 # 打印结果      : Lyon

二、装饰器

什么是装饰器?听名字我们就知道是一个进行装饰的工具,装饰什么?当然是装饰函数,即给原来的函数加上一些功能。

装饰器是由函数去生成的,用于装饰某个函数或者方法或者类(类以后再说),他可以让这个函数在执行之前或者执行之后做一些操作。反正就是给函数加功能。

语法:

1.  def  decorator(func) :

2.    return  func

3.  @decorator             @ + "函数名"  是python中的一种语法糖

4.  def  func() :

5.    pass

学习装饰器,首先得知道上述  @ + "函数名" 这个语法糖 到底进行了些什么操作。

看下面这个等式帮助理解:

@decorator   =   decorator(func)    ,   func   =   decorator的返回值

就利用上述语法作为例子,来说一下语法糖 进行的操作:

首先 @ + "函数名" ---> 将该操作下面的函数的函数名(即func)作为参数传入装饰器函数(即decorator),等装饰器函数执行完之后又将装饰器函数返回值返回给函数名

  • 第一个版本
 1 def decorate(func):
 2 # 定义装饰器函数,func参数接收被装饰函数名
 3 
 4     return func()
 5     # 返回function的返回值给decorate
 6 
 7 @decorate      #给function函数装上decorate函数
 8 def function():
 9 # function最后会接收decorate的返回值
10 
11     return "装饰成功!"
12     # function的返回值为 "装饰成功!"
13 
14 res = function
15 # 进行调用,不要加括号,加了会报错。----> 传递过程在下面
16 
17 print(res)
18 # 打印结果   :"装饰成功!"

函数的调用其实就是调用函数名,而函数名其实就是一个内存地址,方式是通过 括号"( )"进行调用。

传递过程:function --> decorate(function) -->  function()  --> decorate --> function

传递过程注解:函数名 --> decorate中的参数 --> 加括号进行调用 --> 返回decorate --> 返回函数名

通过传递过程我们可以知道,在过程中function已经进行了调用,所以最后我们进行调用的时候是不能在加括号的,因为function此时已经是运行后拿到了返回值。

  • 第二个版本
 1 def decorate(func):
 2 # 定义装饰器函数,func参数接收被装饰函数名
 3 
 4     def inner():
 5     # 这一步的作用通过调用方式基本能看出来了
 6 
 7         return func()
 8         # 将function的返回值给inner
 9 
10     return inner
11     # 将inner内存地址返回给decorate
12 
13 @decorate      #给function函数装上decorate函数
14 def function():
15 # function最后接收的是一个内存地址
16 
17     return "装饰成功!"
18     # function的返回值为 "装饰成功!"
19 
20 res = function()
21 # 利用 ( ) 调用其函数名,函数名现在对应的是inner的内存地址
22 
23 print(res)
24 # 打印结果   :"装饰成功!"

一般我们用的是第二个版本,因为最后调用方式跟我们进行函数调用的方式是一样的。

*语法糖:指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖主要是为程序员提供更实用的编码方式,提高代码的可读性,并有益于更好的编码风格。

通过以上基本已经了解了装饰用的用法,以及原理。

更多示例:

 1 def decorator1(func):
 2     def inner():
 3         return func()
 4     return inner
 5 
 6 def decorator2(func):
 7     def inner():
 8         return func()
 9     return inner
10 
11 @decorator1
12 @decorator2
13 def function():
14     print("执行函数...")
15 function()
多个装饰器装饰同一个函数
 1 def decorator(func):
 2     def inner(name):
 3     #被装饰函数参数所放位置
 4 
 5         return func(name)
 6     return inner
 7 
 8 @decorator
 9 def function(name):
10     print("my name is %s" % name)
11 
12 function("Lyon")
被装饰函数带有参数

 三、闭包

闭包:必须是内部定义的函数(嵌套函数),该函数包含对外部作用域而不是全局作用域名字的引用。

进一步解释:在嵌套函数中,我们可以将函数作为参数(高阶函数)或者返回值进行传递,函数作为一个容器元素,作为一个变量可以去进行赋值。

闭包的作用:

1. 可以不动原函数里面的代码,并给他新增功能的一个手段。(即装饰器)

 1 # 版本一
 2 # 直接函数名调用
 3 def func():
 4 # 定义了一个函数,要给他加功能
 5 
 6     print("我是func")
 7     # 执行func内部操作
 8 
 9     return func
10     # 返回None
11 
12 def decorator(func):
13 # 功能函数
14 
15     print("我是func之前的decorator")
16     # 功能函数中的功能
17 
18     func()
19     # 调用传入的   函数名-->指向内存地址   用()进行调用
20 
21     return decorator
22     # 返回None
23 
24 func = decorator(func)
25 # 将decorator和func的调用操作赋给了  func-->定义的变量名
26 
27 func
28 # 功能实现--->加功能实际上是让他先执行我的功能函数然后再执行我的函数
29 
30 # 版本二
31 # 改变调用方式
32 def decorator(func):
33     def inner():
34         print("我是func之前的decorator")
35         func()
36     return inner
37     # inner并么有进行调用,所以返回给decorator之后还可以用括号进行调用
38 
39 def func():
40     print("我是func")
41     return func
42 
43 func = decorator(func)
44 # 覆盖原来的func
45 
46 func()
47 # 调用装饰后的函数 --> 即返回的 inner的内存地址

这样我们就可以看出,装饰器其实就是利用闭包原理实现的,只不过利用语法糖来简化了我们的调用方式。

 1 def decorator(func):
 2     def inner(*args,**kwargs):
 3         print("我是func之前的decorator")
 4         func(*args,**kwargs)
 5     return inner
 6 def func(*args,**kwargs):
 7     print("我是func")
 8     print(args,kwargs)
 9     return func
10 func = decorator(func)
11 func( ) -->  inner( )
12 
13 加参数版本
加参数版本

2. 需要对某个函数的参数提前赋值

 1 def func():
 2     name = "Lyon"
 3     def inner():
 4         print(name)
 5     return inner
 6 s = func()
 7 print(s.__closure__)
 8 # __closure__方法可以返回闭包函数中引用变量(即name)的取值,__closure__里包含了一个元组(tuple),这个元组中的每个元素是cell类型的对象。
 9 
10 """
11 例子中我们进行调用inner时需要用到name变量。如果我们将name变量定义在inner中,当inner进行调用时,python会先将name存到内存中,等inner执行结束后,python又会把name给清空,那如果我们调用一万次inner,python解释器就要创建一万次再清空一万次,这样的调用过程会浪费很多内存,而闭包函数,他会先将要用的变量创建好,等以后都不用了再将他从内存中清空。
12 所以闭包还可以对所需要用到的参数进行提前赋值,减少内存消耗。
13 """
 1 s = [lambda x: x + i for i in range(10)]
 2 print(s[0](10))
 3 print(s[1](10))
 4 print(s[2](10))
 5 print(s[3](10))
 6 
 7 """
 8 请看完匿名函数后再来怼怼这个问题
 9 
10 """
11 # 翻译版本
12 def func():
13     l = []
14     for i in range(10):
15         def inner(x):
16             return i + x
17         l.append(inner)
18         print(inner)
19     return l
20 res = func()
21 print(res[0](10))
22 print(res[1](10))
23 print(res[2](10))
24 print(res[3](10))
一个比较难的例子

 四、递归函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自己本身,这个函数就是递归函数。既然是调用自身那每次调用,需要解决的问题就应该有所减少,不然这个函数就没有尽头的执行下去。

 1 def counter(num):
 2 # 定义一个函数counter
 3 
 4     print(num)
 5     # 打印num
 6 
 7     if num <= 0:
 8     # 如果num小于等于0
 9 
10         return num
11         # 返回num
12 
13     num -= 1
14     # 必须相对上一次有所减少
15 
16     counter(num)
17     #反复调用,直到return将函数停止运行
18 
19 counter(10)
20 # 调用函数

用递归实现斐波那契数列

1 def counter(n1,n2):
2     if n1 > 1000:
3         return "不搞了!"
4     print(n1)
5     n3 = n1 + n2
6     counter(n2,n3)
7 counter(0,1)

更多资料 --> 安生,大好时光

原文地址:https://www.cnblogs.com/lyonyang/p/7232171.html