zoukankan      html  css  js  c++  java
  • 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)

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

  • 相关阅读:
    奋力拼搏,永不言弃
    软件工程最终总结
    人生第一次JAVA编程,电梯(并不算完成版),以及IDEA里使用git
    尝试单元测试
    作业2的回答
    word count程序,以及困扰人的宽字符与字符
    关于未成品的问题:字符类型和其他种种
    随手一写,简单的四则运算练习
    浏览器缓存分析
    Codeforces Round #582 (Div. 3)
  • 原文地址:https://www.cnblogs.com/lyonyang/p/7232171.html
Copyright © 2011-2022 走看看