Python 中更多的特殊功能

Python 是一种很棒的编程语言!它是开发人工智能和机器学习应用程序最流行的语言之一。Python 语法易于学习,并具有一些使其与其他语言区别开来的特殊功能。在本教程中,我们将讨论 Python 编程语言的一些独特属性。

完成本教程后,您将了解:

  • 列表和字典推导式结构
  • 如何使用 zip 和 enumerate 函数
  • 什么是函数上下文和装饰器
  • Python 中生成器的用途是什么

使用我的新书《Python for Machine Learning》来启动您的项目,其中包括分步教程和所有示例的 Python 源代码文件。

让我们开始吧。

Python 特殊功能
图片由 M Mani 拍摄,保留部分权利。

教程概述

本教程分为四个部分;它们是

  1. 列表和字典推导式
  2. Zip 和 enumerate 函数
  3. 函数上下文和装饰器
  4. Python 中的生成器以及 Keras 生成器的示例

导入部分

本教程中使用的库在下面的代码中导入。

列表推导式

列表推导式提供了一种从现有列表创建新列表的简短、简单语法。例如,假设我们需要一个新列表,其中每个新项都是旧项乘以 3。一种方法是使用如下所示的 for 循环

使用列表推导式的较短方法只需要一行代码

您甚至可以根据特殊条件创建新列表。例如,如果我们只想将偶数添加到新列表

还可以将 else 与上述相关联。例如,我们可以保留所有偶数不变,并将奇数替换为零

列表推导式也可以用于替换嵌套循环。例如

可以使用以下方式完成,在列表推导式中有两个“for”

语法

列表推导式的语法如下所示

newlist = [expression for item in iterable if condition == True]

或者

newList = [expression if condition == True else expression for item in iterable]

想开始学习用于机器学习的 Python 吗?

立即参加我为期7天的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

字典推导式

字典推导式与列表推导式类似,只是现在我们有(键、值)对。这是一个示例;我们将通过将字符串“number ”连接到每个值来修改字典的每个值

同样,条件表达式也是可能的。我们可以根据新字典中的条件选择添加(键,值)对。

Python 中的枚举器和 Zip

在 Python 中,可迭代对象定义为任何可以一次返回其所有项的数据结构。这样,您就可以使用 for 循环逐一进一步处理所有项。Python 有两个额外的构造,使 for 循环更容易使用,即 enumerate()zip()

枚举

在传统编程语言中,您需要一个循环变量来遍历容器的不同值。在 Python 中,这通过允许您访问循环变量以及可迭代对象的一个值来简化。enumerate(x) 函数返回两个可迭代对象。一个可迭代对象从 0 到 len(x)-1 变化。另一个是其值等于 x 项的可迭代对象。示例如下所示

默认情况下,enumerate 从 0 开始,但如果指定,我们可以从其他数字开始。这在某些情况下很有用,例如

Zip

Zip 允许您创建元组的可迭代对象。Zip 将多个容器 $(m_1, m_2, \ldots, m_n)$ 作为参数,并通过配对每个容器中的一个项来创建第 i 个元组。第 i 个元组是 $(m_{1i}, m_{2i}, \ldots, m_{ni})$。如果传递的对象长度不同,则形成的元组总数长度等于传递对象的最小长度。

下面是使用 zip()enumerate(). 的示例

函数上下文

Python 允许嵌套函数,您可以在外部函数中定义内部函数。Python 中的嵌套函数有一些很棒的特性。

  • 外部函数可以返回内部函数的句柄。
  • 内部函数保留其所有环境和局部变量,以及其包含函数中的变量,即使外部函数执行结束。

下面给出一个示例,并在注释中进行解释。

Python 中的装饰器

装饰器是 Python 的一个强大功能。您可以使用装饰器自定义类或函数的工作方式。将它们视为应用于另一个函数的函数。使用带有 @ 符号的函数名来在被装饰函数上定义装饰器函数。装饰器将函数作为参数,提供了很大的灵活性。

考虑以下函数 square_decorator(),它接受一个函数作为参数,也返回一个函数。

  • 内部嵌套函数 square_it() 接受一个参数 arg
  • square_it() 函数将该函数应用于 arg 并将结果平方。
  • 我们可以将诸如 sin 的函数传递给 square_decorator(),它反过来将返回 $\sin^2(x)$
  • 您还可以编写自己的自定义函数,并使用特殊的 @ 符号在其上使用 square_decorator() 函数,如下所示。函数 plus_one(x) 返回 x+1。此函数由 square_decorator() 装饰,因此我们得到 $(x+1)^2$。

Python 中的生成器

Python 中的生成器允许您生成序列。生成器不是返回一个 return 语句,而是通过多个 yield 语句返回多个值。第一次调用函数时,返回第一个 yield 值。第二次调用时,返回第二个 yield 值,依此类推。

生成器函数可以通过 next() 调用。每次调用 next() 时,都会返回下一个 yield 值。下面显示了一个生成斐波那契序列直到给定数字 x 的示例。

Keras 数据生成器示例

生成器的一个用途是 Keras 中的数据生成器。它很有用,因为我们不想将所有数据都保留在内存中,而是想在训练循环需要时即时创建它。请记住,在 Keras 中,神经网络模型是分批训练的,因此生成器用于发出数据批次。下面的函数来自我们之前的文章,“使用 CNN 进行金融时间序列预测

上述函数的作用是选取 pandas 数据框的随机行作为起点,然后剪切接下来的几行作为一次性时间间隔样本。这个过程重复多次,将许多时间间隔收集到一批中。当我们收集到足够的时间间隔样本时,在上述函数的倒数第二行,使用 yield 命令分派批次。您可能已经注意到,生成器函数没有 return 语句。在这个示例中,函数将永远运行。这很有用且必要,因为它允许我们的 Keras 训练过程运行任意数量的 epoch。

如果我们不使用生成器,我们将需要将数据框转换为所有可能的时间间隔,并将它们保存在内存中以供训练循环使用。这将是大量重复数据(因为时间间隔是重叠的),并且会占用大量内存。

由于它很有用,Keras 在库中预定义了一些生成器函数。下面是 ImageDataGenerator() 的一个示例。我们已经在 x_train 中加载了 32x32 图像的 cifar10 数据集。数据通过 flow() 方法连接到生成器。next() 函数返回下一批数据。在下面的示例中,对 next() 进行了 4 次调用。在每种情况下,都会返回 8 张图像,因为批次大小为 8。

下面是完整的代码,它还在每次调用 next() 后显示所有图像。

进一步阅读

如果您想深入了解,本节提供了更多关于该主题的资源。

Python 文档

书籍

API 参考

总结

在本教程中,您了解了 Python 的一些特殊功能。

具体来说,你学到了:

  • 列表和字典推导式的目的
  • 如何使用 zip 和 enumerate
  • 嵌套函数、函数上下文和装饰器
  • Python 中的生成器和 Python 中的 ImageDataGenerator

您对本文讨论的 Python 功能有任何疑问吗?请在下面的评论中提出您的问题,我将尽力回答。

 

掌握用于机器学习的 Python!

Python For Machine Learning

更有信心用 Python 编写代码

...从学习实用的 Python 技巧开始

在我的新电子书中探索如何实现
用于机器学习的 Python

它提供自学教程,包含数百个可运行代码,为您提供包括以下技能:
调试性能分析鸭子类型装饰器部署等等...

向您高层次地展示 Python 工具箱,用于
您的项目


查看内容

Python 中的更多特殊功能的 8 条回复

  1. Gerard Elifuraha Mtalo,博士 2021 年 12 月 18 日晚上 8:11 #

    亲爱的 Jason Brownlee(博士)和 Mehreen Saeed,

    感谢你们毫无保留地在全球范围内分享有用的知识。我热切地关注你们的许多教程。

    我观察到在使用 set() 函数和 zip() 函数时有以下行为。

    >>> shapes=zip(name,sides,colors)
    >>> shapes

    >>> b=set(shapes)
    >>> b
    {('Pentagon', 5, 'blue'), ('Triangle', 3, 'red'), ('Hexagon', 6, 'yellow'), ('Square', 4, 'green')}
    >>> print(b)
    {('Pentagon', 5, 'blue'), ('Triangle', 3, 'red'), ('Hexagon', 6, 'yellow'), ('Square', 4, 'green')}
    >>> shapes

    >>> b=set(shapes)
    >>> shapes

    >>> print(b)
    set()
    >>> b
    set()

    有没有人能告诉我为什么我第二次执行赋值 b=set(shapes) 时 b 会变成一个空集合?

    请注意,对象 shapes 在内部仍定义为

    • Adrian Tam
      Adrian Tam 2021 年 12 月 19 日下午 1:57 #

      在 Python 2 中,您的代码应该会产生您想要的结果。但在 Python 3 中,zip 的输出是一个生成器,只能读取一次。因此,如果您第二次运行 b=set(shapes),它将为空。

  2. Gerard Elifuraha Mtalo,博士 2021 年 12 月 18 日晚上 8:22 #

    亲爱的 Jason Brownlee 和 Mehreen,

    我注意到变量“shapes”的内部表示在早些时候发送的注释中被“过滤掉了”。

    我还想告诉您,我的代码是在安装在 Windows 10 上的 Python 3.7.7 shell 上运行的。

    Gerard Elifuraha Mtalo

  3. Anthony The Koala 2022 年 1 月 9 日下午 6:24 #

    亲爱的授权答复者,

    我尝试了“函数上下文”部分

    在代码中,您有两个 circle 函数。

    输出

    请问:
    我屏蔽了第一个 circle 函数。第一个 circle 函数的目的是什么?它从未被调用过?

    这两个 circle 函数的目的是否是为了函数重载?

    谢谢你,
    悉尼的Anthony

    • Anthony The Koala 2022 年 1 月 10 日凌晨 2:07 #

      澄清一下,即使是函数“def circle(r)”的第一个版本,第一个函数也永远不会被调用。

      重载不像其他语言那样工作

      输出

      结论
      * 显然 python 不允许重载,如运行时错误所示
      * 但它没有回答为什么可以有两个函数。请注意,第一个函数根本没有被调用。

      输出显示只调用了第二个函数。第一个函数从未被调用/执行。

      谢谢你
      悉尼的Anthony

      • James Carmichael 2022 年 1 月 10 日上午 11:13 #

        感谢您的反馈和关注,Anthony!

        • Anthony The Koala 2022 年 1 月 10 日上午 11:45 #

          有两个函数,而且只有第二个函数被调用,这是怎么回事?

          通过注释掉第一个函数来屏蔽它并没有什么害处。

          我不理解本教程这一部分的要点。

          谢谢你,
          悉尼的Anthony

          • Adrian Tam
            Adrian Tam 2022 年 4 月 16 日上午 5:28 #

            要理解这种行为,您需要记住 Python 中一切皆对象。这是与许多其他语言的主要区别。当您定义函数 circle() 并再次定义它时,后面的定义将优先,因为名称 circle 被重新分配给新的函数对象。同样,如果您可以从函数返回一个整数,您也可以返回一个函数,因为从 Python 的角度来看,整数和函数都是对象。它们没有太大区别。

            因此,在您的代码中,调用的不是第二个函数。而是最新定义的 circle 被调用了。

发表评论

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。