Python 简明教程

Python - Quick Guide

Python - Overview

Python 是一种高级、多范例编程语言。由于 Python 是一种基于解释器的语言,因此与其他一些主流语言相比,它更容易学习。Python 是一种动态类型语言,具有非常直观的数据类型。

Python 是一种开源跨平台编程语言。它可以在所有主流操作系统平台 Linux、Windows 和 Mac OS 上使用(与 GNU 通用公共许可证兼容)。

Python 的设计理念强调简单、可读性和明确性。Python 以其包含电池的方法而闻名,因为 Python 软件随附的标准函数和模块库非常全面。

Python 的设计理念在中得到记录。它包含十九条格言,例如 -

  1. 优美胜于丑陋

  2. 明确胜于含蓄

  3. 简单胜于复杂

  4. 复杂胜于繁琐

要获得完整的 Python 禅宗文档,请在 Python shell 中键入 -

>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Python 支持命令式、结构化和面向对象编程方法。它还提供函数式编程的功能。

Python - History

一位荷兰程序员 van Rossum 创建了 Python 编程语言。在 80 年代末,他曾在荷兰计算机科学研究所 CWI 从事 ABC 语言开发。1991 年,范罗苏姆构想并发布了 Python 作为 ABC 语言的继承者。

对于许多门外汉来说,“Python”一词与一种蛇类有关。然而,范罗苏姆将选择 Python 这个名称归功于 BBC 上的一部流行喜剧系列剧“Monty Python’s Flying Circus”。

作为 Python 的首席架构师,开发者社区授予他“仁慈独裁者终身(BDFL)”的称号。然而,2018 年,范罗苏姆放弃了这个称号。此后,Python 参考实现的开发和分发由非营利组织处理。

Python 历史上的重要阶段 -

Python 0.9.0

Python 最早发布的版本是 0.9。它于 1991 年 2 月发布。它提供对面向对象编程核心原则的支持。

Python 1.0

1994 年 1 月,版本 1.0 发布,配备功能性的编程工具,例如对复数的支持等功能。

Python 2.0

下一个主要版本 − Python 2.0 于 2000 年 10 月发布。其中包含许多新功能,例如列表解析、垃圾回收和 Unicode 支持。

Python 3.0

Python 3.0 是 Python 的一个彻底修改的版本,于 2008 年 12 月发布。这次修改的主要目的是消除 Python 2.x 版本中出现的很多差异。Python 3 已反向移植到 Python 2.6。它还包含一个名为 python2to3 的实用程序,以方便 Python 2 代码自动转换为 Python 3。

EOL for Python 2.x

即使在 Python 3 发布之后,Python 软件基金会仍继续为 Python 2 分支提供增量微版本支持,直至 2019 年。然而,它决定在 2020 年年底停止支持,届时 Python 2.7.17 是该分支中的最后一个版本。

Current Version

同时,Python 3.x 分支已集成了越来越多的功能。截至目前,Python 3.11.2 是当前稳定版本,于 2023 年 2 月发布。

What’s New in Python 3.11?

Python 3.11 版本最重要的特性之一是速度显着提高。据 Python 官方文档称,此版本比前一版本(3.10)快 60%。它还指出,标准基准套件显示执行速度提高了 25%。

  1. Python 3.11 具有更好的异常消息处理。现在,当发生异常时,它不再生成冗长的回溯,而是获取导致错误的确切表达式。

  2. 根据 PEP 678 的建议, add_note() 方法已添加到 BaseException 类中。您可以在 except 子句中调用此方法,并传递自定义错误消息。

  3. 它还在模块中添加了函数。它返回给定数的立方根。

  4. 标准库中添加了一个新模块 tomllib 。可以使用 tomlib 模块函数对 TOML(Tom’s Obvious Minimal Language)进行解析。

Python - Features

在本章中,我们重点介绍 Python 的一些重要特性,使其广受欢迎。

Python is Easy to Learn

这是 Python 流行最重要的原因之一。Python 有一组有限的关键字。它的特点是语法简单、使用缩进避免大括号的混乱,以及无需事先声明变量的动态类型,这有助于初学者快速轻松地学习 Python。

Python is Interpreter Based

任何编程语言中的指令都必须转换为机器码以便处理器执行它们。编程语言要么是基于编译器的,要么是基于解释器的。

在编译器的情况下,将生成整个源程序的机器语言版本。即使只有一条错误语句,转换也会失败。因此,对于初学者来说,开发过程很繁琐。C 家族语言(包括 C、C++、Java、C Sharp 等)是基于编译器的。

Python 是一种基于解释器的语言。解释器一次从源代码中获取一条指令,将其转换为机器码并执行。在第一次出现错误之前,指令将被执行。通过此功能,可以更轻松地调试程序,从而证明这对初学者水平的程序员逐渐建立信心非常有用。因此,Python 是一种对初学者友好的语言。

Python is Interactive

Python 标准发行版带有工作于 REPL(读取-求值-打印-循环)原理的交互式外壳程序。该外壳程序会显示 Python 提示符 >>>。你可以键入任何有效的 Python 表达式并按回车。Python 解释器会立即返回响应并恢复提示读取下一个表达式。

>>> 2*3+1
7
>>> print ("Hello World")
Hello World

交互模式对于熟悉库并测试其功能特别有用。你可以在编写程序之前在交互模式中尝试较小的代码片段。

Python is MultiParadigm

Python 是一门完全的面向对象的语言。Python 程序中的所有内容都是对象。然而,Python 巧妙地封装了其面向对象的属性以用作命令式语言或过程化语言,比如 C。此外,Python 还提供了一些类似于函数式编程的功能。另外,已开发出一些第三方工具来支持其他编程范例,如面向方面的编程和逻辑编程。

Python’s Standard Library

尽管它只有很少的关键词(仅三十五个),但 Python 软件仍发行有一个由大量模块和包组成的标准库。因此,Python 开箱即用地支持序列化、数据压缩、互联网数据处理等编程需求。Python 因其“附带电池”的方式而闻名。

python important features

Python is Open Source and Cross Platform

可以从 https://www.python.org/downloads/ 下载 Python 标准发行版,没有任何限制。你可以下载针对各种操作系统平台的预编译二进制文件。此外,源代码也是免费提供的,这就是它属于开源范畴的原因。

Python 软件(以及文档)在 Python Software Foundation License 下发行。它是一个 BSD 风格的宽容软件许可证,且与 GNU GPL(通用公共许可证)兼容。

Python 是一种跨平台语言。预编译二进制文件可用于在各种操作系统平台(如 Windows、Linux、Mac OS、Android OS)上使用。Python 的参考实现称为 CPython,是用 C 编写的。你可以下载源代码并为你的操作系统平台编译它。

Python 程序首先编译成中间平台无关字节码。然后,解释器内的虚拟机执行字节码。此行为使 Python 成为一种跨平台语言,因此 Python 程序可以轻松地从一个操作系统平台移植到另一个平台。

Python for GUI Applications

Python 的标准发行版有一个称为 TKinter 的优秀的图形库。它是针对广受欢迎的 GUI 工具包 TCL/Tk 的 Python 端口。你可以在 Python 中构建有吸引力且用户友好的 GUI 应用程序。GUI 工具包通常用 C/C++ 编写。其中许多已移植到 Python 中。例如 PyQt、WxWidgets、PySimpleGUI 等。

Python’s Database Connectivity

几乎任何类型的数据库都可以用作 Python 应用程序的后端。DB-API 是一组数据库驱动程序软件规范,允许 Python 与关系数据库通信。通过许多第三方库,Python 也能处理 NoSQL 数据库,如 MongoDB。

Python is Extensible

可扩展性一词意味着添加新特性或修改现有特性的能力。如前所述,CPython(Python 的参考实现)是用 C 编写的。因此,人们可以轻松地用 C 编写模块/库,并将它们合并到标准库中。还有其他 Python 实现,如 Jython(用 Java 编写)和 IPython(用 C# 编写)。因此,可以在这些实现中分别用 Java 和 C# 编写并合并新功能。

Python’s Active Developer Community

由于 Python 的流行和开源特性,大量的 Python 开发者经常在网上论坛和会议中互动。Python Software Foundation 也有大量成员,参与组织的使命“促进、保护和推进 Python 编程语言”。

Python 也获得了显着的机构支持。主要 IT 公司 Google、Microsoft 和 Meta 通过准备文档和其他资源做出了很大贡献。

Python vs C++

Python 和 C++ 都是最流行的编程语言。它们俩都有各自的优点和缺点。在本章中,我们将了解它们的特性。

Compiled vs Interpreted

与 C 一样,C++ 也是基于编译器的语言。编译器将整个代码转换成特定于正在使用的操作系统和处理器架构的机器语言代码。

Python 是基于解释器的语言。解释器逐行执行源代码。

Cross platform

当在 Linux 上编译 C++ 源代码(例如 hello.cpp)时,它只能在任何其他带有 Linux 操作系统的计算机上运行。如果需要在其他操作系统上运行,则需要进行编译。

Python 解释器不生成编译后的代码。源代码在每次运行在任何操作系统时都会被转换为字节码,而不会有任何更改或额外的步骤。

Portability

Python 代码可以轻松地从一个操作系统移植到另一个操作系统。C++ 代码不可移植,因为它在操作系统更改时必须重新编译。

Speed of Development

C++ 程序被编译为机器代码。因此,其执行速度比基于解释器的语言更快。

Python 解释器不会生成机器代码。每次执行程序时都会将中间字节码转换为机器语言。

如果要频繁使用程序,则 C++ 比 Python 更有效率。

Easy to Learn

与 C 相比,Python 具有更简单的语法。其代码更具可读性。编写 C 代码一开始似乎令人望而生畏,因为语法规则复杂,例如使用花括号和分号来结束句子。

Python 不使用花括号来标记一个语句块。相反,它使用缩进。相同缩进级别的语句标记一个块。这使得 Python 程序更具可读性。

Static vs Dynamic Typing

C++ 是一种静态类型语言。存储数据的变量的类型需要一开始就声明。未声明的变量无法使用。一旦变量被声明为特定类型,则只能存储该类型的变量。

Python 是一种动态类型语言。它不要求在给变量赋值之前对其进行声明。由于变量可以存储任何类型的数据,因此称为动态类型。

OOP Concepts

C 和 Python 都实现了面向对象编程的概念。C 比 Python 更接近 OOP 理论。C++ 支持数据封装的概念,因为变量的可见性可以定义为 public、private 和 protected。

Python 没有定义可见性的规定。与 C++ 不同,Python 不支持方法重载。因为它是一种动态类型,所以所有的方法本质上都是多态的。

C 实际上是 C 的一个扩展。可以说在 C 中添加了额外的关键字,以便它支持 OOP。因此,我们可以在 C 中编写一个 C 类型面向过程的程序。

Python 是完全的面向对象语言。Python 的数据模型是这样的,即使你可以采用面向过程的方法,但 Python 的内部使用的是面向对象的方法。

Garbage Collection

C 使用指针的概念。C 程序中未使用的内存不会自动清除。在 C 中,垃圾回收过程是手动进行的。因此,C 程序可能面临与内存相关的异常行为。

Python 具有自动垃圾回收机制。因此,Python 程序更健壮,不太容易出现与内存相关的问题。

Application Areas

因为 C++ 程序直接编译为机器代码,所以它更适合于系统编程、编写设备驱动程序、嵌入式系统和操作系统实用程序。

Python 程序适合于应用程序编程。它今天的主要应用领域是数据科学、机器学习、API 开发等。

下表总结了 C++ 和 Python 之间的对比:

Python - Hello World Program

Hello World 程序是一种用通用编程语言编写的基础计算机代码,用作测试程序。它不请求任何输入,并在输出控制台上显示一条 Hello World 消息。它用于测试编译并运行该程序所需的软件是否已正确安装。

使用 Python 解释器非常容易地显示 Hello World 消息。从操作系统的一个命令终端启动解释器,并从 Python 提示符发出以下 print 语句:

PS C:\Users\mlath> python
Python 3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print ("Hello World")
Hello World

同样,Hello World 消息也打印在 Linux 中。

mvl@GNVBGL3:~$ python3
Python 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print ("Hello World")
Hello World

Python 解释器还在脚本模式下工作。打开任何文本编辑器,输入以下文本并保存为 Hello.py

print ("Hello World")

对于 Windows 操作系统,打开命令提示符终端 (CMD),然后按如下所示运行程序 −

C:\Python311>python hello.py
Hello World

终端会显示 Hello World 消息。

hello world

在 Ubuntu Linux 上工作时,必须遵循以下步骤,保存代码并从 Linux 终端中运行。我们使用 vi 编辑器来保存程序。

run on linux terminal

从 Linux 终端运行程序

mvl@GNVBGL3:~$ python3 hello.py
Hello World

在 Linux 中,您可以将 Python 程序转换成一个可自执行的脚本。代码中的第一条语句必须是一个 Shebang。它必须包含 Python 可执行文件的路径。在 Linux 中,Python 已安装在 /usr/bin 目录中,且可执行程序的名称是 python3。因此,我们将这一语句添加到 hello.py 文件中

#!/usr/bin/python3
print ("Hello World")

您还需要使用 chmod +x 命令为文件授予可执行权限

mvl@GNVBGL3:~$ chmod +x hello.py

接着,您可以运行带有以下命令行的程序:

mvl@GNVBGL3:~$ ./hello.py

output 如下所示:

output hello world

因此,我们能够使用解释器模式和脚本模式在 Python 中编写和运行“Hello World”程序。

Python - Application Areas

Python 是一种通用编程语言。它适用于开发广泛的软件应用程序。在过去几年中,Python 成为开发人员在以下应用领域中的首选语言:

Python for Data Science

Python 近期在受欢迎排行榜上的扶摇直上很大程度上归功于它的数据科学库。对于数据科学家来说,Python 已成为一项必备技能。如今,实时网络应用、移动应用和其它设备会生成海量数据。Python 的数据科学库帮助公司从这些数据中生成商业洞察。

NumPy、Pandas 和 Matplotlib 等库被广泛用于将数学算法应用于数据,并生成可视化效果。Anaconda 和 ActiveState 等商业和社区 Python 发行版中捆绑了数据科学所需的所有必要库。

Python for Machine Learning

TensorFlow 和 Scikit-learn 等 Python 库有助于根据过去的构建模型来预测趋势,例如客户满意度、股票的预测值等。机器学习应用包括(但不限于)医学诊断、统计套利、购物篮分析、销售预测等。

Python for Web Development

Python 的网络框架是快速网络应用开发的催化剂。Django、Pyramid 和 Flask 在网络开发者社区中非常流行,这些框架让开发和部署简单又复杂的网络应用变得非常容易。

最新版本的 Python 提供异步编程支持。现代 Web 框架利用此功能开发快速且高性能的 Web 应用程序和 API。

Python for Computer Vision and Image processing

OpenCV 是一个广泛流行的图像捕捉和处理库。图像处理算法从图像中提取信息,重构图像和视频数据。计算机视觉使用图像处理来进行面部检测和模式识别。OpenCV 是一个 C++ 库。它的 Python 移植版被广泛用于快速开发这项功能。

计算机视觉的一些应用领域包括机器人技术、工业监控和自动化、生物识别技术等。

Python for Embedded Systems and IoT

Micropython ( https://micropython.org/ ),一个专用于微控制器(如 Arduino)的轻量级版本。许多自动产品、机器人、物联网和自助终端应用都是围绕 Arduino 而构建的,并用 Micropython 进行编程。树莓派也是一个非常流行的低成本单板计算机,可用于这些类型的应用。

Python for Job Scheduling and Automation

Python 在自动化 CRON(按时执行命令)作业中找到了它的第一个应用。某些任务(如定期数据备份)可以用 Python 脚本编写,计划由操作系统计划程序自动调用。

许多软件产品(如 Maya)嵌入了 Python API,用于编写自动化脚本(类似于 Excel 微控件)。

Try Python Online

如果您是 Python 新手,在计算机上安装 Python 软件之前,最好通过尝试众多在线资源中的其中一个资源熟悉一下该语言的语法和功能。

您可以从 Python 官方网站 https://www.python.org/ 的主页启动 Python 交互式 shell。

pythons official website

在 Python 提示符 (>>>) 前面,可以输入并计算任何有效的 Python 表达式。

python code

Tutorialspoint 网站也设有 Coding Ground 专区:

在该处,您可以为包括 Python 在内的各种语言查找在线编译器。访问 https://www.tutorialspoint.com/execute_python_online.php 。您可以体验使用 Python 解释器的交互模式和脚本模式。

python coding ground

Python - Interpreter

Python 是一种基于解释器的语言。在 Linux 系统中,Python 的可执行文件已安装在 /usr/bin/ 目录中。对于 Windows,可执行文件 (python.exe) 位于安装文件夹中(例如 C:\python311 )。在本章中,您将 how Python interpreter works ,它的交互模式和脚本模式。

Python 代码一次只执行一个语句方法。Python 解释器有两个组件。翻译器检查语句的语法。如果发现正确,它会生成中间字节码。有一个 Python 虚拟机,然后将字节代码转换为本机二进制代码并执行它。下图说明了该机制:

python interpreter

Python 解释器具有交互模式和脚本模式。

Interactive Mode

当从命令行终端启动且没有任何其他选项时,将出现 Python 提示符 >>> ,并且 Python 解释器将基于 REPL (Read, Evaluate, Print, Loop) 的原理工作。在 Python 提示符前输入的每个命令都会被读取、翻译并执行。典型的交互式会话如下。

>>> price = 100
>>> qty = 5
>>> ttl = price*qty
>>> ttl
500
>>> print ("Total = ", ttl)
Total = 500

若要关闭交互式会话,请输入行结束字符(对于 Linux 为 ctrl+D,对于 Windows 为 ctrl+Z)。您还可以在 Python 提示符前键入 quit() 并按 Enter 返回到操作系统提示符。

标准 Python 发行版提供的交互式外壳不具备行编辑、历史记录搜索、自动完成等功能。您可以使用其他高级交互式解释器软件,例如 IPythonbpython

Scripting Mode

不必像在交互式环境中那样逐条输入并获取结果,而是可以将一组指令保存在文本文件中,确保其具有 .py 扩展名,并将名称用作 Python 命令的命令行参数。

使用文本编辑器(如 Linux 上的 vim 或 Windows 上的记事本)将以下行另存为 prog1.py

print ("My first program")
price = 100
qty = 5
ttl = price*qty
print ("Total = ", ttl)

使用此名称作为命令行参数启动 Python。

C:\Users\Acer>python prog1.py
My first program
Total = 500

请注意,即使 Python 执行整个脚本,它仍逐个执行。

对于任何基于编译器的语言(如 Java),除非整个代码没有错误,否则不会将源代码转换为字节代码。另一方面,在 Python 中,语句执行直到遇到第一个错误。

让我们有目的地在上述代码中引入一个错误。

print ("My first program")
price = 100
qty = 5
ttl = prive*qty #Error in this statement
print ("Total = ", ttl)

请注意,拼写错误的变量 prive ,而不是 price 。尝试像以前一样再次执行脚本 −

C:\Users\Acer>python prog1.py
My first program
Traceback (most recent call last):
  File "C:\Python311\prog1.py", line 4, in <module>
   ttl = prive*qty
   ^^^^^
NameError: name 'prive' is not defined. Did you mean: 'price'?

请注意,错误语句之前的语句已执行,然后出现错误消息。因此,现在很明显 Python 脚本是以解释的方式执行的。

除了如上执行 Python 脚本外,该脚本本身还可以在 Linux 中作为自执行文件,就像 shell 脚本一样。您必须在脚本的顶部添加 shebang 行。shebang 指示使用哪个可执行文件解释脚本中的 Python 语句。脚本的第一行以 #! 开头,然后紧跟着 Python 可执行文件的路径。

修改 prog1.py 脚本如下 −

#! /usr/bin/python3.11
print ("My first program")
price = 100
qty = 5
ttl = price*qty
print ("Total = ", ttl)

若要将脚本标记为自执行,请使用 chmod 命令

user@ubuntu20:~$ chmod +x prog1.py

现在,您可以直接执行脚本,而无需将其用作命令行参数。

user@ubuntu20:~$ ./hello.py

IPython

IPython(代表 Interactive Python )是 Python 的增强和强大的交互式环境,与标准 Python 外壳相比具有许多功能。IPython 最初于 2001 年由 Fernando Perez 开发。

IPython 具有以下重要特性 −

  1. IPython 在运行期间检查对象属性的对象内省能力。

  2. 其语法高亮功能已被证明对识别关键字、变量等语言元素非常有用。

  3. 交互历史记录会内部存储,并且可以重复使用。

  4. 关键字、变量和函数名称的选项卡补全功能是最重要的功能之一。

  5. IPython 的 Magic 命令系统对于控制 Python 环境和执行操作系统任务非常有用。

  6. 这是 Jupyter 笔记本和其他 Project Jupyter 前端工具的主要内核。

使用 PIP 安装程序实用程序安装 IPython。

pip3 install ipython

从命令行启动 IPython

C:\Users\Acer>ipython
Python 3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934
64 bit (AMD64)] on win32
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]:

与标准解释器中的常规 >>> 提示不同,您将注意到两个主要的 IPython 提示,如下所示 −

  1. In[1] 出现在任何输入表达式之前。

  2. Out[1] 出现之前的结果。

In [1]: price = 100
In [2]: quantity = 5
In [3]: ttl = price*quantity
In [4]: ttl
Out[4]: 500
In [5]:

选项卡补全功能是 IPython 提供的最有用的增强功能之一。在对象前面的句点后面按 Tab 键时,IPython 会弹出适当的方法列表。

在以下示例中,将定义一个字符串。按 “.” 符号后面的 Tab 键,作为响应,将显示字符串类别的属性。您可以导航到所需的位置。

example

通过在 IPython 中输入 “?”,您可以获取任何对象的详细信息(内省)。它包括文档字符串、函数定义和类的构造函数详细信息。例如,要浏览上面定义的字符串对象 var,请在输入提示符中输入 var?。

In [5]: var = "Hello World"
In [6]: var?
Type: str
String form: Hello World
Length: 11
Docstring:
str(object='') -> str
str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or
errors is specified, then the object must expose a data buffer
that will be decoded using the given encoding and error handler.
Otherwise, returns the result of object.__str__() (if defined)
or repr(object).
encoding defaults to sys.getdefaultencoding().
errors defaults to 'strict'.

IPython 的神奇功能功能极其强大。行魔术函数允许您在 IPython 中运行 DOS 命令。让我们从 IPython 控制台中运行 dir 命令

In [8]: !dir *.exe
 Volume in drive F has no label.
 Volume Serial Number is E20D-C4B9

 Directory of F:\Python311

07-02-2023 16:55            103,192 python.exe
07-02-2023 16:55            101,656 pythonw.exe
                2 File(s)    204,848 bytes
                0 Dir(s)  105,260,306,432 bytes free

Jupyter 笔记本是 Python、Julia、R 和许多其他编程环境的基于 Web 的界面。对于 Python,它使用 IPython 作为其主要内核。

Python - Environment Setup

学习 Python 的第一步是在您的机器上安装它。如今,大多数计算机,尤其是装有 Linux 操作系统,都预装了 Python。但它可能不是最新版本。

在本部分,我们将学习在 Linux、Windows 和 Mac OS 上安装 Python 最新版本 Python 3.11.2

可以从 PSF 的官方网站下载所有操作系统环境的 Python 最新版本。

psfs official website

Install Python on Ubuntu Linux

要检查 Python 是否已安装,请打开 Linux 终端并输入以下命令:

user@ubuntu20:~$ python3 --version

在 Ubuntu Linux 中,安装 Python 最简单的方法是使用 apt − Advanced Packaging Tool 。始终建议更新所有配置的存储库中的软件包列表。

user@ubuntu20:~$ sudo apt update

即使更新后,根据您正在使用的 Ubuntu 版本,最新版本的 Python 可能仍不可用。若要克服此问题,请添加 deadsnakes 存储库。

user@ubuntu20:~$ sudo apt-get install software-properties-common
user@ubuntu20:~$ sudo add-apt-repository ppa:deadsnakes/ppa

再次更新软件包列表。

user@ubuntu20:~$ sudo apt update

要安装最新的 Python 3.11 版本,请在终端中输入以下命令:

user@ubuntu20:~$ sudo apt-get install python3.11

检查是否已正确安装。

user@ubuntu20:~$ python3.11
Python 3.11.2 (main, Feb 8 2023, 14:49:24) [GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print ("Hello World")
Hello World
>>>

Install Python on Windows

请注意,Python 3.10 及更高版本无法安装在 Windows 7 或更早的操作系统上。

建议使用官方安装程序来安装 Python。主页上给出了最新稳定版本。也可以在 https://www.python.org/downloads/windows/. 中找到。

您可以找到 32 位和 64 位架构的可嵌入软件包和安装程序。

embeddable packages

让我们下载 64 位 Windows 安装程序:

双击下载文件所在的位置以开始安装。

installation

虽然您可以直接单击“立即安装”按钮继续进行,但建议选择路径较短的安装文件夹,并勾选第二个复选框以更新 PATH 变量。

接受此安装向导中其余步骤的默认设置以完成安装。

complete installation

打开窗口命令提示符终端并运行 Python 以检查安装是否成功。

C:\Users\Acer>python
Python 3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934
64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Python 的标准库有一个可执行模块,称为 IDLE —— Integrated Development and Learning Environment 的缩写。从 Windows 开始菜单中找到并启动它。

idle

IDLE 包含 Python 外壳(交互式解释器)和一个可自定义的多窗口文本编辑器,具有语法突出显示、智能缩进、自动补全等功能。它是跨平台的,因此在 Windows、MacOS 和 Linux 上工作方式相同。它还有一个调试器,可以设置断点、步进和查看全局和局部命名空间。

Install Python on MacOS

MacOS 的早期版本通常预装 Python 2.7。但是,现在由于不再支持该版本,因此已停止使用。因此,您需要自行安装 Python。

在 Mac 电脑上,可以通过两种方法安装 Python:

  1. Using the official installer

  2. Manual installation with homebrew

您可以在官方网站的下载页面上找到 macOS 64 位通用 2 安装程序 −

安装过程与 Windows 上的过程基本相似。通常情况下,只需在向导步骤中接受默认选项即可完成此操作。

installation process

此安装向导也会安装常用实用程序,如 PIP 和 IDLE。

或者,您可以选择从命令行进行安装。如果尚未安装 Mac 的软件包管理器 Homebrew ,则需要安装它。您可以在 https://docs.brew.sh/Installation. 查看安装说明

之后,打开终端并输入以下命令 −

brew update && brew upgrade
brew install python3

现在将安装 Python 最新版本。

Install Python from Source Code

如果您是一位经验丰富且对 C++ 和 Git 工具有深入认识的开发人员,则可以按照本节中的说明来构建 Python 可执行文件及其标准库中的模块。

您的操作系统必须具有 C 编译器。在 Ubuntu 和 MacOS 中,都有 gcc 编译器。对于 Windows,您应该安装 Visual Studio 2017 或更高版本。

Steps to Build Python on Linux/Mac

从 Python 官方网站或其 GitHub 存储库下载 Python 最新版本的源代码。

使用命令解压文件 −

tar -xvzf /home/python/Python-3.11.2.tgz

或者,克隆 Python GitHub 存储库的主分支。(您应该安装 git)

git clone -b main https://github.com/python/cpython

源代码中有一个 configure 脚本。运行此脚本将创建 makefile。

./configure --enable-optimizations

之后,使用 make 工具来构建文件,然后 make install 来将最终文件放到 /usr/bin/ 目录中。

make
make install

Python 已从其源代码成功构建。

如果您使用 Windows,请确保已安装 Visual Studio 2017Git for Windows 。使用与上面相同的命令克隆 Python 源代码存储库。

在放置源代码的文件夹中打开 Windows 命令提示符。运行以下批处理文件

PCbuild\get_externals.bat

此操作将下载源代码依赖项(OpenSSL、Tk 等)

打开 Visual Studio 和 PCbuild/sbuild.sln 解决方案,并编译(按 F10)显示 python_d.exe 调试文件夹,这是 Python 可执行文件的调试版本。

若要从命令提示符进行编译,请使用以下命令−

PCbuild\build.bat -e -d -p x64

因此,在本教程中,您已学到如何从预编译二进制文件以及源代码安装 Python。

Setting Up the PATH

安装 Python 软件后,它应该可在文件系统中的任何地方访问。为此,需要更新 PATH 环境变量。系统 PATH 是一串字符串,由 semicolon (;) 分隔的文件夹名称组成。每当从命令行调用可执行程序时,操作系统都在 PATH 变量中列出的文件夹中搜索该程序。我们需要将 Python 安装文件夹追加到 PATH 字符串。

在 Windows 操作系统中,如果您在安装向导的第一屏上已启用“将 python.exe 添加到系统路径”选项,则路径将自动更新。若要手动执行,请从高级系统设置中打开环境变量部分。

setting up the path

编辑 Path 变量,并添加一个新条目。输入 Python 已安装到的安装文件夹名称,然后按确定。

edit the path variable

在 Linux 中,为特定会话将 Python 目录添加到路径−

In the bash shell (Linux) − 键入 export PATH="$PATH:/usr/bin/python3.11" ,然后按 Enter。

Python Command Line Options

我们知道可以从终端简单地通过调用 Python 可执行文件来调用交互式 Python 解释器。请注意,无需其他参数或选项便可启动交互式会话。

user@ubuntu20:~$ python3.11
Python 3.11.2 (main, Feb 8 2023, 14:49:24) [GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print ("Hello World")
Hello World
>>>

Python 解释器也对以下命令行选项做出响应−

-c <command>

解释器以一个字符串执行一条或多条语句,这些语句由换行符 (;) 符号分隔。

user@ubuntu20:~$ python3 -c "a=2;b=3;print(a+b)"
5

-m <module-name>

解释器执行命名模块的内容,作为 main 模块。由于参数是模块名称,您不得提供文件扩展名 (.py)。

考虑以下示例。此处,标准库中的 timeit 模块具有命令行界面。-s 选项为该模块设置参数。

C:\Users\Acer>python -m timeit -s "text = 'sample string'; char = 'g'
'char in text'"
5000000 loops, best of 5: 49.4 nsec per loop

<script>

解释器执行包含在带有 .py 扩展名的脚本中的 Python 代码,它必须是文件系统路径(绝对路径或相对路径)。

假定当前目录中存在名为 hello.py 文本文件,其中包含 print (“Hello World”) 语句。脚本选项的以下命令行使用方法。

C:\Users\Acer>python hello.py
Hello World

? Or -h or −help

此命令行选项打印所有命令行选项以及相应环境变量的简短描述,然后退出。

-V or --version

此命令行选项打印 Python 版本号。

C:\Users\Acer>python -V
Python 3.11.2
C:\Users\Acer>python --version
Python 3.11.2

Python Environment Variables

操作系统使用 path 环境变量搜索任何可执行文件(不仅仅是 Python 可执行文件)。特定 Python 环境变量允许您配置 Python 的行为。例如,检查导入模块的文件夹位置。正常情况下,Python 解释器在当前文件夹中搜索该模块。您可以设置一个或多个备用文件夹位置。

Python 环境变量可以临时设置为当前会话,或像在 path 变量的情况下那样在系统属性中持续添加。

PYTHONPATH

如上所述,如果你想让解释器在当前以外的其他文件夹中搜索模块,则一个或多个此类文件夹位置将存储为 PYTHONPATH 变量。

首先,在与 Python 安装文件夹不同的文件夹中保存 hello.py 脚本,不妨将其称为 c:\modulepath\hello.py

若要使该模块在全局范围内对解释器可用,请设置 PYTHONPATH

C:\Users\Acer>set PYTHONPATH= c:\modulepath
C:\Users\Acer>echo %PYTHONPATH%
c:\modulepath

现在,你甚至可以从 c:\modulepath 目录之外的任何目录导入该模块。

>>> import hello
Hello World
>>>

PYTHONHOME

设置此变量可更改标准 Python 库的位置。默认情况下,库在 Linux 中的 /usr/local/pythonversion 和 Windows 中的 instalfolder\lib 中进行搜索。例如, c:\python311\lib

PYTHONSTARTUP

通常,此变量设置为一个 Python 脚本,你打算每次启动 Python 解释器时都会自动执行该脚本。

让我们创建一个简单的脚本如下,并将其保存在 Python 安装文件夹中,名称为 startup.py

print ("Example of Start up file")
print ("Hello World")

现在设置 PYTHONSTARTUP 变量并为其指定此文件名称。然后启动 Python 解释器。它会在出现提示之前显示此脚本的输出。

F:\311_2>set PYTHONSTARTUP=startup.py
F:\311_2>echo %PYTHONSTARTUP%
startup.py
F:\311_2>python
Python 3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934
64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
Example of Start up file
Hello World
>>>

PYTHONCASEOK

此环境仅可在 Windows 和 MacOSX 上使用,而不能在 Linux 上使用。它会导致 Python 忽略 import 语句中的大小写。

PYTHONVERBOSE

如果将此变量设置为非空字符串,则相当于指定 python -v 命令。它会打印一条消息,在每次初始化模块时显示位置(文件名或内置模块)。如果设置为整数,比如 2,则相当于指定 -v 2 次。(python --v)。

PYTHONDONTWRITEBYTECODE

通常,导入的模块会被编译为 .pyc 文件。如果将此变量设置为非空字符串,则在导入源模块时不会创建 .pyc 文件。

PYTHONWARNINGS

Python 的警告消息会重定向到标准错误流 sys.stderr 。此环境变量相当于 python -W 选项。以下是此变量允许的值:

  1. PYTHONWARNINGS=default # 每调用位置警告一次

  2. PYTHONWARNINGS=error # 转换为异常

  3. PYTHONWARNINGS=always # 每一次都警告

  4. PYTHONWARNINGS=module # 每调用模块警告一次

  5. PYTHONWARNINGS=once # 每处理 Python 警告一次

  6. PYTHONWARNINGS=ignore  # Never warn

Python - Virtual Environment

在本章中,你将了解 Python 中的虚拟环境是什么,以及如何创建和使用虚拟环境来构建 Python 应用程序。

当您在电脑上安装 Python 软件后,它就可以在文件系统的任何位置被使用。这是一种系统范围内的安装。

当使用 pip 实用工具在 Python 中开发应用程序时,可能需要安装一个或多个库(例如: pip3 install somelib )。此外,一个应用程序(不妨称之为 App1)可能需要某个特定版本的库——不妨称之为 somelib 1.0 。同时,另一个 Python 应用程序(例如 App2)可能需要同一库的一个较新版本——不妨称之为 somelib 2.0 。因此,通过安装一个新版本,App1 的功能可能由于同一库的不同两个版本之间的冲突而受到损害。

可以通过在同一台机器中提供两个独立的 Python 环境来避免此冲突。这些环境称为虚拟环境。虚拟环境是一个分离的目录结构,其中包含一个隔离安装,具有 Python 解释器、标准库和其他模块的本地副本。

下图显示了使用虚拟环境的优势所在。利用全球性的 Python 安装,创建了多个虚拟环境,每个环境都有同一库的不同版本,于是,避免了冲突。

python virtual environment

此功能由 estándar Python 配送中的 venv 模块提供支持。使用以下命令创建一个新的虚拟环境。

C:\Users\Acer>md\pythonapp
C:\Users\Acer>cd\pythonapp
C:\pythonapp>python -m venv myvenv

此处, myvenv 是一个文件夹,将在其中创建一个新的 Python 虚拟环境,并显示以下目录结构 −

Directory of C:\pythonapp\myvenv
22-02-2023 09:53 <DIR> .
22-02-2023 09:53 <DIR> ..
22-02-2023 09:53 <DIR> Include
22-02-2023 09:53 <DIR> Lib
22-02-2023 09:53 77 pyvenv.cfg
22-02-2023 09:53 <DIR> Scripts

用于激活和取消激活虚拟环境的实用工具以及 Python 解释器的本地副本将被放置在 scripts 文件夹中。

Directory of C:\pythonapp\myvenv\scripts
22-02-2023 09:53 <DIR> .
22-02-2023 09:53 <DIR> ..
22-02-2023 09:53 2,063 activate
22-02-2023 09:53 992 activate.bat
22-02-2023 09:53 19,611 Activate.ps1
22-02-2023 09:53 393 deactivate.bat
22-02-2023 09:53 106,349 pip.exe
22-02-2023 09:53 106,349 pip3.10.exe
22-02-2023 09:53 106,349 pip3.exe
22-02-2023 09:53 242,408 python.exe
22-02-2023 09:53 232,688 pythonw.exe

若要启用这个新的虚拟环境,请在 Scripts 文件夹中执行 activate.bat

C:\pythonapp>myvenv\scripts\activate
(myvenv) C:\pythonapp>

请注意括号中的虚拟环境名称。Scripts 文件夹包含 Python 解释器的本地副本。您可以在此虚拟环境中启动一个 Python 会话。

要确认此 Python 会话是否在虚拟环境中,请检查 sys.path

(myvenv) C:\pythonapp>python
Python 3.10.1 (tags/v3.10.1:2cd268a, Dec 6 2021, 19:10:37) [MSC v.1929
64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', 'C:\\Python310\\python310.zip', 'C:\\Python310\\DLLs',
'C:\\Python310\\lib', 'C:\\Python310', 'C:\\pythonapp\\myvenv',
'C:\\pythonapp\\myvenv\\lib\\site-packages']
>>>

这个虚拟环境的脚本文件夹中还包含 pip 实用程序。如果你安装了一个 PyPI 包,该包只会在当前虚拟环境中激活。如需停用此环境,请运行 deactivate.bat

Python - Basic Syntax

在 Python 中,术语语法指的是形成语句或表达式的规则。Python 语言以其简洁的语法而闻名。与其他语言相比,它还有一组受限关键字和更简单的标点规则。让我们在这章了解 Python 的基本语法。

一个 Python 程序包含预定义的关键字和标识符,它们表示函数、类、模块等。Python 明确定义规则来形成标识符、编写语句和在 Python 源代码中添加评论。

Python Keywords

一组预定义的关键字是任何编程语言中最关键的方面。这些关键字是保留字。它们具有预定义的含义,必须仅用于其预定义目的和根据预定义的语法规则。编程逻辑使用这些关键字进行编码。

截至 Python 3.11 版本,Python 中有 35 个(三十五个)关键字。若要获取 Python 关键字的列表,请在 Python shell 中输入以下帮助命令。

>>> help("keywords")

Here is a list of the Python keywords. Enter any keyword to get more
help.

所有关键字均为字母,且全部(False、None 和 True 除外)均为小写。kwlist 属性还在 keyword 模块中定义的属性中给出了关键字的列表。

>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',
'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',
'while', 'with', 'yield']

如何验证某个单词是否是关键字?大多数 Python IDE 提供有色语法突出显示功能,其中关键字以特定颜色显示。

下面是 VS Code 中的 Python 代码。关键字(if 和 else)、标识符和常量显示为不同的配色方案。

vs code

keyword 模块还有一个 iskeyword() 函数。它会对有效的关键字返回 True,返回 false 则表示无效。

>>> import keyword
>>> keyword.iskeyword("else")
True
>>> keyword.iskeyword("Hello")
False

Python 关键字可大体分为以下类别:

我们将在本教程中学习如何在每个类别中使用这些关键字。

Python Identifiers

Python 程序中的除关键字外的各种元素称为标识符。标识符是给定源代码中的变量、函数、类、模块、包等的名称。Python 已制定特定规则来形成标识符。这些规则如下:

  1. 标识符应以字母(小写或大写)或下划线(_)开头。后面可以跟一个或多个字母数字字符或下划线。

  2. 不允许将任何关键字用作标识符,因为关键字有预定义的含义。

  3. 传统上,类的名称以大写字母开头。其他元素(如变量或函数)以小写字母开头。

  4. 根据另一个 Python 惯例,变量名开头的一个下划线表示私有变量。

  5. 一个标识符开头有两个下划线表示该变量的私有性很强。

  6. 在语言本身中,两个前置和后置下划线用于特殊用途。例如, addinit

根据上述规则,以下是一些有效的标识符:

  1. Student

  2. score

  3. aTotal

  4. sum_age

  5. __count

  6. TotalValue

  7. price1

  8. cost_of_item

  9. init

以下还给出了一些非法的标识符形式 −

  1. 1001

  2. Name of student

  3. price-1

  4. ft.in

请注意,标识符区分大小写。因此,Name 和 name 是两个不同的标识符。

Python Indents

在代码中使用缩进是 Python 语法的其中一项重要特性。在程序中,您可能经常需要将多条语句组合到一个块中。例如,如果某个条件为真/假时需要多条语句。不同的编程语言具有不同的方法来标记类、函数、条件和循环等结构中语句组的作用域和范围。C、C++、Java 等使用花括号来标记块。Python 使用统一缩进标记语句块,从而提高代码的可读性。

若要标记块开始的位置,请键入“:”符号并按 Enter。任何 Python 识别编辑器(如 IDLE 或 VS Code)会到下一行并另起多个空格(称为缩进)。块中的后续语句遵循相同级别的缩进。若要指示块结束,请按 Backspace 键将空格取消缩进。以下示例演示了在 Python 中使用缩进:

python indents

在这个节点,您可能不理解代码的工作原理。但这无需担心。只需查看冒号符号后缩进级别如何增加即可。

Python Statements

Python 中的语句是 Python 解释器可以执行的任何指令。语句包含一个或多个关键字、运算符、标识符、一个冒号 : 符号,以标记块的开始或反斜杠 \ 作为续行符。

语句可以是简单的赋值语句,如 amount = 1000,或在条件或循环结构中,将多条语句分组到统一缩进的块中的复合语句。

您可以在交互式外壳的 Python 提示符前面输入语句,或在编辑器窗口中输入。通常,以 Enter 键(称为换行符)结束的文本被 Python 解释器识别为语句。因此,除非编辑器中每一行以注释字符 (#) 开始,否则每一行都是一个语句。

print ("My first program")
price = 100
qty = 5
ttl = price*qty
print ("Total = ", ttl)

上个代码中的每一行都是一个语句。有时,一个 Python 语句可能在多行中溢出。若要实现,请使用反斜杠 (\) 作为续行符。可以将一个较长的字符串打破成多行,如下所示 −

name = "Ravi"
string = "Hello {} \
Welcome to Python Tutorial \
from TutorialsPoint".format(name)
print (string)

字符串(带有嵌入的字符串变量名)跨越多行以便提高可读性。输出将是 −

Hello Ravi Welcome to Python Tutorial from TutorialsPoint

续行符也有助于以更可读的方式编写较长的算术表达式。

例如,方程 $\frac{(a+b)\times (c−d)}{(a−b)\times (c+d)}$ 在 Python 中的编码如下 −

a=10
b=5
c=5
d=10
expr = (a+b)*(c-d)/ \
   (a-b)*(c+d)
print (expr)

如果列表、元组或字典对象中的项溢出多行,则不必使用反斜杠符号 (\)。

Subjects = ["English", "French", "Sanskrit",
   "Physics", "Maths",
   "Computer Sci", "History"]

Python 还允许使用分号将多于一条语句放在编辑器中的一行。请看以下示例 −

a=10; b=5; c=5; d=10
if a>10: b=20; c=50

Python - Variables

在本章中,您会学习什么是变量在 Python 中,以及如何使用它们。

属于不同数据类型的数据项存储在计算机的内存中。计算机的存储器位置具有一个数字或地址,在内部以二进制形式呈现。数据也以二进制形式存储,因为计算机按照二进制表示法的原则工作。在以下图表中,字符串 May 和数字 18 显示为存储在存储器位置中。

memory

如果您知道汇编语言,您会转换这些数据项和存储器地址,并给出一个机器语言指令。但是,这对于一般人来说并不容易。例如 Python 解释器这样的语言翻译器执行这种类型的转换。它将对象存储在随机选择的存储器位置。Python 的内置 id() 函数返回存储对象的地址。

>>> "May"
>>> id("May")
2167264641264
>>> 18
18
>>> id(18)
140714055169352

一旦数据存储在内存中,就应该对它重复访问以便执行某个进程。显然,从其 ID 中提取数据很麻烦。像 Python 这样的高级语言使得为存储器位置提供合适的别名或标签成为可能。

在上述示例中,让我们将 May 的位置标记为 month,并将存储 18 的位置标记为 age。Python 使用赋值运算符 (=) 将对象与标签绑定。

>>> month="May"
>>> age=18

数据项(May)及其名称(month)具有相同的 id()。18 和 age 的 id() 相同。

>>> id(month)
2167264641264
>>> id(age)
140714055169352

标签是一个标识符。通常被称为变量。Python 变量是一个符号名称,它是一个对象的引用或指针。

Naming Convention

变量的名称由用户指定,并遵循形成标识符的规则。

  1. Python 变量的名称应该以字母(小写或大写)或下划线(_)开头。后面可以跟多个字母数字字符或下划线。

  2. 不允许将任何关键字用作 Python 变量,因为关键字具有预定义的含义。

  3. Python 中变量的名称区分大小写。因此,age 和 Age 不能互换。

  4. 你应该选择有记忆性的变量名称,以便它能表示其用途。它不应该很短,但也不要太长。

如果变量名包含多个单词,我们应该使用以下命名模式:

  1. Camel case - 第一个字母是小写,但每个后续单词的第一个字母是大写。例如:kmPerHour、pricePerLitre

  2. Pascal case - 每个单词的第一个字母是大写。例如:KmPerHour、PricePerLitre

  3. Snake case - 使用单个下划线(_)字符来分隔单词。例如:km_per_hour、price_per_litre

一旦你使用变量来标识数据项,就可以在其 id() 值不重复的情况下重复使用它。在此情况下,我们有矩形的变量高度和宽度。我们可以使用这些变量来计算面积和周长。

>>> width=10
>>> height=20
>>> area=width*height
>>> area
200
>>> perimeter=2*(width+height)
>>> perimeter
60

在编写脚本或程序时,使用变量特别有利。以下脚本也使用上述变量。

#! /usr/bin/python3.11
width = 10
height = 20
area = width*height
perimeter = 2*(width+height)
print ("Area = ", area)
print ("Perimeter = ", perimeter)

保存带有 .py 扩展名的上述脚本,并从命令行执行它。结果将为:

Area = 200
Perimeter = 60

Assignment Statement

在 C/C++ 和 Java 等语言中,需要在为变量分配任何值之前声明变量及其类型。Python 中不需要这样的预先声明变量。

Python 使用 = 符号作为赋值运算符。变量标识符的名称出现在 = 符号的左侧。对其右侧的表达式求值,并将该值分配给变量。以下是赋值语句的示例:

>>> counter = 10
>>> counter = 10 # integer assignment
>>> price = 25.50 # float assignment
>>> city = "Hyderabad" # String assignment
>>> subjects = ["Physics", "Maths", "English"] # List assignment
>>> mark_list = {"Rohit":50, "Kiran":60, "Lata":70} # dictionary
assignment

Python 的内置 print() 函数显示一个或多个变量的值。

>>> print (counter, price, city)
10 25.5 Hyderabad
>>> print (subjects)
['Physics', 'Maths', 'English']
>>> print (mark_list)
{'Rohit': 50, 'Kiran': 60, 'Lata': 70}

符号右侧的任何表达式的值都赋值给左侧的变量。

>>> x = 5
>>> y = 10
>>> z = x+y

但是,不允许 = 运算符左侧的表达式和右侧的变量。

>>> x = 5
>>> y = 10
>>> x+y=z
   File "<stdin>", line 1
   x+y=z
   ^^^
SyntaxError: cannot assign to expression here. Maybe you meant '=='
instead of '='?

虽然在数学中 z=x+y 和 x+y=z 是等价的,但在这里却不然。这是因为 = 是一个方程符号,而在 Python 中它是一个赋值运算符。

Multiple Assignments

在 Python 中,你可以在单个语句中初始化不止一个变量。在下面的情况下,三个变量具有相同的值。

>>> a=10
>>> b=10
>>> c=10

你可以使用如下的单个赋值语句来代替单独的赋值:

>>> a=b=c=10
>>> print (a,b,c)
10 10 10

在下面的情况下,我们有三个具有不同值得变量。

>>> a=10
>>> b=20
>>> c=30

这些单独的赋值语句可以组合为一个。你可以在 = 运算符的左侧写上用逗号分隔的变量名,在右侧写上用逗号分隔的值。

>>> a,b,c = 10,20,30
>>> print (a,b,c)
10 20 30

变量的概念在 Python 中与在 C/C++ 中不同。

在 C/C++ 中,变量是一个命名的内存位置。如果 a=10 且 b=10,则它们是两个不同的内存位置。我们假设它们的内存地址分别是 100 和 200。

named memory location

如果为 "a" 分配一个不同的值——比如将 100 地址中的 10 覆盖。

different value assigned

Python 变量指的是对象而不是内存位置。对象只存储在内存中一次。多个变量实际上是同一对象的多个标签。

address 100

语句 a=50 在内存中的其他位置创建一个新的 int 对象 50,并将对象 10 指向 "b"。

address 150

此外,如果你为 b 分配其他值,对象 10 将保持未引用。

address 200

Python 的垃圾收集器机制释放了任何未引用对象占用的内存。

如果两个操作数具有相同的 id() 值,Python 的标识运算符 is 返回 True。

>>> a=b=10
>>> a is b
True
>>> id(a), id(b)
(140731955278920, 140731955278920)

Python - Data Types

计算机是一种数据处理设备。计算机将其内存中的数据存储起来,并根据给定的程序进行处理。数据是关于某个对象事实的表示。

一些数据示例:

  1. Data of students ——姓名、性别、班级、成绩、年龄、费用等。

  2. Data of books in library ——书名、作者、出版商、价格、页数、出版年份等。

  3. Data of employees in an office ——姓名、职称、薪水、部门、分公司等。

数据类型表示一种值,并确定可以对其执行哪些操作。数值、非数值和布尔值(真/假)是最明显的数据类型。然而,每种编程语言都有自己分类,很大程度上反映了其编程理念。

Python 使用不同的数据类型标识数据,如下所示 −

data types

Python 的数据模型定义了四个主要数据类型。它们是数值、序列、集合和字典(也称为映射)

Number Type

具有数值值的任何数据项都是一个数字。Python 中有四种标准数值数据类型。它们是整数、浮点数、布尔值和复数。它们每个在 Python 库中都有内置类,分别称为 int, float, boolcomplex

在 Python 中,数字是其对应类的对象。例如,整数 123 是 int 类的对象。类似地,9.99 是浮点数,是 float 类的对象。

Python 的标准库有一个内置函数 type() ,它返回给定对象所属的类。这里,它用于检查整数和浮点数的类型。

>>> type(123)
<class 'int'>
>>> type(9.99)
<class 'float'>

浮点数的小数部分也可以用 scientific 格式表示。数字 -0.000123 等同于其科学计数法 1.23E-4 (或 1.23e-4)。

复数由两部分组成 − realimaginary 。它们由 '+' 或 '-' 符号分隔。虚数部分后跟 'j',表示虚数。-1 的平方根 ($\sqrt{-1}$),定义为虚数。Python 中的复数表示为 x+yj,其中 x 是实部,y 是虚部。因此,5+6j 是一个复数。

>>> type(5+6j)
<class 'complex'>

布尔数只有两个可能的值,分别由关键字 TrueFalse 表示。它们分别对应于整数 1 和 0。

>>> type (True)
<class 'bool'>
>>> type(False)
<class 'bool'>

使用 Python 的算术运算符,您可以执行加法、减法等操作。

Sequence Types

序列是集合数据类型。它是项的有序集合。序列中的项具有从 0 开始的位置索引。它在概念上类似于 C 或 C++ 中的数组。Python 中定义了三种序列类型。字符串、列表和元组。

Strings in Python

字符串是由一个或多个 Unicode 字符组成的序列,用单引号、双引号或三引号(也称为反引号)括起来。只要字符序列相同,单引号、双引号或三引号都没有关系。因此,以下字符串表示形式是等效的。

>>> 'Welcome To TutorialsPoint'
'Welcome To TutorialsPoint'
>>> "Welcome To TutorialsPoint"
'Welcome To TutorialsPoint'
>>> '''Welcome To TutorialsPoint'''
'Welcome To TutorialsPoint'

Python 中的字符串是 str 类的对象。它可以通过 type() 函数验证。

>>> type("Welcome To TutorialsPoint")
<class 'str'>

您想将一些文本作为字符串的一部分嵌入到双引号中,那么字符串本身应该放在单引号中。要嵌入单引号文本,则应在双引号中编写字符串。

>>> 'Welcome to "Python Tutorial" from TutorialsPoint'
'Welcome to "Python Tutorial" from TutorialsPoint'
>>> "Welcome to 'Python Tutorial' from TutorialsPoint"
"Welcome to 'Python Tutorial' from TutorialsPoint"

由于字符串是一个序列,因此其中的每个字符都具有从 0 开始的位置索引。要形成一个三引号字符串,您可以使用三个单引号或三个双引号 − 两个版本是类似的。

>>> '''Welcome To TutorialsPoint'''
'Welcome To TutorialsPoint'
>>> """Welcome To TutorialsPoint"""
'Welcome To TutorialsPoint'

三引号字符串对形成多行字符串很有用。

>>> '''
... Welcome To
... Python Tutorial
... from TutorialsPoint
... '''
'\nWelcome To\nPython Tutorial \nfrom TutorialsPoint\n'

字符串是非数字数据类型。显然,我们无法对其执行算术运算。但是,可以执行 slicingconcatenation 之类运算。Python 的 str 类为字符串处理定义了许多有用的方法。我们将在后续的字符串章节中学习这些方法。

List in Python

在 Python 中,列表是有序集合,其中包含任何类型的数据项。数据项以逗号 (,) 符号分隔并用方括号 ( [] ) 括起来。列表也是一个序列,因此。

列表中的每个项都有一个索引,该索引引用它在集合中的位置。索引从 0 开始。

Python 中的列表看起来类似于 C 或 C 中的数组。但是,两者之间有一个重要的区别。在 C/C 中,数组是类似类型数据的同类集合。Python 列表中的项可以是不同的类型。

>>> [2023, "Python", 3.11, 5+6j, 1.23E-4]

Python 中的列表是 list 类的对象。我们可以使用 type() 函数检查它。

>>> type([2023, "Python", 3.11, 5+6j, 1.23E-4])
<class 'list'>

如前所述,列表中的项可以是任何数据类型。这意味着列表对象也可以是另一个列表中的项。在这种情况下,它将变成一个嵌套列表。

>>> [['One', 'Two', 'Three'], [1,2,3], [1.0, 2.0, 3.0]]

列表项也可以是元组、字典、集合或用户定义类对象。

列表是一个序列,它支持切片和连接操作,就像字符串一样。使用 Python 的内置列表类中提供的方法/函数,我们可以添加、删除或更新项,以及按所需顺序对项进行排序或重新排列。我们将在后续章节中研究这些方面。

Tuples in Python

在 Python 中,元组是有序的任何类型数据项集合。数据项通过逗号 (,) 符号分隔,并用括号或小括号 () 括起来。元组也是一种序列,因此元组中的每个项目都有一个索引,指其在集合中的位置。索引从 0 开始。

>>> (2023, "Python", 3.11, 5+6j, 1.23E-4)

在 Python 中,元组是 tuple 类的对象。我们可以使用 type() 函数检查它。

>>> type((2023, "Python", 3.11, 5+6j, 1.23E-4))
<class 'tuple'>

与列表一样,元组中的项也可以是一个列表、一个元组本身或任何其他 Python 类的对象。

>>> (['One', 'Two', 'Three'], 1,2.0,3, (1.0, 2.0, 3.0))

要形成元组,可以使用圆括号,但不强制要求。默认情况下,逗号分隔而不带任何包围符号的数据项被视为元组。

>>> 2023, "Python", 3.11, 5+6j, 1.23E-4
(2023, 'Python', 3.11, (5+6j), 0.000123)

除了使用分隔符之外,两个序列类型列表和元组看起来很相似,列表使用方括号 ([]),而元组使用括号。但是,列表和元组之间存在一个主要

差别。列表是可变对象,而元组是 immutable 。对象不可变意味着它一旦存储在内存中,就不能更改。 让我们尝试了解一下可变性概念。我们有一个包含相同数据项的列表和元组对象。

>>> l1=[1,2,3]
>>> t1=(1,2,3)

两者都是序列,因此两者中的每个项目都有一个索引。在两者中,索引号为 1 的项目都是 2。

>>> l1[1]
2
>>> t1[1]
2

让我们尝试将列表和元组中项目索引号为 1 的值从 2 更改为 20。

>>> l1[1]
2
>>> t1[1]
2
>>> l1[1]=20
>>> l1
[1, 20, 3]
>>> t1[1]=20
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

错误消息 'tuple' object does not support item assignment 告诉你一旦元组对象形成后就无法修改。这称为不可变对象。 元组的不可变性还意味着 Python 的元组类没有在元组中添加、删除或排序项的功能。然而,由于它是一个序列,我们可以执行切片和连接。 = 字典类型[id="_dictionary_type"]=== 字典类型 Python 的字典是 mapping 类型的示例。映射对象“映射”一个对象的另一个对象的值。在语言词典中,我们有一对单词及其相应的含义。成对的两部分是键(单词)和值(含义)。同样,Python 字典也是 key:value 对的集合。这些对通过逗号分隔并放入大括号 {} 中。为了建立键和值之间的映射,在两者之间放置分号':' 符号。

>>> {1:'one', 2:'two', 3:'three'}

字典中的每个键必须唯一,并且应该是一个数字、字符串或元组。值对象可以是任何类型,并且可以映射到多个键(它们不必是唯一的) 在 Python 中,字典是内置 dict 类的对象。我们可以使用 type() 函数检查它。

>>> type({1:'one', 2:'two', 3:'three'})
<class 'dict'>

Python 的字典不是序列。它是一个项的集合,但每个项(键值对)不像字符串、列表或元组那样,由位置索引标识。因此,无法对字典执行切片操作。字典是一个可变对象,因此可以执行添加、修改或删除操作,其对应的功能在 dict 类中定义。将在后续章节中说明这些操作。 = 集合类型[id="_set_type"]=== 集合类型 集合是集合在 Python 中的实现,如数学中定义的。Python 中的集合是一个集合,但它不是索引或有序集合,如字符串、列表或元组。在一个集合中,对象不能出现多次,而在列表和元组中,同一个对象可以出现多次。 集合中用逗号分隔的项被放入大括号或花括号中。集合集合中的项可以是不同数据类型。

>>> {2023, "Python", 3.11, 5+6j, 1.23E-4}
{(5+6j), 3.11, 0.000123, 'Python', 2023}

请注意,集合集合中的项可能不会按照它们输入的顺序出现。Python 根据数学定义对项的位置进行优化,以便对集合执行操作。 Python 的集合是内置 set 类的对象,可以使用 type() 函数检查。

>>> type({2023, "Python", 3.11, 5+6j, 1.23E-4})
<class 'set'>

一个集合只能存储不可变对象,例如数字(整数、浮点数、复数或布尔值)、字符串或元组。如果你尝试将列表或字典放入集合集合中,Python 会引发 TypeError

>>> {['One', 'Two', 'Three'], 1,2,3, (1.0, 2.0, 3.0)}
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Hashing 是计算机科学中的一种机制,它可以更快地搜索计算机内存中的对象。 Only immutable objects are hashable 。 即使集合不允许可变项,但集合本身是可变的。因此,可以使用内置集合类中的方法对集合对象执行添加/删除/更新操作。Python 还有一组算符来执行集合操作。这些方法和算符在后面的章节中进行了解释 = Python - 类型转换[id="_python_type_casting"]== Python - 类型转换 在制造业中,铸造是指将液化或熔化的金属浇注到模具中,然后使其冷却以获得所需的形状。在编程中,铸造是指将一种类型转换为另一种的对象。在此,我们将学习 Python 中的类型转换。 在 Python 中,有不同的数据类型,例如数字、序列、映射等。在某些情况下,你可能有某一类型的数据,但你想以另一种形式使用它。例如,用户输入了一个字符串,但你想将其作为数字使用。Python 的类型转换机制让你能够做到这一点。 = Python 中的隐式转换 [id="_implicit_casting_in_python"]=== Python 中的隐式转换 转换有两种类型− implicitexplicit 。 当任何语言编译器/解释器自动将一种类型对象转换为另一种类型时,称为隐式转换。Python 是一种强类型语言。它不允许无关数据类型之间的自动类型转换。例如,字符串不能转换为任何数字类型。然而,整数可以转换为浮点数。其他语言(如 JavaScript)是一种弱类型语言,其中整数被强制转换为字符串以便连接。 请注意,每种类型对内存的需求不同。例如,Python 中的整数对象占用 4 字节内存,而浮点数对象由于小数部分需要 8 字节。因此,Python 解释器不会自动将浮点数转换为整数,因为这会导致数据丢失。另一方面,整数可以通过将其小数部分设置为 0 来轻松转换为浮点数。 隐式 int 到 float 的转换发生在对 int 和 float 操作数执行任意算术运算时。 我们有一个整数和一个浮点数变量

>>> a=10 # int object
>>> b=10.5 # float object

为了执行其加法,10 - 整数对象升级为 10.0。它是一个浮点数,但相当于其早期的数字值。现在,我们可以对两个浮点数执行加法。

>>> c=a+b
>>> print (c)
20.5

在隐式类型转换中,字节大小较小的对象升级为与操作中其他对象的字节大小匹配。例如,布尔对象在与浮点对象相加之前,首先升级为 int 然后再升级为 float。在以下示例中,我们尝试将一个布尔对象添加到一个浮点型中。

>>> a=True
>>> b=10.5
>>> c=a+b
>>> print (c)
11.5

请注意,True 等于 1,False 等于 0。 虽然自动或隐式转换仅限于 intfloat 转换,但您可以使用 Python 的内置函数执行显式转换,例如字符串到整数。 = int() 函数 [id="_int_function"]=== int() 函数 Python 的内置函数 int() 将整数字面值转换为整数对象、浮点数转换为整数以及字符串转换为整数,如果字符串本身具有有效的整数字面值表示形式。 将 int() 与 int 对象作为参数一起使用等同于直接声明 int 对象。

>>> a = int(10)
>>> a
10

等同于 −

>>> a = 10
>>> a
10
>>> type(a)
<class 'int>

如果 int() 函数的参数是浮点数对象或浮点表达式,它将返回 int 对象。例如 -

>>> a = int(10.5) #converts a float object to int
>>> a
10
>>> a = int(2*3.14) #expression results float, is converted to int
>>> a
6
>>> type(a)
<class 'int'>

如果将布尔对象作为参数提供,则 int() 函数还返回整数 1。

>>> a=int(True)
>>> a
1
>>> type(a)
<class 'int'>

= 字符串到整数 [id="_string_to_integer"]==== 字符串到整数 int() 函数从字符串对象返回一个整数,但前提是它包含有效的整数表示形式。

>>> a = int("100")
>>> a
100
>>> type(a)
<class 'int'>
>>> a = ("10"+"01")
>>> a = int("10"+"01")
>>> a
1001
>>> type(a)
<class 'int'>

但是,如果字符串包含非整数表示形式,Python 将引发 ValueError。

>>> a = int("10.5")
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '10.5'
>>> a = int("Hello World")
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'Hello World'

int() 函数还可以从二进制、八进制和十六进制字符串中返回整数。为此,该函数需要一个基数参数,分别为 2、8 或 16。该字符串应具有有效的二进制/八进制/十六进制表示形式。 = 二进制字符串转换为整数[id="_binary_string_to_integer"]==== 二进制字符串转换为整数 该字符串应仅由 1 和 0 组成,且基数应为 2。

>>> a = int("110011", 2)
>>> a
51

二进制数 110011 的十进制等价数为 51。 = 八进制字符串转换为整数[id="_octal_string_to_integer"]==== 八进制字符串转换为整数 该字符串应仅包含 0 至 7 位数字,且基数应为 8。

>>> a = int("20", 8)
>>> a
16

八进制数 20 的十进制等价数为 16。 = 十六进制字符串转换为整数[id="_hexa_decimal_string_to_integer"]==== 十六进制字符串转换为整数 该字符串应仅包含十六进制符号,即 0-9 和 A、B、C、D、E 或 F。基数应为 16。

>>> a = int("2A9", 16)
>>> a
681

十六进制数 2A9 的十进制等价数为 681。 您可以在 Windows、Ubuntu 或智能手机中的计算器应用程序中轻松验证这些转换。 = float() 函数[id="_float_function"]=== float() 函数 float() 是 Python 中的一个内置函数。如果参数是浮点字面量、整数或具有有效浮点表示的字符串,则它返回一个 float 对象。 将 float() 与 float 对象作为参数一起使用相当于直接声明一个 float 对象

>>> a = float(9.99)
>>> a
9.99
>>> type(a)
<class 'float'>

等同于 −

>>> a = 9.99
>>> a
9.99
>>> type(a)
<class 'float'>

如果 float() 函数的参数为整数,则返回值为小数部分设为 0 的浮点数。

>>> a = float(100)
>>> a
100.0
>>> type(a)
<class 'float'>

如果字符串中包含有效的浮点数,则 float() 函数从字符串中返回 float 对象,否则将引发 ValueError。

>>> a = float("9.99")
>>> a
9.99
>>> type(a)
<class 'float'>
>>> a = float("1,234.50")
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: '1,234.50'

这里导致 ValueError 的原因是字符串中存在逗号。 为了将字符串转换为浮点数,浮点数的科学计数法也会被视为有效计数法。

>>> a = float("1.00E4")
>>> a
10000.0
>>> type(a)
<class 'float'>
>>> a = float("1.00E-4")
>>> a
0.0001
>>> type(a)
<class 'float'>

= str() 函数[id="_str_function"]=== str() 函数 我们看到 Python 如何从对应的字符串表示中获取整数或小数。str() 函数的作用相反。它用单引号 (') 将整数或浮点数对象括起来,返回一个 str 对象。str() 函数返回该字符串。 Python 对象的任何表示。在本节中,我们将看到 Python 中 str() 函数的不同示例。 str() 函数有三个参数。第一个必需参数(或自变量)是我们要获取其字符串表示的对象。另两个运算符,编码和错误,是可选的。 我们将在 Python 控制台中执行 str() 函数,以轻松验证返回的对象是一个字符串,并有引号 (')。 整数转字符串

>>> a = str(10)
>>> a
'10'
>>> type(a)
<class 'str'>

= 浮点数到字符串[id="_float_to_string"]==== 浮点数到字符串 str() 函数将浮点数对象转化为带小数点的标准记法,即整数部分和小数部分用小数点分隔,以及带指数的科学记法,转化为字符串对象。

>>> a=str(11.10)
>>> a
'11.1'
>>> type(a)
<class 'str'>
>>> a = str(2/5)
>>> a
'0.4'
>>> type(a)
<class 'str'>

在第二个案例中,除法式被作为自变量提供给 str() 函数。请注意,表达式最先被求值,然后结果被转化为字符串。 以 E 或 e 以及正、负幂表示的科学记法中的浮点数可以用 str() 函数转化为字符串。

>>> a=str(10E4)
>>> a
'100000.0'
>>> type(a)
<class 'str'>
>>> a=str(1.23e-4)
>>> a
'0.000123'
>>> type(a)
<class 'str'>

当布尔常量被作为自变量输入时,它会被单引号 (') 括起来,因此 True 变成 'True'。列表和元组对象也可以作为自变量提供给 str() 函数。结果字符串是带单引号 (') 的列表/元组。

>>> a=str('True')
>>> a
'True'
>>> a=str([1,2,3])
>>> a
'[1, 2, 3]'
>>> a=str((1,2,3))
>>> a
'(1, 2, 3)'
>>> a=str({1:100, 2:200, 3:300})
>>> a
'{1: 100, 2: 200, 3: 300}'

= 序列类型的转换[id="_conversion_of_sequence_types"]==== 序列类型的转换 列表、元组和字符串是 Python 中的序列类型。它们是按顺序排列或按索引排列的项目集合。 字符串和元组可以通过使用 list() 函数转化为列表对象。类似地, tuple() 函数将字符串或列表转化为元组。 我们将研究这三种序列类型中的每个对象,及其相互转化。

>>> a=[1,2,3,4,5]
>>> b=(1,2,3,4,5)
>>> c="Hello"
### list() separates each character in the string and builds the list
>>> obj=list(c)
>>> obj
['H', 'e', 'l', 'l', 'o']
### The parentheses of tuple are replaced by square brackets
>>> obj=list(b)
>>> obj
[1, 2, 3, 4, 5]
### tuple() separates each character from string and builds a tuple of
characters
>>> obj=tuple(c)
>>> obj
('H', 'e', 'l', 'l', 'o')
### square brackets of list are replaced by parentheses.
>>> obj=tuple(a)
>>> obj
(1, 2, 3, 4, 5)
### str() function puts the list and tuple inside the quote symbols.
>>> obj=str(a)
>>> obj
'[1, 2, 3, 4, 5]'
>>> obj=str(b)
>>> obj
'(1, 2, 3, 4, 5)'

因此,Python 的显式类型转换特性允许借助于其内置函数,将一种数据类型转化为另一种数据类型。 = Python - Unicode 系统[id="_python_unicode_system"]== Python - Unicode 系统 软件应用程序经常需要以不同的语言(如英语、法语、日语、希伯来语或印地语)显示输出信息。Python 的字符串类型使用 Unicode 标准来表示字符。这使得该程序能够处理所有这些不同的可能字符。 字符是文本中可能的最小的组成部分。“A”、“B”、“C”等等,都是不同的字符。“È”和“Í”也是不同的字符。 根据 Unicode 标准,字符由代码点表示。代码点值是 0 到 0x10FFFF 范围内的整数。 代码点的序列在内存中表示为一组代码单元,映射到 8 位字节。将 Unicode 字符串转换为字节序列的规则称为字符编码。 存在三种类型的编码:UTF-8、UTF-16 和 UTF-32。UTF 代表 Unicode Transformation Format 。 Python 3.0 及更高版本已内置支持 Unicode。 str 类型包含 Unicode 字符,因此使用单引号、双引号或三重引号字符串语法创建的任何字符串都将存储为 Unicode。Python 源代码的默认编码为 UTF-8。 因此,字符串可能包含 Unicode 字符的文字表示形式 (3/4) 或其 Unicode 值 (\u00BE)。

var = "3/4"
print (var)
var = "\u00BE"
print (var)

以上代码将产生以下 output

'3/4'
3/4

在下例中,一个字符串“10”使用 1 和 0 的 Unicode 值(分别为 \u0031 和 u0030)进行存储。

var = "\u0031\u0030"
print (var)

它将生成以下 output

10

字符串以人类可读的格式显示文字,字节将字符存储为二进制数据。编码将数据从字符字符串转换为一系列字节。解码将字节转换回人类可读字符和符号。重要的是不要 将这两种方法混淆。encode 是字符串方法,而 decode 是 Python 字节对象的方法。 在下面的示例中,我们有一个由 ASCII 字符组成的字符串变量。ASCII 是 Unicode 字符集的一个子集。可以使用 encode() 方法将其转换为字节对象。

string = "Hello"
tobytes = string.encode('utf-8')
print (tobytes)
string = tobytes.decode('utf-8')
print (string)

反解码 (decode()) 方法将字节对象转回 str 对象。所使用的反解码方法为 utf-8。

b'Hello'
Hello

在下例中,卢比符号(₹)存储在变量中,使用其 Unicode 值。我们将字符串转换为字节,然后转换为 str。

string = "\u20B9"
print (string)
tobytes = string.encode('utf-8')
print (tobytes)
string = tobytes.decode('utf-8')
print (string)

执行上述代码时,将会生成以下 output

₹
b'\xe2\x82\xb9'
₹

= Python - Literals[id="_python_literals"]== Python - Literals 在计算机科学中,字面量是一种表示源代码中固定值的形式。例如,在赋值语句中。

x = 10

此处 10 是一个字面量,因为表示 10 的数字值直接存储在内存中。但是,

y = x*2

此处,即使表达式计算为 20,也不会直接包含在源代码中。还可以使用内置 int() 函数声明一个 int 对象 −

x = int(10)

但是,这也是实例化的间接方式,而不是使用字面量。 可以使用字面量表示形式为任何内置数据类型创建对象。 = 整数字面量[id="_integer_literal"]=== 整数字面量 只包含数字符号(0 到 9)的任何表示都创建了一个 int 类型的对象。这样声明的对象可以使用赋值运算符来引用变量。 看看以下 example

x = 10
y = -25
z = 0

Python 允许将整数表示为八进制数字或十六进制数字。仅使用八个数字符号(0 到 7)但以 0o 或 0O 为前缀的数字表示形式是八进制数。

x = 0O34

类似地,由一串十六进制符号(0 到 9 和 a 到 f)组成,并以 0x 或 0X 为前缀的表示一个以十六进制形式表示的整数。

x = 0X1C

但是,需要注意的是,即使使用八进制或十六进制字面量符号,Python 在内部也会将其视为 int 类型。

# Using Octal notation
x = 0O34
print ("0O34 in octal is", x, type(x))
# Using Hexadecimal notation
x = 0X1c
print ("0X1c in Hexadecimal is", x, type(x))

当您运行此代码时,它将生成以下 output

0O34 in octal is 28 <class 'int'>
0X1c in Hexadecimal is 28 <class 'int'>

= 浮点字面量[id="_float_literal"]=== 浮点字面量 浮点数由整数部分和小数部分组成。按照惯例,小数点符号(.)在浮点数的字面量表示中分隔这两个部分。例如,

x = 25.55
y = 0.05
z = -12.2345

对于一位数在小数点前或后的浮点数,如果位数过多,会使用科学计数法进行紧凑的字面量表示。在整数部分之后加上正整数或负整数的符号 E 或 e。 例如,数字 1.23E05 等于 123000.00。同样,1.23e-2 等于 0.0123

# Using normal floating point notation
x = 1.23
print ("1.23 in normal float literal is", x, type(x))
# Using Scientific notation
x = 1.23E5
print ("1.23E5 in scientific notation is", x, type(x))
x = 1.23E-2
print ("1.23E-2 in scientific notation is", x, type(x))

在这里,你会得到以下 output

1.23 in normal float literal is 1.23 <class 'float'>
1.23E5 in scientific notation is 123000.0 <class 'float''>
1.23E-2 in scientific notation is 0.0123 <class 'float''>

= 复数字面量[id="_complex_literal"]=== 复数字面量 复数包含实数和虚数部分。虚数部分是任何数字(整数或浮点数)乘以“-1”的平方根 ($\sqrt{−1}$)。在字面量表示中 ($\sqrt{−1}$) 由“j”或“J”表示。因此,复数的字面量表示形式为 x+yj。

#Using literal notation of complex number
x = 2+3j
print ("2+3j complex literal is", x, type(x))
y = 2.5+4.6j
print ("2.5+4.6j complex literal is", x, type(x))

该代码将会生成以下 output

2+3j complex literal is (2+3j) <class 'complex'>
2.5+4.6j complex literal is (2+3j) <class 'complex'>

= 字符串字面量[id="_string_literal"]=== 字符串字面量 字符串对象是 Python 中的序列数据类型之一。它是一个不可变的 Unicode 代码点序列。代码点是一个根据 Unicode 标准对应于一个字符的数字。字符串是 Python 内置类 'str' 的对象。 字符串字面量通过将字符序列括在单引号('hello')、双引号("hello")或三引号('''hello''' 或 """hello""")中写成。

var1='hello'
print ("'hello' in single quotes is:", var1, type(var1))
var2="hello"
print ('"hello" in double quotes is:', var1, type(var1))
var3='''hello'''
print ("''''hello'''' in triple quotes is:", var1, type(var1))
var4="""hello"""
print ('"""hello""" in triple quotes is:', var1, type(var1))

在这里,你会得到以下 output

'hello' in single quotes is: hello <class 'str'>
"hello" in double quotes is: hello <class 'str'>
''''hello'''' in triple quotes is: hello <class 'str'>
"""hello""" in triple quotes is: hello <class 'str'>

如果需要将双引号作为字符串的一部分嵌入,则应将字符串本身放到单引号中。另一方面,如果要嵌入单引号文本,则应使用双引号编写字符串。

var1='Welcome to "Python Tutorial" from TutorialsPoint'
print (var1)
var2="Welcome to 'Python Tutorial' from TutorialsPoint"
print (var2)

它将生成以下 output

Welcome to "Python Tutorial" from TutorialsPoint
Welcome to 'Python Tutorial' from TutorialsPoint

= 列表字面量[id="_list_literal"]=== 列表字面量 Python 中的列表对象是其他数据类型对象的一个集合。列表是有序的项集合,不一定是同类型的。集合中的单个对象由从零开始的索引访问。 列表对象的文本表示形式通过一个或多个逗号分隔、并用方括号 [] 括起来的对象来表示。

L1=[1,"Ravi",75.50, True]
print (L1, type(L1))

它将生成以下 output

[1, 'Ravi', 75.5, True] <class 'list'>

= 元组字面量[id="_tuple_literal"]=== 元组字面量 Python 中的元组对象是其他数据类型的对象的集合。元组是有序的项目集合,不一定具有相同的类型。集合中的各个对象按索引从零开始访问。 元组对象的文本表示形式通过一个或多个逗号分隔、并用括号 () 括起来的对象来表示。

T1=(1,"Ravi",75.50, True)
print (T1, type(T1))

它将生成以下 output

[1, 'Ravi', 75.5, True] <class tuple>

Python 序列的默认分隔符是括号,这意味着一个没有括号的逗号分隔序列也相当于一个元组的声明。

T1=1,"Ravi",75.50, True
print (T1, type(T1))

在这里,您也将获得相同的 output

[1, 'Ravi', 75.5, True] <class tuple>

= 字典字面量[id="_dictionary_literal"]=== 字典字面量 与列表或元组类似,字典也是一种集合数据类型。但是,它不是序列。它是无序的项目集合,其中每个项目都是键值对。值通过冒号 ":" 符号与键绑定。用逗号分隔的一对或多对键值对放入花括号中({})以形成字典对象。

capitals={"USA":"New York", "France":"Paris", "Japan":"Tokyo",
"India":"New Delhi"}
numbers={1:"one", 2:"Two", 3:"three",4:"four"}
points={"p1":(10,10), "p2":(20,20)}

键应为一个不可变对象。数字、字符串或元组可以用作键。键在同一个集合中不可出现多次。如果某个键出现多次,则只有最后一个会被保留。值可以是任何数据类型。一个值可以分配给多个键。例如:

staff={"Krishna":"Officer", "Rajesh":"Manager", "Ragini":"officer", "Anil":"Clerk", "Kavita":"Manager"}

= Python - 运算符[id="_python_operators"]== Python - 运算符 在 Python 以及任何编程语言中,运算符都是预定义的符号(有时是关键字),用于对一个或多个操作数执行某些最常用的操作。 = 运算符类型[id="_types_of_operators"]=== 运算符类型 Python 语言支持以下类型的运算符 -

  1. Arithmetic Operators

  2. Comparison (Relational) Operators

  3. Assignment Operators

  4. Logical Operators

  5. Bitwise Operators

  6. Membership Operators

  7. Identity Operators

让我们逐个查看所有运算符。 = Python - 算术运算符[id="_python_arithmetic_operators"]== Python - 算术运算符 在 Python 中,数字是最常用的数据类型。Python 使用相同符号进行基本算术运算,每个人都熟悉这些符号,即加号 "" 用于加法,减号 "-" 用于减法,"@"{s0}" 用于乘法(代替数学/代数中使用的 "x"),斜线 "/" 用于除法(再次替代数学中使用的 "÷")。 此外,Python 还定义了更多算术运算符。它们是 "%"(取模)、"**"(指数)和 "//"(向下取整除)。 算术运算符是二元运算符,意思是对两个操作数进行运算。Python 完全支持混合算术。也就是说,两个操作数可以是两种不同的数字类型。在这种情况下,Python 会扩展较窄的操作数。整数对象比浮点数窄,而浮点数比复数对象窄。因此,int 和 float 算术运算的结果是 float。float 和 complex 的结果是复数,类似地,integer 和 complex 对象上的运算结果是 complex 对象。 让我们通过示例来研究这些运算符。 = Python - 加法运算符 ()[id="_python_addition_operator"]=== Python - 加法运算符 () 此运算符发音为 plus,是基本的算术运算符。它将两侧的两个数字操作数相加,并返回加法结果。 在下例中,两个整型变量是 "" 运算符的操作数。

a=10
b=20
print ("Addition of two integers")
print ("a =",a,"b =",b,"addition =",a+b)

它将生成以下 output

Addition of two integers
a = 10 b = 20 addition = 30

整型和浮点数的加法得到浮点数。

a=10
b=20.5
print ("Addition of integer and float")
print ("a =",a,"b =",b,"addition =",a+b)

它将生成以下 output

Addition of integer and float
a = 10 b = 20.5 addition = 30.5

将浮点数加到复数的结果是复数。

a=10+5j
b=20.5
print ("Addition of complex and float")
print ("a=",a,"b=",b,"addition=",a+b)

它将生成以下 output

Addition of complex and float
a= (10+5j) b= 20.5 addition= (30.5+5j)

= Python 减法运算符 (-)[id="_python_subtraction_operator"]=== Python 减法运算符 (-) 此运算符称为负号,计算第二个操作数与第一个操作数之差。如果第二个操作数较大,则结果为负数。 第一个示例说明两个整数的减法。

a=10
b=20
print ("Subtraction of two integers:")
print ("a =",a,"b =",b,"a-b =",a-b)
print ("a =",a,"b =",b,"b-a =",b-a)

结果 −

Subtraction of two integers
a = 10 b = 20 a-b = -10
a = 10 b = 20 b-a = 10

用一个整数和一个浮点数进行减法遵循相同的原理。

a=10
b=20.5
print ("subtraction of integer and float")
print ("a=",a,"b=",b,"a-b=",a-b)
print ("a=",a,"b=",b,"b-a=",b-a)

它将生成以下 output

subtraction of integer and float
a= 10 b= 20.5 a-b= -10.5
a= 10 b= 20.5 b-a= 10.5

进行复杂减法和浮点数减法时,实部参与运算。

a=10+5j
b=20.5
print ("subtraction of complex and float")
print ("a=",a,"b=",b,"a-b=",a-b)
print ("a=",a,"b=",b,"b-a=",b-a)

它将生成以下 output

subtraction of complex and float
a= (10+5j) b= 20.5 a-b= (-10.5+5j)
a= (10+5j) b= 20.5 b-a= (10.5-5j)

= Python 乘法运算符 ()[id="_python_multiplication_operator"]=== Python 乘法运算符 () *(星号)符号在 Python 中定义为乘法运算符(如同在许多语言中定义的一样)。它返回其两侧两个操作数的乘积。如果任一操作数为负数,结果也为负数。如果两者均为负数,结果为正数。更改操作数的顺序不会更改结果

a=10
b=20
print ("Multiplication of two integers")
print ("a =",a,"b =",b,"a*b =",a*b)

它将生成以下 output

Multiplication of two integers
a = 10 b = 20 a*b = 200

在乘法中,浮点数操作数可能采用标准小数点表示法,或采用科学计数法。

a=10
b=20.5
print ("Multiplication of integer and float")
print ("a=",a,"b=",b,"a*b=",a*b)
a=-5.55
b=6.75E-3
print ("Multiplication of float and float")
print ("a =",a,"b =",b,"a*b =",a*b)

它将生成以下 output

Multiplication of integer and float
a = 10 b = 20.5 a-b = -10.5
Multiplication of float and float
a = -5.55 b = 0.00675 a*b = -0.037462499999999996

对于涉及一个复杂操作数的乘法运算,另一个操作数与实部和虚部两部分相乘。

a=10+5j
b=20.5
print ("Multiplication of complex and float")
print ("a =",a,"b =",b,"a*b =",a*b)

它将生成以下 output

Multiplication of complex and float
a = (10+5j) b = 20.5 a*b = (205+102.5j)

= Python 除法运算符 (/)[id="_python_division_operator"]=== Python 除法运算符 (/) “/”符号通常称为正斜杠。除法运算符的结果为分子(左操作数)除以分母(右操作数)。如果任一操作数为负数,则结果为负数。由于不能在内存中存储无限大,因此在分母为 0 时,Python 会引发 ZeroDivisionError。 在 Python 中,除法运算符的结果始终是浮点数,即使两个操作数都是整数。

a=10
b=20
print ("Division of two integers")
print ("a=",a,"b=",b,"a/b=",a/b)
print ("a=",a,"b=",b,"b/a=",b/a)

它将生成以下 output

Division of two integers
a= 10 b= 20 a/b= 0.5
a= 10 b= 20 b/a= 2.0

除法中,浮点数操作数可能采用标准小数点表示法,或采用科学计数法。

a=10
b=-20.5
print ("Division of integer and float")
print ("a=",a,"b=",b,"a/b=",a/b)
a=-2.50
b=1.25E2
print ("Division of float and float")
print ("a=",a,"b=",b,"a/b=",a/b)

它将生成以下 output

Division of integer and float
a= 10 b= -20.5 a/b= -0.4878048780487805
Division of float and float
a= -2.5 b= 125.0 a/b= -0.02

当其中一个操作数是复数时,其他操作数与复数(实数和虚数)对象的各个部分进行除法。

a=7.5+7.5j
b=2.5
print ("Division of complex and float")
print ("a =",a,"b =",b,"a/b =",a/b)
print ("a =",a,"b =",b,"b/a =",b/a)

它将生成以下 output

Division of complex and float
a = (7.5+7.5j) b = 2.5 a/b = (3+3j)
a = (7.5+7.5j) b = 2.5 b/a = (0.16666666666666666-0.16666666666666666j)

如果分子为 0,则除法结果始终为 0,但分母为 0 除外,在这种情况之下,Python 会引发 ZeroDivisionError,并显示除以零错误消息。

a=0
b=2.5
print ("a=",a,"b=",b,"a/b=",a/b)
print ("a=",a,"b=",b,"b/a=",b/a)

它将生成以下 output

a= 0 b= 2.5 a/b= 0.0
Traceback (most recent call last):
  File "C:\Users\mlath\examples\example.py", line 20, in <module>
     print ("a=",a,"b=",b,"b/a=",b/a)
                                 ~^~
ZeroDivisionError: float division by zero

= Python 取模求余运算符 (%)[id="_python_modulus_operator"]=== Python 取模求余运算符 (%) Python 定义了符号“%”,这被称为百分比符号,即取模(或 modulo)运算符。它返回分母除以分子后的余数。它也可以称为取余运算符。取模运算符的结果是整数商之后的剩余数字。举个例子,当 10 除以 3 时,商为 3,余数为 1。因此,10%3(通常读作 10 模 3)的结果为 1。 如果两个操作数都是整数,则模值是整数。如果分子完全可除,则余数为 0。如果分子小于分母,则模数等于分子。如果分母为 0,则 Python 会引发 ZeroDivisionError。

a=10
b=2
print ("a=",a, "b=",b, "a%b=", a%b)
a=10
b=4
print ("a=",a, "b=",b, "a%b=", a%b)
print ("a=",a, "b=",b, "b%a=", b%a)
a=0
b=10
print ("a=",a, "b=",b, "a%b=", a%b)
print ("a=", a, "b=", b, "b%a=",b%a)

它将生成以下 output

a= 10 b= 2 a%b= 0
a= 10 b= 4 a%b= 2
a= 10 b= 4 b%a= 4
a= 0 b= 10 a%b= 0
Traceback (most recent call last):
  File "C:\Users\mlath\examples\example.py", line 13, in <module>
    print ("a=", a, "b=", b, "b%a=",b%a)
                                    ~^~
ZeroDivisionError: integer modulo by zero

如果任何操作数为浮点数,则模值始终为浮点数。

a=10
b=2.5
print ("a=",a, "b=",b, "a%b=", a%b)
a=10
b=1.5
print ("a=",a, "b=",b, "a%b=", a%b)
a=7.7
b=2.5
print ("a=",a, "b=",b, "a%b=", a%b)
a=12.4
b=3
print ("a=",a, "b=",b, "a%b=", a%b)

它将生成以下 output

a= 10 b= 2.5 a%b= 0.0
a= 10 b= 1.5 a%b= 1.0
a= 7.7 b= 2.5 a%b= 0.20000000000000018
a= 12.4 b= 3 a%b= 0.40000000000000036

Python 不支持将复数用作模运算中的操作数。它会引发 TypeError: % 的不兼容操作数类型。 = Python − 指数运算符 () [id="_python_exponent_operator"] = Python − 指数运算符 () Python 使用 *(双星号)作为指数运算符(有时称为求幂运算符)。因此,对于 a*b,您可以说 a 的 b 次方,甚至是 a 的 b 次方。 如果在指数表达式中,两个操作数都是整数,结果也是整数。如果其中一个为浮点数,则结果为浮点数。同样,如果任一操作数是复数,指数运算符返回一个复数。 如果底数为 0,则结果为 0,如果指数为 0,则结果始终为 1。

a=10
b=2
print ("a=",a, "b=",b, "a**b=", a**b)
a=10
b=1.5
print ("a=",a, "b=",b, "a**b=", a**b)
a=7.7
b=2
print ("a=",a, "b=",b, "a**b=", a**b)
a=1+2j
b=4
print ("a=",a, "b=",b, "a**b=", a**b)
a=12.4
b=0
print ("a=",a, "b=",b, "a**b=", a**b)
print ("a=",a, "b=",b, "b**a=", b**a)

它将生成以下 output

a= 10 b= 2 a**b= 100
a= 10 b= 1.5 a**b= 31.622776601683793
a= 7.7 b= 2 a**b= 59.290000000000006
a= (1+2j) b= 4 a**b= (-7-24j)
a= 12.4 b= 0 a**b= 1.0
a= 12.4 b= 0 b**a= 0.0

= Python − 取整除运算符 (//) [id="_python_floor_division_operator"] = Python − 取整除运算符 (//) 取整除也称为整数除法。Python 使用 //(双正斜杠)符号来实现此目的。与返回余数的模数或模运算不同,取整除给出了涉及操作数的商。 如果两个操作数都为正,取整运算符返回一个移除了小数部分的数字。例如,9.8 除以 2 的取整除结果为 4(纯除法为 4.9,去除掉小数部分,结果为 4)。 但如果其中一个操作数为负,结果会从 0 向远离的方向取整(朝向负无穷大)。-9.8 除以 2 的取整除结果为 5(纯除法为 4.9,从 0 向远离的方向取整)。

a=9
b=2
print ("a=",a, "b=",b, "a//b=", a//b)
a=9
b=-2
print ("a=",a, "b=",b, "a//b=", a//b)
a=10
b=1.5
print ("a=",a, "b=",b, "a//b=", a//b)
a=-10
b=1.5
print ("a=",a, "b=",b, "a//b=", a//b)

它将生成以下 output

a= 9 b= 2 a//b= 4
a= 9 b= -2 a//b= -5
a= 10 b= 1.5 a//b= 6.0
a= -10 b= 1.5 a//b= -7.0

= Python − 复数运算 [id="_python_complex_number_arithmetic"] = Python − 复数运算 当两个操作数都是复数对象时,算术运算的不同之处在于它们的行为。 复数的加法和减法是各自实数部分和虚数部分的简单加/减法。

a=2.5+3.4j
b=-3+1.0j
print ("Addition of complex numbers - a=",a, "b=",b, "a+b=", a+b)
print ("Subtraction of complex numbers - a=",a, "b=",b, "a-b=", a-b)

它将生成以下 output

Addition of complex numbers - a= (2.5+3.4j) b= (-3+1j) a+b= (-0.5+4.4j)
Subtraction of complex numbers - a= (2.5+3.4j) b= (-3+1j) a-b=
(5.5+2.4j)

复数的乘法类似于代数中的二项式乘法。如果“a+bj”和“x+yj”是两个复数,那么它们相乘的结果由该公式给出:

(a+bj)*(x+yj) = ax+ayj+xbj+byj2 = (ax-by)+(ay+xb)j

For example,

a=6+4j
b=3+2j
c=a*b
c=(18-8)+(12+12)j
c=10+24j

下面的程序确认了该结果:

a=6+4j
b=3+2j
print ("Multplication of complex numbers - a=",a, "b=",b, "a*b=", a*b)

要了解如何对两个复数进行除法,我们应该利用复数的共轭。Python 的 complex 对象有一个 conjugate() 方法,它返回一个虚数部分符号相反的复数。

>>> a=5+6j
>>> a.conjugate()
(5-6j)

要除两个复数,将分子和分母除以分母的共轭,然后进行乘法。

a=6+4j
b=3+2j
c=a/b
c=(6+4j)/(3+2j)
c=(6+4j)*(3-2j)/3+2j)*(3-2j)
c=(18-12j+12j+8)/(9-6j+6j+4)
c=26/13
c=2+0j

要进行验证,运行以下代码:

a=6+4j
b=3+2j
print ("Division of complex numbers - a=",a, "b=",b, "a/b=", a/b)

Python 中的复杂类不支持取模运算符 (%) 和取整除运算符 (//)。 == Python - 赋值运算符[id="_python_assignment_operators"]== Python 的赋值运算符 = (等于)符号在 Python 中定义为赋值运算符。其右侧的 Python 表达式的值分配给左侧的单个变量。= 符号在一般的编程(尤其是 Python)中的用处,不应与其在数学中的用法相混淆;在数学中,它表示符号两侧的表达式相等。 除了简单的赋值运算符外,Python 还提供了更多可用于高级用途的赋值运算符。它们称为累积赋值运算符或扩充赋值运算符。在本章中,我们将学习如何使用 Python 中定义的扩充赋值运算符。 考虑下面的 Python 语句:

a=10
b=5
a=a+b
print (a)

一开始,对于编程新手而言,即使他们懂数学,“a=a+b”这条语句看起来也很奇怪。a 怎么可能等于“a+b”?然而,需要注意的是,符号在这里是一个赋值运算符,而不是用来表示左右两侧相等。 因为它是一个赋值,所以右侧表达式求值为 15,该值被分配给 a。 在语句“a+=b”中,两个运算符“" 和 "=" 可以组合成一个“=" 运算符。这称为加法和赋值运算符。在一条语句中,它对两个操作数“a”和“b”执行加法运算,并将结果分配给左侧操作数, 即“a”。 = 运算符是一个扩充运算符。它也被称为累加运算符,因为它在“a”中加上“b”,并将结果重新分配给变量。 Python 针对所有算术和比较运算符均具有扩充赋值运算符。 == Python - 扩充加法运算符 (=)[id="_python_augmented_addition_operator"]== Python 的扩充加法运算符 (=) 此运算符在一个语句中组合加法和赋值。由于 Python 支持混合算术,两个操作数可以是不同类型的。但如果右侧操作数更宽,左侧操作数的类型将更改为右侧操作数的类型。 以下示例将有助于理解 "=" 运算符如何工作:

a=10
b=5
print ("Augmented addition of int and int")
a+=b #equivalent to a=a+b
print ("a=",a, "type(a):", type(a))
a=10
b=5.5
print ("Augmented addition of int and float")
a+=b #equivalent to a=a+b
print ("a=",a, "type(a):", type(a))
a=10.50
b=5+6j
print ("Augmented addition of float and complex")
a+=b #equivalent to a=a+b
print ("a=",a, "type(a):", type(a))

它将生成以下 output

Augmented addition of int and int
a= 15 type(a): <class 'int'>
Augmented addition of int and float
a= 15.5 type(a): <class 'float'>
Augmented addition of float and complex
a= (15.5+6j) type(a): <class 'complex'>

== Python - 扩充减法运算符 (-=)[id="_python_augmented_subtraction_operator"]=== Python 的扩充减法运算符 (-=) 使用 -= 符号在一个语句中执行减法和赋值操作。操作数可以是任何数字类型。Python 对较窄的对象执行隐式类型转换。

a=10
b=5
print ("Augmented subtraction of int and int")
a-=b #equivalent to a=a-b
print ("a=",a, "type(a):", type(a))
a=10
b=5.5
print ("Augmented subtraction of int and float")
a-=b #equivalent to a=a-b
print ("a=",a, "type(a):", type(a))
a=10.50
b=5+6j
print ("Augmented subtraction of float and complex")
a-=b #equivalent to a=a-b
print ("a=",a, "type(a):", type(a))

它将生成以下 output

Augmented subtraction of int and int
a= 5 type(a): <class 'int'>
Augmented subtraction of int and float
a= 4.5 type(a): <class 'float'>
Augmented subtraction of float and complex
a= (5.5-6j) type(a): <class 'complex'>

== Python - 扩充乘法运算符 (=)[id="_python_augmented_multiplication_operator"]=== Python 的扩充乘法运算符 (=) “@ {s0}=b”执行乘法和赋值操作,相当于“a=a*b”。对于两个复数的扩充乘法,上一章讨论的乘法规则适用。

a=10
b=5
print ("Augmented multiplication of int and int")
a*=b #equivalent to a=a*b
print ("a=",a, "type(a):", type(a))
a=10
b=5.5
print ("Augmented multiplication of int and float")
a*=b #equivalent to a=a*b
print ("a=",a, "type(a):", type(a))
a=6+4j
b=3+2j
print ("Augmented multiplication of complex and complex")
a*=b #equivalent to a=a*b
print ("a=",a, "type(a):", type(a))

它将生成以下 output

Augmented multiplication of int and int
a= 50 type(a): <class 'int'>
Augmented multiplication of int and float
a= 55.0 type(a): <class 'float'>
Augmented multiplication of complex and complex
a= (10+24j) type(a): <class 'complex'>

== Python - 扩充除法运算符 (/=)[id="_python_augmented_division_operator"]=== Python 的扩充除法运算符 (/=) 组合符号“/=”用作除法和赋值运算符,因此“a/=b”相当于“a=a/b”。int 或 float 操作数的除法运算为 float。两个复数的除法返回一个复数下文给出扩充除法运算符的示例。

a=10
b=5
print ("Augmented division of int and int")
a/=b #equivalent to a=a/b
print ("a=",a, "type(a):", type(a))
a=10
b=5.5
print ("Augmented division of int and float")
a/=b #equivalent to a=a/b
print ("a=",a, "type(a):", type(a))
a=6+4j
b=3+2j
print ("Augmented division of complex and complex")
a/=b #equivalent to a=a/b
print ("a=",a, "type(a):", type(a))

它将生成以下 output

Augmented division of int and int
a= 2.0 type(a): <class 'float'>
Augmented division of int and float
a= 1.8181818181818181 type(a): <class 'float'>
Augmented division of complex and complex
a= (2+0j) type(a): <class 'complex'>

= Python - 增强的取模运算符 (%=)[id="_python_augmented_modulus_operator"]=== Python - 增强的取模运算符 (%=) 如需在单个语句中执行取模和赋值运算,请使用 %= 运算符。与 mod 运算符一样,其增强的版本也不支持复数。

a=10
b=5
print ("Augmented modulus operator with int and int")
a%=b #equivalent to a=a%b
print ("a=",a, "type(a):", type(a))
a=10
b=5.5
print ("Augmented modulus operator with int and float")
a%=b #equivalent to a=a%b
print ("a=",a, "type(a):", type(a))

它将生成以下 output

Augmented modulus operator with int and int
a= 0 type(a): <class 'int'>
Augmented modulus operator with int and float
a= 4.5 type(a): <class 'float'>

= Python - 增强的指数运算符 (=)[id="_python_augmented_exponent_operator"]=== Python - 增强的指数运算符 (=) “**=”运算符会导致计算“a”的“b”次方,并将值赋回给“a”。下面给出了几个示例:

a=10
b=5
print ("Augmented exponent operator with int and int")
a**=b #equivalent to a=a**b
print ("a=",a, "type(a):", type(a))
a=10
b=5.5
print ("Augmented exponent operator with int and float")
a**=b #equivalent to a=a**b
print ("a=",a, "type(a):", type(a))
a=6+4j
b=3+2j
print ("Augmented exponent operator with complex and complex")
a**=b #equivalent to a=a**b
print ("a=",a, "type(a):", type(a))

它将生成以下 output

Augmented exponent operator with int and int
a= 100000 type(a): <class 'int'>
Augmented exponent operator with int and float
a= 316227.7660168379 type(a): <class 'float'>
Augmented exponent operator with complex and complex
a= (97.52306038414744-62.22529992036203j) type(a): <class 'complex'>

= Python - 增强的取整除运算符 (//=)[id="_python_augmented_floor_division_operator"]=== Python - 增强的取整除运算符 (//=) 如需在单个语句中执行取整除和赋值,请使用 “//=”运算符。“a//=b”相当于“a=a//b”。此运算符不能用于复数。

a=10
b=5
print ("Augmented floor division operator with int and int")
a//=b #equivalent to a=a//b
print ("a=",a, "type(a):", type(a))
a=10
b=5.5
print ("Augmented floor division operator with int and float")
a//=b #equivalent to a=a//b
print ("a=",a, "type(a):", type(a))

它将生成以下 output

Augmented floor division operator with int and int
a= 2 type(a): <class 'int'>
Augmented floor division operator with int and float
a= 1.0 type(a): <class 'float'>

= Python - 比较运算符[id="_python_comparison_operators"]== Python - 比较运算符 Python 中的比较运算符在 Python 的条件语句( if, elseelif )和循环语句(while 和 for 循环)中非常重要。与算术运算符类似,比较运算符“ -”也称为关系运算符(“<”代表小于,“>”代表大于)是众所周知的。 Python 使用另外两个运算符,将“=”符号与这两个运算符结合起来。符号“⇐”表示小于或等于。符号“>=”表示大于或等于。 Python 还有另外两个比较运算符,形式为“==”和“!=”。它们表示等于和不等于运算符。因此,Python 中有六个比较运算符。 比较运算符本质上是二进制的,需要两个操作数。包含比较运算符的表达式称为布尔表达式,并且始终返回 True 或 False。

a=5
b=7
print (a>b)
print (a<b)

它将生成以下 output

False
True

两个操作数都可以是 Python 字面量、变量或表达式。由于 Python 支持混合算术,因此可以有任何数类型的操作数。 以下代码演示了 Python 的 comparison operators with integer numbers 的用法:

print ("Both operands are integer")
a=5
b=7
print ("a=",a, "b=",b, "a>b is", a>b)
print ("a=",a, "b=",b,"a<b is",a<b)
print ("a=",a, "b=",b,"a==b is",a==b)
print ("a=",a, "b=",b,"a!=b is",a!=b)

它将生成以下 output

Both operands are integer
a= 5 b= 7 a>b is False
a= 5 b= 7 a<b is True
a= 5 b= 7 a==b is False
a= 5 b= 7 a!=b is True

= 浮点数比较[id="_comparison_of_float_number"]==== 浮点数比较 在以下示例中,比较了一个整数和一个浮点操作数。

print ("comparison of int and float")
a=10
b=10.0
print ("a=",a, "b=",b, "a>b is", a>b)
print ("a=",a, "b=",b,"a<b is",a<b)
print ("a=",a, "b=",b,"a==b is",a==b)
print ("a=",a, "b=",b,"a!=b is",a!=b)

它将生成以下 output

comparison of int and float
a= 10 b= 10.0 a>b is False
a= 10 b= 10.0 a<b is False
a= 10 b= 10.0 a==b is True
a= 10 b= 10.0 a!=b is False

= 复数比较[id="_comparison_of_complex_umbers"]==== 复数比较 尽管复数对象是 Python 中的一个数字数据类型,但其行为与其他数据类型不同。Python 不支持 < 和 > 运算符,但是支持相等 (==) 和不等 (!=) 运算符。

print ("comparison of complex numbers")
a=10+1j
b=10.-1j
print ("a=",a, "b=",b,"a==b is",a==b)
print ("a=",a, "b=",b,"a!=b is",a!=b)

它将生成以下 output

comparison of complex numbers
a= (10+1j) b= (10-1j) a==b is False
a= (10+1j) b= (10-1j) a!=b is True

使用小于或大于运算符会得到 TypeError。

print ("comparison of complex numbers")
a=10+1j
b=10.-1j
print ("a=",a, "b=",b,"a<b is",a<b)
print ("a=",a, "b=",b,"a>b is",a>b)

它将生成以下 output

comparison of complex numbers
Traceback (most recent call last):
  File "C:\Users\mlath\examples\example.py", line 5, in <module>
    print ("a=",a, "b=",b,"a<b is",a<b)
                                      ^^^
TypeError: '<' not supported between instances of 'complex' and
'complex

= 布尔值比较[id="_comparison_of_booleans"]==== 布尔值比较 Python 中的布尔对象实际上是整数:True 是 1,False 是 0。实际上,Python 把任何非零数字当作 True。在 Python 中,比较布尔对象是可行的。 “False < True”为 True!

print ("comparison of Booleans")
a=True
b=False
print ("a=",a, "b=",b,"a<b is",a<b)
print ("a=",a, "b=",b,"a>b is",a>b)
print ("a=",a, "b=",b,"a==b is",a==b)
print ("a=",a, "b=",b,"a!=b is",a!=b)

它将生成以下 output

comparison of Booleans
a= True b= False a<b is False
a= True b= False a>b is True
a= True b= False a==b is False
a= True b= False a!=b is True

= 序列类型的比较[id="_comparison_of_sequence_types"]==== 序列类型的比较 在 Python 中,只能对相似的序列对象执行比较。字符串对象只能与另一个字符串比较。列表不能与元组比较,即使两者有相同的项。

print ("comparison of different sequence types")
a=(1,2,3)
b=[1,2,3]
print ("a=",a, "b=",b,"a<b is",a<b)

它将生成以下 output

comparison of different sequence types
Traceback (most recent call last):
  File "C:\Users\mlath\examples\example.py", line 5, in <module>
    print ("a=",a, "b=",b,"a<b is",a<b)
                                       ^^^
TypeError: '<' not supported between instances of 'tuple' and 'list'

序列对象通过词法排序机制进行比较。比较从第 0 索引处的项开始。如果它们相等,则比较移至下一个索引,直到某些索引处的项碰巧不相等,或者其中一个序列用尽。如果一个序列是另一个序列的初始子序列,则较短的序列较小(较少)。 哪个操作数较大取决于不相等索引处的项值的差。例如,“BAT”>“BAR”为 True,因为 T 在 Unicode 顺序中排在 R 之后。 如果两个序列的所有项比较相等,则认为序列相等。

print ("comparison of strings")
a='BAT'
b='BALL'
print ("a=",a, "b=",b,"a<b is",a<b)
print ("a=",a, "b=",b,"a>b is",a>b)
print ("a=",a, "b=",b,"a==b is",a==b)
print ("a=",a, "b=",b,"a!=b is",a!=b)

它将生成以下 output

comparison of strings
a= BAT b= BALL a<b is False
a= BAT b= BALL a>b is True
a= BAT b= BALL a==b is False
a= BAT b= BALL a!=b is True

在以下示例中,比较了两个元组对象−

print ("comparison of tuples")
a=(1,2,4)
b=(1,2,3)
print ("a=",a, "b=",b,"a<b is",a<b)
print ("a=",a, "b=",b,"a>b is",a>b)
print ("a=",a, "b=",b,"a==b is",a==b)
print ("a=",a, "b=",b,"a!=b is",a!=b)

它将生成以下 output

a= (1, 2, 4) b= (1, 2, 3) a<b is False
a= (1, 2, 4) b= (1, 2, 3) a>b is True
a= (1, 2, 4) b= (1, 2, 3) a==b is False
a= (1, 2, 4) b= (1, 2, 3) a!=b is True

= 字典对象的比较[id="_comparison_of_dictionary_objects"]==== 字典对象的比较 未定义在 Python 的字典中使用“<”和“>”运算符。在使用这些运算符的情况下,将报告 TypeError:'<' 不支持 'dict' 和 'dict' 实例之间的比较。 相等比较检查两个 dict 项的长度是否相同。字典的长度是其中键值对的数量。 Python 字典仅仅按长度进行比较。元素较少的字典被认为少于元素较多的字典。

print ("comparison of dictionary objects")
a={1:1,2:2}
b={2:2, 1:1, 3:3}
print ("a=",a, "b=",b,"a==b is",a==b)
print ("a=",a, "b=",b,"a!=b is",a!=b)

它将生成以下 output

comparison of dictionary objects
a= {1: 1, 2: 2} b= {2: 2, 1: 1, 3: 3} a==b is False
a= {1: 1, 2: 2} b= {2: 2, 1: 1, 3: 3} a!=b is True

= Python - 逻辑运算符[id="_python_logical_operators"]== Python - 逻辑运算符 使用 Python 中的逻辑运算符,我们可以形成复合布尔表达式。这些逻辑运算符的每个操作数本身都是一个布尔表达式。例如,

age>16 and marks>80
percentage<50 or attendance<75

除了关键字 False,Python 将 None、所有类型的数字零、空序列(字符串、元组、列表)、空字典和空集合解释为 False。所有其他值都被视为 True。 Python 中有三个逻辑运算符。它们是“and”、“or”和“not”。它们必须是小写。 = “and”运算符[id="_the_and_operator"]==== “and”运算符 对于复合布尔表达式为 True,两个操作数都必须为 True。如果任何一个或两个操作数计算结果为 False,则表达式返回 False。下表显示了场景。 = “or”运算符[id="_the_or_operator"]==== “or”运算符 相反,如果任何一个操作数为 True,则 or 运算符返回 True。对于复合布尔表达式为 False,两个操作数都必须为 False,如下表所示 − = 非运算符[id="_the_not_operator"]==== 非运算符 这是一个一元运算符。会颠倒其后的布尔操作数的状态。因此,not True 变成 False,not False 变成 True。 = Python 解释器如何评估逻辑运算符?[id="_how_the_python_interpreter_evaluates_the_logical_operators"]==== Python 解释器如何评估逻辑运算符? 表达式 "x and y" 首先评估 "x"。若 "x" 为 false,则返回其值;否则,评估 "y" 并返回所产生的值。 image::https://www.iokays.com/tutorialspoint/python/_images/logical_operator.jpg[] 表达式 "x or y" 首先评估 "x";若 "x" 为 true,则返回其值;否则,评估 "y" 并返回所产生的值。 image::https://www.iokays.com/tutorialspoint/python/_images/x_or_y.jpg[] 下面给出逻辑运算符的几个用例 -

x = 10
y = 20
print("x > 0 and x < 10:",x > 0 and x < 10)
print("x > 0 and y > 10:",x > 0 and y > 10)
print("x > 10 or y > 10:",x > 10 or y > 10)
print("x%2 == 0 and y%2 == 0:",x%2 == 0 and y%2 == 0)
print ("not (x+y>15):", not (x+y)>15)

它将生成以下 output

x > 0 and x < 10: False
x > 0 and y > 10: True
x > 10 or y > 10: True
x%2 == 0 and y%2 == 0: True
not (x+y>15): False

我们可以对逻辑运算符使用非布尔操作数。在此,我们需要注意到任何非零数字和非空序列都会被评估为 True。因此,会应用逻辑运算符的相同真值表。 在以下示例中,数字操作数用于逻辑运算符。变量“x”、“y”的值为 True,“z”的值为 False

x = 10
y = 20
z = 0
print("x and y:",x and y)
print("x or y:",x or y)
print("z or x:",z or x)
print("y or z:", y or z)

它将生成以下 output

x and y: 20
x or y: 10
z or x: 10
y or z: 20

在以下示例中,字符串变量被视为 True,空元组被视为 False -

a="Hello"
b=tuple()
print("a and b:",a and b)
print("b or a:",b or a)

它将生成以下 output

a and b: ()
b or a: Hello

最后,下面的两个列表对象非空。因此 x and y 返回后者,而 x or y 返回前者。

x=[1,2,3]
y=[10,20,30]
print("x and y:",x and y)
print("x or y:",x or y)

它将生成以下 output

x and y: [10, 20, 30]
x or y: [1, 2, 3]

= Python - 按位运算符[id="_python_bitwise_operators"]== Python - 按位运算符 Python 的按位运算符通常用于整数类型对象。然而,它不是将对象作为一个整体来对待,而是将其作为一系列位来对待。它对字符串中的每个位执行不同的操作。 Python 有六个按位运算符 - &、|、^、~、<< 和 >>。除了 ~ 之外,所有这些运算符本质上都是二元的,也就是说它们对两个操作数进行操作。每个操作数是一个二进制位 (bit) 1 或 0。 = Python − 按位 AND 运算符 (&)[id="_python_bitwise_and_operator"]=== Python − 按位 AND 运算符 (&) 按位 AND 运算符有点类似于逻辑与运算符。仅当两个位操作数均为 1(即 True)时,它才返回 True。所有组合如下所示:

0 & 0 is 0
1 & 0 is 0
0 & 1 is 0
1 & 1 is 1

当您使用整数作为操作数时,这两个整数都会转换为等效的二进制,& 操作针对每个数字的对应位执行,从最低有效位开始朝最高有效位移动。 让我们取两个整数 60 和 13,并将它们分别赋值给变量 a 和 b。

a=60
b=13
print ("a:",a, "b:",b, "a&b:",a&b)

它将生成以下 output

a: 60 b: 13 a&b: 12

要了解 Python 如何执行操作,请获取每个变量的二进制等效值。

print ("a:", bin(a))
print ("b:", bin(b))

它将生成以下 output

a: 0b111100
b: 0b1101

为方便起见,为每个数字使用标准 8 位格式,这样“a”就是 00111100,“b”就是 00001101。让我们手动对这两个数字的每个对应位执行 and 操作。

            0011 1100
                &
            0000 1101
            -------------
            0000 1100

将结果二进制值转换回整数。您将得到 12,这就是之前获得的结果。

>>> int('00001100',2)
12

= Python − 按位 OR 运算符 (|)[id="_python_bitwise_or_operator"]=== Python − 按位 OR 运算符 (|) “|”符号(称为 pipe )是按位 OR 运算符。如果任何一位操作数为 1,则结果为 1,否则为 0。

0 | 0 is 0
0 | 1 is 1
1 | 0 is 1
1 | 1 is 1

取 a=60、b=13 的相同值。“|”操作的结果为 61。获得它们的二进制等效值。

a=60
b=13
print ("a:",a, "b:",b, "a|b:",a|b)
print ("a:", bin(a))
print ("b:", bin(b))

它将生成以下 output

a: 60 b: 13 a|b: 61
a: 0b111100
b: 0b1101

要手动执行“|”操作,请使用 8 位格式。

                0011 1100
                    |
                0000 1101
                -------------
                0011 1101

将二进制数转换回整数以比较结果 −

>>> int('00111101',2)
61

= Python − 二进制 XOR 运算符 (^)[id="_python_binary_xor_operator"]=== Python − 二进制 XOR 运算符 (^) 术语 XOR 代表或排除。这意味着如果只有其中一个位为 1,则对两个位执行或运算的结果将为 1。

0 ^ 0 is 0
0 ^ 1 is 1
1 ^ 0 is 1
1 ^ 1 is 0

让我们对 a=60 和 b=13 执行 XOR 运算。

a=60
b=13
print ("a:",a, "b:",b, "a^b:",a^b)

它将生成以下 output

a: 60 b: 13 a^b: 49

现对位进行手动 XOR 运算。

            0011 1100
                ^
            0000 1101
            -------------
            0011 0001

int() 函数将 00110001 显示为 49。

>>> int('00110001',2)
49

= Python – 二进制 NOT 运算符 (~)[id="_python_binary_not_operator"]=== Python – 二进制 NOT 运算符 (~) 这个运算符是逻辑 NOT 运算符的二进制等价项。它会翻转每个位,使 1 变成 0,0 变成 1,并返回原始数字的补数。Python 使用 2 的补码方法。对于正整数,可以通过简单地颠倒位来获得它。对于负数 -x,它使用 (x-1) 的位模式来编写,并且所有这些位都进行了补码(将 1 转换为 0 或 0 转换为 1)。因此:(对于 8 位表示)

-1 is complement(1 - 1) = complement(0) = "11111111"
-10 is complement(10 - 1) = complement(9) = complement("00001001") = "11110110".

对于 a=60,其补数为 −

a=60
print ("a:",a, "~a:", ~a)

它将生成以下 output

a: 60 ~a: -61

= Python – 左移位运算符 (<<)[id="_python_left_shift_operator"]=== Python – 左移位运算符 (<<) 左移位运算符将最显着的位向右移动“<<”符号右侧的数字的位数。因此,“x << 2”会导致二进制表示向右移动两个位。让我们对 60 执行左移位。

a=60
print ("a:",a, "a<<2:", a<<2)

它将生成以下 output

a: 60 a<<2: 240

这是如何发生的?让我们使用 60 的二进制等价项,并向左移位 2。

            0011 1100
             <<
                 2
            -------------
            1111 0000

将二进制转换为整数。它为 240。

>>> int('11110000',2)
240

= Python – 右移位运算符 (>>)[id="_python_right_shift_operator"]==== Python – 右移位运算符 (>>) 右移位运算符将最不显着的位向左移动“>>”符号右侧的数字的位数。因此,“x >> 2”会导致二进制表示向左移动两个位。让我们对 60 执行右移位。

a=60
print ("a:",a, "a>>2:", a>>2)

它将生成以下 output

a: 60 a>>2: 15

对 60 执行的手动右移位运算如下 −

         0011 1100
         >>
             2
         -------------
         0000 1111

使用 int() 函数将上述二进制数转换为整数。它是 15。

>>> int('00001111',2)
15

= Python - 成员资格运算符[id="_python_membership_operators"]== Python - 成员资格运算符 Python 中的成员资格运算符帮助我们确定给定容器类型对象中是否出现项目,或者换句话说,项目是否为给定容器类型对象的成员。 Python 有两个成员资格运算符:“in”和“not in”。两者都返回布尔结果。“in”运算符的结果与“not in”运算符的结果相反。 您可以使用 in 运算符来检查子字符串是否出现在更大的字符串中,列表或元组中是否存在任何项目,或者列表或元组中是否包含子列表或子元组。 在以下示例中,检查不同的子字符串是否属于字符串 var="TutorialsPoint"。Python根据字符的 Unicode 值来区分字符。因此,“To”与“to”不同。还要注意,如果“in”运算符返回 True,则“not in”运算符求值为 False。

var = "TutorialsPoint"
a = "P"
b = "tor"
c = "in"
d = "To"
print (a, "in", var, ":", a in var)
print (b, "not in", var, ":", b not in var)
print (c, "in", var, ":", c in var)
print (d, "not in", var, ":", d not in var)

它将生成以下 output

P in TutorialsPoint : True
tor not in TutorialsPoint : False
in in TutorialsPoint : True
To not in TutorialsPoint : True

您可以使用“in/not in”运算符来检查项目在列表或元组中的成员身份。

var = [10,20,30,40]
a = 20
b = 10
c = a-b
d = a/2
print (a, "in", var, ":", a in var)
print (b, "not in", var, ":", b not in var)
print (c, "in", var, ":", c in var)
print (d, "not in", var, ":", d not in var)

它将生成以下 output

20 in [10, 20, 30, 40] : True
10 not in [10, 20, 30, 40] : False
10 in [10, 20, 30, 40] : True
10.0 not in [10, 20, 30, 40] : False

在最后的情况下,“d”是一个浮点数,但它仍然与列表中的 10 (一个 int ) 比较为 True。即使给出了以二进制、八进制或十六进制等其他格式表示的数字,成员运算符也会告诉它是否在序列中。

>>> 0x14 in [10, 20, 30, 40]
True

但是,如果您尝试检查两个连续的数字是否存在于列表或元组中,in 运算符将返回 False。如果列表/元组本身将连续的数字作为序列包含在内,那么它将返回 True。

var = (10,20,30,40)
a = 10
b = 20
print ((a,b), "in", var, ":", (a,b) in var)
var = ((10,20),30,40)
a = 10
b = 20
print ((a,b), "in", var, ":", (a,b) in var)

它将生成以下 output

(10, 20) in (10, 20, 30, 40) : False
(10, 20) in ((10, 20), 30, 40) : True

Python 的成员运算符也适用于集合对象。

var = {10,20,30,40}
a = 10
b = 20
print (b, "in", var, ":", b in var)
var = {(10,20),30,40}
a = 10
b = 20
print ((a,b), "in", var, ":", (a,b) in var)

它将生成以下 output

20 in {40, 10, 20, 30} : True
(10, 20) in {40, 30, (10, 20)} : True

允许将 in 以及 not in 运算符与字典对象一起使用。但是,Python 仅使用键的集合来检查成员身份,而不是值。

var = {1:10, 2:20, 3:30}
a = 2
b = 20
print (a, "in", var, ":", a in var)
print (b, "in", var, ":", b in var)

它将生成以下 output

2 in {1: 10, 2: 20, 3: 30} : True
20 in {1: 10, 2: 20, 3: 30} : False

= Python - 恒等运算符[id="_python_identity_operators"]== Python - 恒等运算符 Python 有两个恒等运算符:is 和 is not。两者都返回相反的布尔值。“in”运算符在两个操作数对象共享相同的内存位置时求值为 True。可以通过“id()”函数获取对象的内存位置。如果两个变量的 id() 相同,“in”运算符返回 True(因此,is not 返回 False)。

a="TutorialsPoint"
b=a
print ("id(a), id(b):", id(a), id(b))
print ("a is b:", a is b)
print ("b is not a:", b is not a)

它将生成以下 output

id(a), id(b): 2739311598832 2739311598832
a is b: True
b is not a: False

列表和元组对象不同,乍一看可能很奇怪。在以下示例中,两个列表“a”和“b”包含相同的项目。但它们的 id() 不同。

a=[1,2,3]
b=[1,2,3]
print ("id(a), id(b):", id(a), id(b))
print ("a is b:", a is b)
print ("b is not a:", b is not a)

它将生成以下 output

id(a), id(b): 1552612704640 1552567805568
a is b: False
b is not a: True

这个列表或元组仅包含单个项的内存位置,而不包含项本身。因此,“a”包含某个位置中 10、20 和 30 整数对象的地址,其可能不同于“b”。

print (id(a[0]), id(a[1]), id(a[2]))
print (id(b[0]), id(b[1]), id(b[2]))

它将生成以下 output

140734682034984 140734682035016 140734682035048
140734682034984 140734682035016 140734682035048

由于“a”和“b”的两个不同位置,“ is ”运算符即使两个列表包含相同的数字也会返回 False。 = Python - 注释[id="_python_comments"]== Python - 注释 计算机程序中的注释是一段文本,旨在成为源代码中的解释性或描述性注释,在生成机器语言代码时不应被编译器/解释器考虑。在源程序中充分使用注释可以使每个人更容易地了解算法的语法、用法和逻辑等。 在 Python 脚本中,符号 # 标记注释行的开头。它在编辑器中行的末尾有效。如果 # 是行中的第一个字符,则整行都是注释。如果用在行中,则行前的文本是有效的 Python 表达式,而行后的文本被视为注释。

# this is a comment
print ("Hello World")
print ("How are you?") #also a comment but after a statement.

在 Python 中,没有提供编写多行注释或块注释的规定。(如在 C/C++ 中,/* .. */ 内的多个行被视为多行注释)。 每行应该在开头有“#”符号才能标记为注释。许多 Python IDE 都有将语句块标记为注释的快捷方式。 除非是函数或类的文档字符串,否则三引号多行字符串也视为注释。

'''
First line in the comment
Second line in the comment
Third line in the comment
'''
print ("Hello World")

= Python - 用户输入[id="_python_user_input"]== Python - 用户输入 每个计算机应用程序都应该有一个在运行时接受用户数据的条款。这使得应用程序具有交互性。根据开发方式,应用程序可以接受用户输入的形式,比如在控制 (sys.stdin) 中输入的文本、图形化布局或基于 web 的界面。在本章中,我们将学习 Python 如何从控制台接受用户输入,并将输出也显示在控制台上。 Python 解释器以交互和脚本模式工作。虽然交互模式适合快速评估,但效率较低。对于重复执行相同指令集,应该使用脚本模式。 让我们编写一个简单的 Python 脚本来开始。

#! /usr/bin/python3.11
name = "Kiran"
city = "Hyderabad"
print ("Hello My name is", name)
print ("I am from", city)

将上述代码另存为 hello.py,并从命令行中运行。以下是输出结果:

C:\python311> python var1.py
Hello My name is Kiran
I am from Hyderabad

该程序只是打印程序中两个变量的值。如果你重复运行该程序,每次都会显示相同的输出。若要将该程序用于其他姓名和城市,你可以编辑代码,将 name 改为“Ravi”,将 city 改为“Chennai”。每次需要指定不同的值时,你都必须编辑该程序,保存并运行代码,这不是理想的方式。 = input() 函数 [id="_input_function"] === input() 函数 显然,你需要在运行期间(程序正在运行)指定变量不同的机制。Python 的 input() 函数执行相同的工作。 Python 的标准库具有 input() 函数。

>>> var = input()

当解释器遇到此函数时,它会等待用户从标准输入流中输入数据(键盘输入),直至按 Enter 键。字符序列可能会存储在字符串变量中,以供以后使用。 在读取 Enter 键后,程序会继续执行下一条语句。让我们更改程序,将用户输入存储在 name 和 city 变量中。

#! /usr/bin/python3.11
name = input()
city = input()
print ("Hello My name is", name)
print ("I am from ", city)

运行时,你会发现光标在等待用户输入。输入 name 和 city 的值。使用输入的数据,输出结果会显示。

Ravi
Chennai
Hello My name is Ravi
I am from Chennai

现在,程序中并未为变量指定任何特定值。每次运行时,都可输入不同的值。因此,你的程序已经成为真正的交互式程序。 在 input() 函数中,你可以提供一个 prompt 文本,在运行代码时,该文本会出现在光标前。

#! /usr/bin/python3.11
name = input("Enter your name : ")
city = input("enter your city : ")
print ("Hello My name is", name)
print ("I am from ", city)

运行程序时,它会显示提示消息,实质上帮助用户输入内容。

Enter your name: Praveen Rao
enter your city: Bengaluru
Hello My name is Praveen Rao
I am from Bengaluru

= 数值输入 [id="_numeric_input"] === 数值输入 我们编写一段 Python 代码,它从用户处获取矩形的宽度和高度,并计算面积。

#! /usr/bin/python3.11
width = input("Enter width : ")
height = input("Enter height : ")
area = width*height
print ("Area of rectangle = ", area)

运行程序并输入宽度和高度。

Enter width: 20
Enter height: 30
Traceback (most recent call last):
  File "C:\Python311\var1.py", line 5, in <module>
   area = width*height
TypeError: can't multiply sequence by non-int of type 'str'

你为什么在这里得到一个 TypeError ?原因在于,Python 始终将用户输入作为字符串进行读取。因此,width="20" 和 height="30" 是字符串,显然你不能对两个字符串进行乘法运算。 为克服这一问题,我们将使用 int() ,这是 Python 标准库中的另一个内置函数。它将字符串对象转换为整数。 为从用户处获取整数输入,以字符串形式读取输入,然后使用 int() 函数将其类型转换为整数:

w= input("Enter width : ")
width=int(w)
h= input("Enter height : ")
height=int(h)

你可以将 input 和类型转换语句组合到一个语句中:

#! /usr/bin/python3.11
width = int(input("Enter width : "))
height = int(input("Enter height : "))
area = width*height
print ("Area of rectangle = ", area)

现在,你可以向程序中的两个变量输入任何整数值:

Enter width: 20
Enter height: 30
Area of rectangle = 600

Python 的 float() 函数将字符串转换为浮点对象。以下程序接受用户输入并将其解析为浮点变量 rate,并计算用户输入的金额的利息。

#! /usr/bin/python3.11
amount = float(input("Enter Amount : "))
rate = float(input("Enter rate of interest : "))
interest = amount*rate/100
print ("Amount: ", amount, "Interest: ", interest)

该程序要求用户输入金额和汇率;并显示结果如下 −

Enter Amount: 12500
Enter rate of interest: 6.5
Amount: 12500.0 Interest: 812.5

= print() 函数[id="_print_function"]==== print() 函数 Python 的 print() 函数是一个内置函数。它是最常用的函数,它在 Python 的控制台或标准输出 (sys.stdout) 上显示括号中给出的 Python 表达式的值。

print ("Hello World ")

括号内可以包含任意数量的 Python 表达式。他们必须以逗号符号分隔。列表中的每个项目可以是任何 Python 对象或有效的 Python 表达式。

#! /usr/bin/python3.11
a = "Hello World"
b = 100
c = 25.50
d = 5+6j
print ("Message: a)
print (b, c, b-c)
print(pow(100, 0.5), pow(c,2))

对 print() 的第一次调用显示了一个字符串文字和一个字符串变量。第二个打印两个变量的值和它们的减法。 pow() 函数计算一个数字的平方根和一个变量的平方。

Message Hello World
100 25.5 74.5
10.0 650.25

如果 print() 函数的括号中有多个用逗号分隔的对象,这些值将用一个空格 " " 分隔。要将任何其他字符用作分隔符,请为 print() 函数定义一个 sep 参数。该参数应跟随要打印的表达式列表。 在 print() 函数的以下输出中,变量用逗号分隔。

#! /usr/bin/python3.11
city="Hyderabad"
state="Telangana"
country="India"
print(city, state, country, sep=',')

sep=',' 的效果可以在结果中看到 −

Hyderabad,Telangana,India

print() 函数默认情况下在末尾发出一个换行符 ('\n')。因此,下一个 print() 语句的输出将出现在控制台的下一行。

city="Hyderabad"
state="Telangana"
print("City:", city)
print("State:", state)

两行显示为输出 −

City: Hyderabad
State: Telangana

要使这两行出现在同一行中,请在第一个 print() 函数中定义 end 参数并将其设置为一个空格字符串 " "。

city="Hyderabad"
state="Telangana"
country="India"
print("City:", city, end=" ")
print("State:", state)

两个 print() 函数的输出都将继续出现。

City: Hyderabad State: Telangana

= Python - 数字[id="_python_numbers"]== Python - 数字 在你的任何工作中,你经常处理数字。显然,任何计算机应用程序都涉及数字。因此,包括 Python 在内的编程语言都内置了支持存储和处理数字数据。 在本章中,我们将详细了解 Python 数字类型的属性。 三种数字类型整数 (int) 、浮点数 (float)complex 数已内置到 Python 解释器中。Python 还具有一个称为 bool 的内置布尔数据类型。它可以被视为 int 类型的子类型,因为它的两个可能值 True 和 False 分别代表整数 1 和 0。 = Python − 整数[id="_python_integers"]=== Python − 整数 在 Python 中,任何没有分数部分存储的数字都是整数。(请注意,如果数字中的分数部分为 0,并不意味着它是一个整数。例如,数字 10.0 不是一个整数,它是一个分数部分为 0 的浮点数,其数值为 10。)一个整数可以是零、正整数或负整数。例如,1234、0、-55。 形成整形对象有三种方式:使用文字表示、将任何表达式求值为整数,以及使用 int() 函数。 文字是用于直接在源代码中表示常量的符号。例如 −

>>> a =10

但是,请看以下对整数变量 c 的赋值。

a=10
b=20
c=a+b
print ("a:", a, "type:", type(a))

它将生成以下 output

a: 10 type: <class 'int'>

此处,c 确实是一个整数变量,但表达式 a + b 先被求值,并且其值被间接分配给 c。 形成整数对象的第三种方法是 int() 函数的返回值。它将浮点数或字符串转换为整数。

>>> a=int(10.5)
>>> b=int("100")

您可以用二进制、八进制或十六进制数字表示整数。然而,对象在内部以整数形式存储。 = 二进制数[id="_binary_numbers"]==== 二进制数 由仅二进制数字(1 和 0)组成的数字并带有 0b 前缀是二进制数。如果您将二进制数分配给变量,它仍然是 int 变量。 为以二进制形式表示整数,可直接将其以字面形式存储,或使用 int() 函数,其中基数设置为 2

a=0b101
print ("a:",a, "type:",type(a))
b=int("0b101011",2)
print ("b:",b, "type:",type(b))

它将生成以下 output

a: 5 type: <class 'int'>
b: 43 type: <class 'int'>

Python 中还有一个 bin() 函数。它返回整数对应的二进制字符串。

a=43
b=bin(a)
print ("Integer:",a, "Binary equivalent:",b)

它将生成以下 output

Integer: 43 Binary equivalent: 0b101011

= 八进制数[id="_octal_numbers"]==== 八进制数 八进制数仅由数字 0 到 7 组成。为了指定整数使用八进制表示法,需要使用 0o (小写 O)或 0O (大写 O)作为前缀。八进制数的文字表示如下 -

a=0O107
print (a, type(a))

它将生成以下 output

71 <class 'int'>

请注意对象在内部以整数形式存储。八进制数 107 的十进制等价数为 71。 由于八进制数系统有 8 个符号(0 至 7),因此其基数为 7。因此,在使用 int() 函数将八进制字符串转换为整数时,需将 base 参数设置为 8。

a=int('20',8)
print (a, type(a))

它将生成以下 output

16 <class 'int'>

八进制 30 的十进制等价数为 16。 在以下代码中,两个 int 对象从八进制记数法中获取,并对其进行加法。

a=0O56
print ("a:",a, "type:",type(a))
b=int("0O31",8)
print ("b:",b, "type:",type(b))
c=a+b
print ("addition:", c)

它将生成以下 output

a: 46 type: <class 'int'>
b: 25 type: <class 'int'>
addition: 71

为获取整数的八进制字符串,请使用 oct() 函数。

a=oct(71)
print (a, type(a))

= 十六进制数[id="_hexa_decimal_numbers"]==== 十六进制数 顾名思义,十六进制数系统中有 16 个符号。它们是 0-9 和 A 至 F。前 10 个数字与十进制数字相同。字母 A、B、C、D、E 和 F 分别等于 11、12、13、14、15 和 16。这些字母符号可以使用大写或小写。 要以十六进制表示法文字表示整数,请使用 0x0X 作为其前缀。

a=0XA2
print (a, type(a))

它将生成以下 output

162 <class 'int'>

要将十六进制字符串转换为整数,请在 int() 函数中将基数设置为 16。

a=int('0X1e', 16)
print (a, type(a))

试用以下代码段。它采用十六进制字符串,并返回整数。

num_string = "A1"
number = int(num_string, 16)
print ("Hexadecimal:", num_string, "Integer:",number)

它将生成以下 output

Hexadecimal: A1 Integer: 161

但是,如果字符串包含十六进制符号表中任何符号(例如 X001),则会引发以下错误 -

Traceback (most recent call last):
  File "C:\Python311\var1.py", line 4, in <module>
    number = int(num_string, 16)
ValueError: invalid literal for int() with base 16: 'X001'

Python 的标准库具有 hex() 函数,您可以使用它获取整数的十六进制等价数。

a=hex(161)
print (a, type(a))

它将生成以下 output

0xa1 <class 'str'>

整数可表示为二进制、八进制或十六进制,但它在内部仍是整数。因此,在执行算术操作时,表示形式不重要。

a=10 #decimal
b=0b10 #binary
c=0O10 #octal
d=0XA #Hexadecimal
e=a+b+c+d
print ("addition:", e)

它将生成以下 output

addition: 30

= Python - 浮点数[id="_python_floating_point_numbers"]=== Python - 浮点数 浮点数字具有整数部分和小数部分,由小数点符号(.)分隔。默认情况下,数字为正数,对负数加前缀减号(-)符号。 浮点数是 Python 的 float 类的对象。若要存储 float 对象,可以使用文字表示法、使用算术表达式的值或使用 float() 函数的返回值。 使用文字是最直接的方式。只需将带分数部分的数字分配给变量即可。以下每个语句都声明一个 float 对象。

>>> a=9.99
>>> b=0.999
>>> c=-9.99
>>> d=-0.999

在 Python 中,浮点数小数点后可以有多少位数没有限制。但是,为了缩短表示法,使用了 Ee 符号。E 表示以 10 为底的指数运算。例如,E4 是以 10 为底的 4 次方(或 10 的 4 次方),e-3 是以 10 为底的 -3 次方。 在科学记数法中,数字有一个系数部分和一个指数部分。系数应大于或等于 1 但小于 10 的浮点数。因此,1.23E+3、9.9E-5 和 1E10 是带有科学符号的浮点数的示例。

>>> a=1E10
>>> a
10000000000.0
>>> b=9.90E-5
>>> b
9.9e-05
>>> 1.23E3
1230.0

形成 float 对象的第二种方法是间接的,使用表达式的结果。此处,将两个浮点数的商分配给一个变量,该变量引用 float 对象。

a=10.33
b=2.66
c=a/b
print ("c:", c, "type", type(c))

它将生成以下 output

c: 3.8834586466165413 type <class 'float'>

Python 的 float() 函数返回一个 float 对象,如果它有适当的内容,则解析一个数字或一个字符串。如果括号中没有给定参数,则返回 0.0,对于一个 int 参数,添加分数部分 0。

>>> a=float()
>>> a
0.0
>>> a=float(10)
>>> a
10.0

即使以二进制、八进制或十六进制表示整数,float() 函数也会返回分数部分为 0 的浮点数。

a=float(0b10)
b=float(0O10)
c=float(0xA)
print (a,b,c, sep=",")

它将生成以下 output

2.0,8.0,10.0

float() 函数从字符串中获取浮点数,而字符串包含一个浮点数,其采用标准小数点格式或者采用科学计数法。

a=float("-123.54")
b=float("1.23E04")
print ("a=",a,"b=",b)

它将生成以下 output

a= -123.54 b= 12300.0

在数学中,无穷大是一个抽象概念。从物理上讲,无限大的数字永远无法存储在任何数量的内存中。但是,对于大多数计算机硬件配置,一个以 10 为底的 400 次方的非常大的数由 Inf 表示。如果将“无穷大”用作 float() 函数的参数,它将返回 Inf。

a=1.00E400
print (a, type(a))
a=float("Infinity")
print (a, type(a))

它将生成以下 output

inf <class 'float'>
inf <class 'float'>

另一种这样的实体是 Nan(代表非数字)。它表示任何未定义或不可表示的值。

>>> a=float('Nan')
>>> a
Nan

= Python - 复数[id="_python_complex_numbers"]=== Python - 复数 在本节中,我们将详细了解 Python 中的复杂数据类型。复数在数学方程式中以及电磁学、电子学、光学和量子论中的定律中得到了应用。傅里叶变换使用复数。它们用于波函数计算、滤波器设计、数字电子产品中的信号完整性、射电天文学等。 复数由实部和虚部组成,用“+”或“-”分隔。实部可以是任何浮点数(或本身是一个复数)。虚部也是一个浮点数/复数,但乘以一个虚数。 在数学中,虚数“i”定义为 -1 的平方根 ($\sqrt{−1}$)。因此,复数表示为“x+yi”,其中 x 是实部,“y”是虚部的系数。 为了避免与电学理论中电流的使用相混淆,通常使用符号“j”代替“I”表示虚数。Python 还使用“j”作为虚数。因此,“x+yj”是 Python 中复数的表示形式。 就像 int 或 float 数据类型一样,可以使用文字表示法或使用 complex() 函数来形成一个复杂的对象。以下所有语句都形成一个复杂的对象。

>>> a=5+6j
>>> a
(5+6j)
>>> type(a)
<class 'complex'>
>>> a=2.25-1.2J
>>> a
(2.25-1.2j)
>>> type(a)
<class 'complex'>
>>> a=1.01E-2+2.2e3j
>>> a
(0.0101+2200j)
>>> type(a)
<class 'complex'>

请注意,实部和虚部的系数必须是浮点数,并且可以用标准小数点符号或科学符号表示。 Python 的 complex() 函数有助于形成复杂类型的对象。该函数接收实部和虚部的参数,并返回复数。 complex() 函数有两个版本,一个有两个参数,一个有一个参数。使用带有两个参数的 complex() 很简单。它使用第一个参数作为实部,使用第二个参数作为虚部的系数。

a=complex(5.3,6)
b=complex(1.01E-2, 2.2E3)
print ("a:", a, "type:", type(a))
print ("b:", b, "type:", type(b))

它将生成以下 output

a: (5.3+6j) type: <class 'complex'>
b: (0.0101+2200j) type: <class 'complex'>

在上面的示例中,我们使用了 x 和 y 作为浮点参数。它们甚至可以是 complex 数据类型。

a=complex(1+2j, 2-3j)
print (a, type(a))

它将生成以下 output

(4+4j) <class 'complex'>

对上述示例感到惊讶?将“x”设为 1+2j,“y”设为 2-3j。尝试手动计算“x+yj”,您就会明白了。

complex(1+2j, 2-3j)
=(1+2j)+(2-3j)*j
=1+2j +2j+3
=4+4j

如果您仅对 complex() 函数使用一个数字参数,它会将其视为实部的值;虚部设为 0。

a=complex(5.3)
print ("a:", a, "type:", type(a))

它将生成以下 output

a: (5.3+0j) type: <class 'complex'>

如果 complex() 函数的唯一参数是一个具有复数表示的字符串,那么它还可以将字符串分析为复数。 在下面的代码段中,系统会要求用户输入一个复数。它用作参数。由于 Python 会将输入读为字符串,因此该函数会从中提取复数对象。

a= "5.5+2.3j"
b=complex(a)
print ("Complex number:", b)

它将生成以下 output

Complex number: (5.5+2.3j)

Python 的内置 complex 类具有两个属性 realimag - 它们返回来自该对象的实部和虚部系数。

a=5+6j
print ("Real part:", a.real, "Coefficient of Imaginary part:", a.imag)

它将生成以下 output

Real part: 5.0 Coefficient of Imaginary part: 6.0

complex 类还定义了一个 conjugate() 方法。它返回另一个虚部分量的符号相反的复数。例如,x+yj 的共轭是 x-yj。

>>> a=5-2.2j
>>> a.conjugate()
(5+2.2j)

= Python - 布尔[id="_python_booleans"]== Python - 布尔 在 Python 中, bool 是 int 类型的子类型。bool 对象有两个可能的值,并且它使用 Python 关键字 True 和 False 初始化。

>>> a=True
>>> b=False
>>> type(a), type(b)
(<class 'bool'>, <class 'bool'>)

bool 对象可接受为类型转换函数的参数。使用 True 作为参数,int() 函数返回 1,float() 返回 1.0;而对于 False,它们分别返回 0 和 0.0。我们有一个参数版本的 complex() 函数。 如果参数是复杂的,则将其作为实部,将其虚部系数设置为 0。

a=int(True)
print ("bool to int:", a)
a=float(False)
print ("bool to float:", a)
a=complex(True)
print ("bool to complex:", a)

运行此代码后,你将得到以下 output

bool to int: 1
bool to float: 0.0
bool to complex: (1+0j)

= Python - 控制流[id="_python_control_flow"]== Python - 控制流 默认情况下,计算机程序中的指令以从上到下或从头到尾的顺序方式执行。然而,此类顺序执行程序只能执行简单的任务。我们希望程序具有决策能力,以便根据不同的条件执行不同的步骤。 大多数编程语言,包括 Python,都提供控制指令执行流的功能。通常,有两种类型的控制流语句。 Decision-making −该程序能够决定取决于一个特定的布尔表达式的值,执行哪组替代指令。 下图说明了决策语句的工作方式: image::https://www.iokays.com/tutorialspoint/python/_images/decision_making_statements.jpg[] Looping or Iteration −大部分进程需要重复执行一组指令。在编程术语中,它被称为 loop 。如果流重定向到任一之前的步骤,而不是下一步,那么它构成了一个循环。 下面的图表说明了循环是如何工作的: image::https://www.iokays.com/tutorialspoint/python/_images/looping_works.jpg[] 如果控制无条件地返回,它就会形成一个无限循环,这是不希望的,因为剩余的代码永远无法得到执行。 在条件循环中,块语句的重复迭代持续到满足某个条件为止。 = Python - 决策制定[id="_python_decision_making"]==Python - 决策制定 Python 的决策制定功能在其关键字中——if、else 和 elif。if 关键字需要一个布尔表达式,后面跟冒号符号。 冒号 (:) 符号开始一个缩进的代码块。如果 if 语句中的布尔表达式为 True,则具有同一缩进级别的语句将被执行。如果表达式不为 True (False),解释器将绕过缩进的代码块,继续执行更早期缩进级别的语句。 = Python − if 语句[id="_python_the_if_statement"]===Python − if 语句 以下流程图说明了 Python if statement 的工作原理− image::https://www.iokays.com/tutorialspoint/python/_images/if_statement_works.jpg[] = 语法[id="_syntax"]====语法 以上流程图中的逻辑由以下语法表示−

if expr==True:
   stmt1
   stmt2
   stmt3
   ..
   ..
Stmt4

if 语句类似于其他语言的语句。 if 语句包含一个布尔表达式,用于比较数据,并根据比较结果做出决策。 如果布尔表达式求值为 True,则 if 语句内语句块将被执行。在 Python 中,代码块中的语句在冒号符号后统一缩进。如果布尔表达式求值为 False,则将执行代码块结束后的第一组代码。 = 示例[id="_example"]====示例 我们考虑一个客户有权获得 10% 折扣的示例,如果他的购买金额 >1000;否则,不适用折扣。此流程图显示了该过程。 image::https://www.iokays.com/tutorialspoint/python/_images/if_flowchart.jpg[] 在 Python 中,我们首先将 discount 变量设置为 0,并接受用户的输入作为金额。 然后是条件语句 if amt>1000。放置开头条件代码块的 : 符号,其中计算可适用的折扣。显然,无论是否折扣,默认情况下下一语句打印金额-折扣。如果适用,它将被减去,如果不是,则它为 0。

discount = 0
amount = 1200
if amount > 1000:
   discount = amount * 10 / 100
print("amount = ",amount - discount)

此处金额为 1200,因此扣除 120 的折扣。执行此代码后,你会得到以下 output

amount = 1080.0

将变量数量更改为 800,并再次运行代码。此时,没有任何折扣适用。你将获得以下输出 −

amount = 800

= Python - if-else 语句[id="_python_the_if_else_statement"]==Python - if-else 语句 与 if 语句一起,还可以选择使用 else 关键字。如果布尔表达式(在 if 语句中)不为 true,它提供了要执行的备用语句块。此流程图显示了如何使用 else 块。 image::https://www.iokays.com/tutorialspoint/python/_images/ifelse_syntax.jpg[] 如果 expr 为 True,则执行 stmt1、2、3 的代码块,然后默认流继续执行 stmt7。但是,如果 If expr 为 False,则运行代码块 stmt4、5、6,然后默认流继续。 = 语法[id="_syntax"]====语法 以下流程图的 Python 实现如下:

if expr==True:
   stmt1
   stmt2
   stmt3
else:
   stmt4
   stmt5
   stmt6
Stmt7

= 示例[id="_example"]====示例 让我们使用以下示例了解 else 子句的用法。变量 age 可以采用不同的值。如果表达式“age > 18”为真,则会显示 you are eligible to vote 消息,否则会显示 not eligible 消息。以下流程图说明了此逻辑。 image::https://www.iokays.com/tutorialspoint/python/_images/ifelse.jpg[] 其 Python 实现很简单。

age=25
print ("age: ", age)
if age>=18:
   print ("eligible to vote")
else:
   print ("not eligible to vote")

首先,将整型变量“age”设置为 25。 然后使用 if 语句,后面紧跟“age>18”表达式和冒号“:”,这将启动一个代码块;如果“age>=18”为真,则此代码块将生效。 要提供 else 块,请使用“else:”之后包含消息 not eligible 的缩进代码块将在“age>=18”为假时生效。 执行此代码后,你将获得以下 ouput

age: 25
eligible to vote

要测试 else 块,将 age 更改为 12,然后再次运行代码。

age: 12
not eligible to vote

= Python - elif 语句[id="_python_elif_statement"]=== Python - elif 语句 elif 语句允许你检查多个真值表达式,并在其中一个条件求值为真时执行一段代码块。 与 else 语句类似, elif 语句是可选的。然而,与 else 不同,后者最多只能有一个语句;在 if 之后可以有任意数量的 elif 语句。 = 语法[id="_syntax"]====语法

if expression1:
   statement(s)
elif expression2:
   statement(s)
elif expression3:
   statement(s)
else:
   statement(s)

= 示例[id="_example"]====示例 让我们借助以下示例了解 elif 的工作原理。 先前示例中使用的折扣结构已修改为不同的折扣等级:

  1. 超过 10000 的金额可享受 20% 折扣,

  2. 5-10000 之间的金额可享受 10% 折扣,

  3. 1 至 5000 之间的金额可享受 5% 折扣。

  4. no discount if amount<1000

以下流程图说明了这些条件: image::https://www.iokays.com/tutorialspoint/python/_images/ifelif.jpg[] = 示例[id="_example"]====示例 我们可以使用 if-else 语句为上述逻辑编写 Python 代码:

amount = int(input('Enter amount: '))
if amount > 10000:
   discount = amount * 20 / 100
else:
   if amount > 5000:
      discount = amount * 10 / 100
   else:
      if amount > 1000:
         discount = amount * 5 / 100
      else:
         dicount = 0
print('amount: ',amount - discount)

虽然此代码将完美运行,但是,如果你查看每个 if 和 else 语句的缩进级别,如果你还有更多条件,则管理起来将变得困难。 elif 语句使代码易于阅读和理解。 Elif 是“else if”的简称。它允许在第一个 if 语句之后将逻辑排列在 elif 语句的级联中。如果第一个 if 语句计算结果为 false,则依次计算后续 elif 语句,并且如果其中任何一个满足条件,则退出级联。 级联中的最后一个块是 else 块,当所有前面的 if/elif 条件均不满足时,该块会进入画面。

amount = 800
print('amount = ',amount)
if amount > 10000:
   discount = amount * 20 / 100
elif amount > 5000:
   discount = amount * 10 / 100
elif amount > 1000:
   discount = amount * 5 / 100
else:
   discount=0

print('payable amount = ',amount - discount)

设置 amount 以测试所有可能条件:800、2500、7500 和 15000。 outputs 将相应地变化 −

amount: 800
payable amount = 800
amount: 2500
payable amount = 2375.0
amount: 7500
payable amount = 6750.0
amount: 15000
payable amount = 12000.0

= 嵌套的 If 语句[id="_nested_if_statements"]=== 嵌套的 If 语句 在某个条件计算结果为 true 之后,可能出现要检查另一个条件的情况。在这种情况中,可以使用嵌套 if 结构。 在嵌套 if 结构中,可以在另一个 if…​elif…​else 结构中使用 if…​elif…​else 结构。 = 语法[id="_syntax"]====语法 嵌套 if…​elif…​else 结构的语法如下 −

if expression1:
   statement(s)
   if expression2:
      statement(s)
   elif expression3:
      statement(s)3
   else
      statement(s)
elif expression4:
   statement(s)
else:
   statement(s)

= 示例[id="_example"]====示例 现在让我们来看一个 Python 代码来了解它的工作原理 −

# !/usr/bin/python3
num=8
print ("num = ",num)
if num%2==0:
   if num%3==0:
      print ("Divisible by 3 and 2")
   else:
      print ("divisible by 2 not divisible by 3")
else:
   if num%3==0:
      print ("divisible by 3 not divisible by 2")
   else:
      print ("not Divisible by 2 not divisible by 3")

当执行以上代码时,它会产生以下 output -

num = 8
divisible by 2 not divisible by 3
num = 15
divisible by 3 not divisible by 2
num = 12
Divisible by 3 and 2
num = 5
not Divisible by 2 not divisible by 3

= Python - MatchCase 语句[id="_python_matchcase_statement"]== Python - MatchCase 语句 在 3.10 版本之前,Python 缺少类似于 C 或 C 中 switch-case 的特性。在 Python 3.10 中,引入了称为 match-case 的模式匹配技术,类似于“switch case”结构。 *match* 语句采用一个表达式并将其值与作为一或多个 case 块给出的连续模式进行比较。与 C 或 C 中的 switch 语句相比,用法更类似于 Rust 或 Haskell 等语言中的模式匹配。仅匹配到的第一个模式得到执行。还可以将值中的组件(序列元素或对象属性)提取到变量中。 = 语法[id="_syntax"]====语法 match-case 的基本用法是将变量与一个或多个值进行比较。

match variable_name:
   case 'pattern 1' : statement 1
   case 'pattern 2' : statement 2
   ...
   case 'pattern n' : statement n

= 示例[id="_example"]====示例 以下代码有一个名为 weekday() 的函数。它接收一个整数参数,将其与所有可能的星期几数字值进行匹配,并返回相应的星期名称。

def weekday(n):
   match n:
      case 0: return "Monday"
      case 1: return "Tuesday"
      case 2: return "Wednesday"
      case 3: return "Thursday"
      case 4: return "Friday"
      case 5: return "Saturday"
      case 6: return "Sunday"
      case _: return "Invalid day number"
print (weekday(3))
print (weekday(6))
print (weekday(7))

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

Thursday
Sunday
Invalid day number

该函数中的最后一个 case 语句以“_”作为要比较的值。它充当通配符 case,如果所有其他 case 都不成立,它将执行。 = 组合 Case[id="_combined_cases"]==== 组合 Case 有时,对于多个 case,可能需要执行类似的操作。为此,可以使用符号“|”表示的 OR 运算符组合 case。 = 示例[id="_example"]====示例

def access(user):
   match user:
      case "admin" | "manager": return "Full access"
      case "Guest": return "Limited access"
      case _: return "No access"
print (access("manager"))
print (access("Guest"))
print (access("Ravi"))

= 输出[id="_output"]==== 输出 上面的代码定义了一个名为 access() 的函数,它有一个 string 参数,代表用户的名字。对于 admin 或 manager 用户,系统会授予完全访问权限;对于 Guest,访问权限受限;对于其他人,没有访问权限。

Full access
Limited access
No access

= 列表作为参数[id="_list_as_the_argument"]==== 列表作为参数 由于 Python 可以将表达式与任何文字匹配,因此你可以将列表用作 case 值。此外,对于列表中数量不定的项,可以使用 "*" 运算符将它们解析为一个序列。 = 示例[id="_example"]====示例

def greeting(details):
   match details:
      case [time, name]:
         return f'Good {time} {name}!'
      case [time, *names]:
         msg=''
         for name in names:
            msg+=f'Good {time} {name}!\n'
         return msg

print (greeting(["Morning", "Ravi"]))
print (greeting(["Afternoon","Guest"]))
print (greeting(["Evening", "Kajal", "Praveen", "Lata"]))

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

Good Morning Ravi!
Good Afternoon Guest!
Good Evening Kajal!
Good Evening Praveen!
Good Evening Lata!

= 在 "Case" 子句中使用 "if"[id="_using_if_in_case_clause"]=== 在 "Case" 子句中使用 "if" 通常,Python 会将表达式与文字 case 匹配。不过,它允许你在 case 子句中加入 if 语句,对匹配变量进行条件计算。 在以下示例中,函数参数是 amount 和 duration 的一个列表,而 intereset 要根据金额小于或大于 10000 来计算。条件包含在 case 子句中。 = 示例[id="_example"]====示例

def intr(details):
   match details:
      case [amt, duration] if amt<10000:
         return amt*10*duration/100
      case [amt, duration] if amt>=10000:
         return amt*15*duration/100
print ("Interest = ", intr([5000,5]))
print ("Interest = ", intr([15000,3]))

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

Interest = 2500.0
Interest = 6750.0

= Python - for 循环[id="_python_the_for_loop"]== Python - for 循环 Python 中的 for 循环有能力迭代任何序列中的项,比如列表或字符串。 = 语法[id="_syntax"]====语法

for iterating_var in sequence:
   statements(s)

如果序列包含一个表达式列表,则首先对该列表求值。然后,序列中的第一个项(在第 0 个索引处)被赋值给迭代变量 iterating_var。 接下来,执行语句块。列表中的每一项都被赋值给 iterating_var,并且语句块一直执行到整个序列用尽为止。 以下流程图说明了 for 循环的工作原理 − image::https://www.iokays.com/tutorialspoint/python/_images/forloop.jpg[] 由于循环针对序列中的每个成员元素执行,因此不需要显式验证控制循环的布尔表达式(如 while 循环中)。 列表、元组或字符串等序列对象被称为 iterables ,因为 for 循环会迭代整个集合。 for 循环可以迭代任何迭代器对象。 字典的 items()、keys() 和 values() 方法返回的视图对象也是可迭代的,因此我们可以对它们运行 for 循环。 Python 内置的 range() 函数返回一个迭代器对象,该对象流式传输一个数字序列。我们可以对范围运行 for 循环。 = 对字符串使用 "for"[id="_using_for_with_a_string"]=== 对字符串使用 "for" 字符串是一个 Unicode 字母序列,每个字母都有一个位置索引。以下示例比较每个字符并显示它是否不是元音('a'、'e'、'I'、'o' 或 'u') = 示例[id="_example"]====示例

zen = '''
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
'''
for char in zen:
   if char not in 'aeiou':
      print (char, end='')

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

Btfl s bttr thn gly.
Explct s bttr thn mplct.
Smpl s bttr thn cmplx.
Cmplx s bttr thn cmplctd.

= 对元组使用 "for"[id="_using_for_with_a_tuple"]=== 对元组使用 "for" Python 的元组对象也是一个索引序列,因此我们可以使用 for 循环遍历它的项。 = 示例[id="_example"]====示例 在以下示例中, for 循环遍历包含整数的元组,并返回所有数字的总和。

numbers = (34,54,67,21,78,97,45,44,80,19)
total = 0
for num in numbers:
   total+=num
print ("Total =", total)

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

Total = 539

= 使用“for”和列表[id="_using_for_with_a_list"]==== 使用“for”和列表 Python 的列表对象也是一个索引序列,因此我们可以使用 for 循环遍历其项。 = 示例[id="_example"]====示例 在以下示例中,for 循环遍历包含整数的列表,并且仅打印可被 2 整除的那些整数。

numbers = [34,54,67,21,78,97,45,44,80,19]
total = 0
for num in numbers:
   if num%2 == 0:
      print (num)

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

34
54
78
44
80

= 使用“for”和范围对象[id="_using_for_with_a_range_object"]==== 使用“for”和范围对象 Python 的内置 range() 函数返回一个范围对象。Python 的范围对象是一个迭代器,它在每次迭代时生成一个整数。该对象包含从开始到结束的整数,由步长参数分隔。 = 语法[id="_syntax"]====语法 range() 函数具有以下语法 −

range(start, stop, step)

= 参数[id="_parameters"]==== 参数

  1. Start − 范围的起始值。可选项。默认为 0

  2. Stop − 范围达到 stop-1

  3. Step − 范围中的整数以步长值递增。选项,默认为 1。

= 返回值[id="_return_value"]==== 返回值 range() 函数返回一个范围对象。它可以解析为列表序列。 = 示例[id="_example"]====示例

numbers = range(5)
'''
start is 0 by default,
step is 1 by default,
range generated from 0 to 4
'''
print (list(numbers))
# step is 1 by default, range generated from 10 to 19
numbers = range(10,20)
print (list(numbers))
# range generated from 1 to 10 increment by step of 2
numbers = range(1, 10, 2)
print (list(numbers))

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

[0, 1, 2, 3, 4]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[1, 3, 5, 7, 9]

= 示例[id="_example"]====示例 一旦我们得到范围,我们就可以使用 for 循环。

for num in range(5):
 print (num, end=' ')
print()
for num in range(10,20):
 print (num, end=' ')
print()
for num in range(1, 10, 2):
 print (num, end=' ')

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

0 1 2 3 4
10 11 12 13 14 15 16 17 18 19
1 3 5 7 9

= 示例:数字的阶乘[id="_example_factorial_of_a_number"]==== 示例:数字的阶乘 阶乘是 1 到该数字(例如 n)的所有数字的乘积。它也可以定义为 1、2 到 n 的乘积。

Factorial of a number n! = 1 * 2 * . . . . . * n

我们使用 range() 函数来获取从 1 到 n-1 的数字序列并执行累积乘法以获得阶乘值。

fact=1
N = 5
for x in range(1, N+1):
   fact=fact*x
print ("factorial of {} is {}".format(N, fact))

= 输出[id="_output"]==== 输出 执行此代码后,会生成以下输出 −

factorial of 5 is 120

在上述程序中,更改 N 的值以获取不同数字的阶乘值。

Using "for" Loop with Sequence Index

为了遍历序列,我们可以使用 range() 函数获取索引列表

Indices = range(len(sequence))

然后,我们可以像下面这样形成一个 for

numbers = [34,54,67,21,78]
indices = range(len(numbers))
for index in indices:
   print ("index:",index, "number:",numbers[index])

执行后,此代码将会产生以下 output

index: 0 number: 34
index: 1 number: 54
index: 2 number: 67
index: 3 number: 21
index: 4 number: 78

Using "for" with Dictionaries

与列表、元祖或字符串不同,Python 中的字典数据类型不是序列,因为项目没有索引值。但是,仍然可以使用不同的技术遍历字典。

对字典对象运行一个简单的 for 可以遍历其中使用的键。

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x in numbers:
   print (x)

执行后,此代码将会产生以下 output

10
20
30
40

一旦我们能够拿到键,就可以使用方括号运算符或 get() 方法轻松访问其关联的值。看看下面的例子——

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x in numbers:
   print (x,":",numbers[x])

它将生成以下 output

10 : Ten
20 : Twenty
30 : Thirty
40 : Forty

dict 类的 items()、keys() 和 values() 方法分别返回视图对象 dict_items、dict_keys 和 dict_values。这些对象是迭代器,因此我们可以使用 for 循环来遍历它们。

dict_items 对象是一个可以像下面这样遍历键值元组的列表——

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x in numbers.items():
   print (x)

它将生成以下 output

(10, 'Ten')
(20, 'Twenty')
(30, 'Thirty')
(40, 'Forty')

这里,“x”是从 dict_items 迭代器中提取的元组元素。我们可以将这个元组进一步解压成两个不同的变量。查看以下代码——

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x,y in numbers.items():
   print (x,":", y)

它将生成以下 output

10 : Ten
20 : Twenty
30 : Thirty
40 : Forty

类似地,dict_keys 对象中的键集合可以被迭代。看看下面的例子——

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x in numbers.keys():
   print (x, ":", numbers[x])

它将产生相同的 output ——

10 : Ten
20 : Twenty
30 : Thirty
40 : Forty

Python - The forelse Loop

Python 支持在“for”循环语句中包含一个“else”语句。如果“else”语句与“for”循环一起使用,“else”语句将在控制转移到执行的主线之前,在序列用尽时执行。

下面的流程图说明了如何 else 语句与 for 循环一起使用——

forelse

Example

下面的例子说明了 else 语句和 for 语句的组合。直到 count 小于 5,都会打印迭代的次数。当 count 变为 5 时,将在控制权移交给主程序中的下一个语句前执行 else 块中的 print 语句。

for count in range(6):
   print ("Iteration no. {}".format(count))
else:
   print ("for loop over. Now in else block")
print ("End of for loop")

执行后,此代码将会产生以下 output

Iteration no. 1
Iteration no. 2
Iteration no. 3
Iteration no. 4
Iteration no. 5
for loop over. Now in else block
End of for loop

Nested Loops

Python 编程语言允许在一个循环内使用另一个循环。以下部分示范了一些示例来说明这个概念。

Syntax

for iterating_var in sequence:
   for iterating_var in sequence:
      statements(s)
      statements(s)

Python 编程语言中嵌套的 while 循环语句的语法如下所示——

while expression:
   while expression:
      statement(s)
   statement(s)

关于循环嵌套的最后一点是,您可以将任何类型的循环放到另一种类型的循环中。例如,for 循环可以位于 while 循环中,反之亦然。

Example

下面的程序使用嵌套 for 循环来显示 1-10 的乘法表。

#!/usr/bin/python3
for i in range(1,11):
   for j in range(1,11):
      k=i*j
      print ("{:3d}".format(k), end=' ')
   print()

内部循环中的 print() 函数有 end=' ',它会附加一个空格,而不是默认的新行。因此,数字将出现在一行中。

最后一个 print() 将在 for 循环的末尾执行。

当执行以上代码时,它会产生以下 output -

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
  9  18  27  36  45  54  63  72  81  90
 10  20  30  40  50  60  70  80  90 100

Python - The while Loop

通常,计算机程序中步骤的执行流从头到尾。但是,如果执行流被重定向到任何早期的步骤,而不是执行下一步,那就构成了一个循环。

在 Python 编程语言中, while 循环语句在给定的布尔表达式为真时,会重复执行目标语句。

Syntax

在 Python 编程语言中, while 循环的语法为 -

while expression:
   statement(s)

while 关键字后跟一个布尔表达式,然后是冒号符号,以启动缩进语句块。此处,语句可以是单个语句,也可以是具有统一缩进的语句块。该条件可以是任何表达式,而真为任何非零值。当布尔表达式为真时,循环会迭代。

只要表达式变为假,程序控制权就会传递到紧跟在循环后面的那行。

如果它未能变为假,循环就会继续运行,且除非强制停止,否则就不会停止。这样的循环被称为无限循环,这是计算机程序中不需要的。

以下流程图展示了 while 循环 -

while

Example 1

在 Python 中,编程构造之后缩进相同数量字符空间的所有语句都会被视为单个代码块的一部分。Python 使用缩进来作为其语句分组方法。

count=0
while count<5:
   count+=1
   print ("Iteration no. {}".format(count))

print ("End of while loop")

我们将计数变量初始化为 0,且循环运行到“count<5”。在每次迭代中,都会对计数进行递增和检查。如果不为 5,就会进行下一次重复。在循环块的里面,会打印计数的瞬时值。当 while 条件变为假时,循环会终止,且会执行下一个语句,此处为 while 循环消息的末尾。

Output

执行此代码后,会生成以下输出 −

Iteration no. 1
Iteration no. 2
Iteration no. 3
Iteration no. 4
Iteration no. 5
End of while loop

Example 2

下面是使用 while 循环的另一个示例。对于每次迭代,该程序都会要求用户输入,且会不断重复,直到用户输入非数字字符串。isnumeric() 函数会返回真(如果输入为整数)或假(如果输入为其他)。

var='0'
while var.isnumeric()==True:
   var=input('enter a number..')
   if var.isnumeric()==True:
      print ("Your input", var)
print ("End of while loop")

Output

执行此代码后,会生成以下输出 −

enter a number..10
Your input 10
enter a number..100
Your input 100
enter a number..543
Your input 543
enter a number..qwer
End of while loop

The Infinite Loop

如果条件从不变为假,那么循环就会变成无限循环。使用 while 循环时,您必须小心,因为存在该条件从不解析为假值的可能性。这会导致循环从不结束。这样的循环被称为无限循环。

在客户端/服务器编程中,无限循环可能是非常有用的,其中服务器需要持续运行,以便客户端程序可以视需要与之通信。

Example 3

我们举个示例来了解无限循环在 Python 中的工作原理 -

#!/usr/bin/python3
var = 1
while var == 1 : # This constructs an infinite loop
   num = int(input("Enter a number :"))
   print ("You entered: ", num)
print ("Good bye!")

Output

执行此代码后,会生成以下输出 −

Enter a number :20
You entered: 20
Enter a number :29
You entered: 29
Enter a number :3
You entered: 3
Enter a number :11
You entered: 11
Enter a number :22
You entered: 22
Enter a number :Traceback (most recent call last):
   File "examples\test.py", line 5, in
      num = int(input("Enter a number :"))
KeyboardInterrupt

上面的示例进入无限循环,且您需要使用 Ctrl+C 来退出程序。

The while-else Loop

Python 支持将 else 语句与 while 循环语句相关联。

如果将 else 语句与 while 循环一起使用,那么当控制权转移到执行主行之前,条件变为假时,就会执行 else 语句。

以下流程图展示了如何将 elsewhile 语句结合使用 -

whileelse

Example

以下示例展示了 else 语句与 while 语句的组合。在 count 小于 5 时,会打印迭代计数。当其变为 5 时,会在 else 块中执行 print 语句,然后才会将控制权传递到主程序中的下一条语句。

count=0
while count<5:
   count+=1
   print ("Iteration no. {}".format(count))
else:
   print ("While loop over. Now in else block")
print ("End of while loop")

Output

执行后,此代码将会产生以下 output

Iteration no. 1
Iteration no. 2
Iteration no. 3
Iteration no. 4
Iteration no. 5
While loop over. Now in else block
End of while loop

Python - The break Statement

Loop Control Statements

循环控制语句会将其执行从其正常顺序更改。当执行离开范围时,该范围内创建的所有自动对象都将被销毁。

Python 支持以下控制语句 -

让我们简要地了解循环控制语句。

Python − The break Statement

break 语句用于过早终止当前循环。放弃循环后,与 C 中传统 break 语句一样,从下一条语句处恢复执行。

break 最常用于当触发某些外部条件时需要从循环中快速退出。 break 语句可在 while 和 for 循环中使用。

如果使用嵌套循环,break 语句将停止执行最内层循环并开始执行该代码块后的下一行代码。

Syntax

Python 中 break 语句的语法如下 −

break

Flow Diagram

其流程图如下所示 −

loop break

Example 1

现在,让我们举个例子来了解 "break" 语句如何在 Python 中工作 −

#!/usr/bin/python3
print ('First example')
for letter in 'Python': # First Example
   if letter == 'h':
      break
   print ('Current Letter :', letter)
print ('Second example')
var = 10 # Second Example
while var > 0:
   print ('Current variable value :', var)
   var = var -1
   if var == 5:
      break
print ("Good bye!")

当执行以上代码时,它会产生以下 output -

First example
Current Letter : P
Current Letter : y
Current Letter : t
Second example
Current variable value : 10
Current variable value : 9
Current variable value : 8
Current variable value : 7
Current variable value : 6
Good bye!

Example 2

以下程序演示在 for 循环中使用 break,该循环对列表进行迭代。用户输入一个数字,在列表中搜索该数字。如果找到,则循环以“已找到”消息终止。

#!/usr/bin/python3
no=int(input('any number: '))
numbers=[11,33,55,39,55,75,37,21,23,41,13]
for num in numbers:
   if num==no:
      print ('number found in list')
      break
else:
   print ('number not found in list')

以上程序将产生以下 output

any number: 33
number found in list
any number: 5
number not found in list

Example 3: Checking for Prime Number

请注意,当遇到 break 语句时,Python 会放弃循环中的其余语句,包括 else 块。

以下示例利用此行为来判断一个数字是否是质数。根据定义,一个数字是质数,如果它不能被除 1 和自身以外的任何其他数字整除。

以下代码对从 2 到所需数字 -1 的数字运行 for 循环。如果它可以被循环变量的任何值整除,那么该数字就不是质数,因此程序会从循环中 break。如果数字不能被 2 到 x-1 之间的任何数字整除,else 块会打印消息,指出给定的数字是质数。

num = 37
print ("Number: ", num)
for x in range(2,num):
   if num%x==0:
      print ("{} is not prime".format(num))
      break
else:
   print ("{} is prime".format(num))

Output

为 num 分配不同的值以检查它是否是质数。

Number: 37
37 is prime
Number: 49
49 is not prime

Python - The Continue Statement

Python 中的 continue 语句将控制权返回给当前循环的开头。遇到该语句时,循环会启动下一次迭代,而不会执行当前迭代中的其余语句。

continue 语句可在 whilefor 循环中使用。

Syntax

continue

Flow Diagram

continue 语句的流程图如下所示 −

loop continue

continue 语句恰恰相反 break 。它会跳过当前循环中的其余语句并启动下一次迭代。

Example 1

现在,让我们举个例子来了解 continue 语句如何在 Python 中工作 −

for letter in 'Python': # First Example
   if letter == 'h':
      continue
   print ('Current Letter :', letter)
var = 10 # Second Example
while var > 0:
   var = var -1
   if var == 5:
      continue
   print ('Current variable value :', var)
print ("Good bye!")

当执行以上代码时,它会产生以下 output -

Current Letter : P
Current Letter : y
Current Letter : t
Current Letter : o
Current Letter : n
Current variable value : 9
Current variable value : 8
Current variable value : 7
Current variable value : 6
Current variable value : 4
Current variable value : 3
Current variable value : 2
Current variable value : 1
Current variable value : 0
Good bye!

Example 2: Checking Prime Factors

以下代码使用 continue 来查找给定数字的质因子。要找到质因子,我们需要从 2 开始连续除以给定数字,增加除数,并继续相同过程,直到输入减少到 1。

找到质因数的算法如下 -

  1. 从用户处接受输入 (n)

  2. 将除数 (d) 设定为 2

  3. Perform following till n>1

  4. 检查给定的数字 (n) 能否被除数 (d) 整除。

  5. If n%d==0[style="loweralpha"]

    1. 将 d 打印为一个因子将 n 的新值设定为 n/d从 4 重复

  6. If not

  7. Increment d by 1

  8. Repeat from 3

给定一个 Python 代码以便实现以下目的 -

num = 60
print ("Prime factors for: ", num)
d=2
while num>1:
   if num%d==0:
      print (d)
      num=num/d
      continue
   d=d+1

执行后,此代码将会产生以下 output

Prime factors for: 60
2
2
3
5

在上述程序中将不同的值(例如 75)分配给 num 并测试其质因数的结果。

Prime factors for: 75
3
5
5

Python - The pass Statement

当语法上需要一个语句但你不想执行任何指令或代码时,将使用 pass 语句。

pass 语句是一个空操作;执行时不会发生任何事。 pass 语句在代码最终会执行的位置也有用,但尚未编写(即在存根中)。

Syntax

pass

Example

以下代码展示了如何在 Python 中使用 pass 语句 -

for letter in 'Python':
   if letter == 'h':
      pass
      print ('This is pass block')
   print ('Current Letter :', letter)
print ("Good bye!")

当执行以上代码时,它会产生以下 output -

Current Letter : P
Current Letter : y
Current Letter : t
This is pass block
Current Letter : h
Current Letter : o
Current Letter : n
Good bye!

Python - Functions

函数是一个组织良好的、可重复使用的代码块,用于执行一个单独的相关操作。函数为你的应用程序提供了更好的模块化和高度代码重用。

采用自上而下的方法构建处理逻辑涉及定义独立的可重用函数块。函数可以通过传递所需的数据(称为 parametersarguments )从任何其他函数调用。被调用的函数将其结果返回给调用环境。

python functions

Types of Python Functions

Python 提供以下类型的函数 -

  1. Built-in functions

  2. 内置模块中定义的函数

  3. User-defined functions

Python 的标准库包含许多内置函数。Python 的一些内置函数是 print()、int()、len()、sum() 等。这些函数始终可用,因为在启动 Python 解释器后,它们被加载到计算机的内存中。

标准库还捆绑了许多模块。每个模块定义一组函数。这些函数不是随时可用的。你需要将它们从各自模块导入内存。

除了内置函数和内置模块中的函数外,你还可以创建自己的函数。这些函数称为用户自定义函数。

Python Defining a Function

你可以定义自定义函数来提供所需的功能。以下是定义 Python 函数的简单规则。

  1. 函数块以关键字 def 开始,后面是函数名称和小括号 ( ( ) )。

  2. 任何输入参数或参数都应放置在这些括号内。您还可以在这些括号内定义参数。

  3. 函数的第一条语句可以是可选的语句;函数的文档字符串或文档字符串。

  4. 每个函数中的代码块以冒号 (:) 开头,并以缩进开头。

  5. 语句 return [expression] 退出一个函数,可选地将一个表达式传回调用者。没有参数的 return 语句与 return None 相同。

Syntax

def functionname( parameters ):
   "function_docstring"
   function_suite
   return [expression]

默认情况下,参数具有按位置的行为,您需要按照定义它们的顺序告知它们。

一旦定义了该函数,您就可以通过从另一个函数或直接从 Python 提示符中调用它来执行它。

Example

下面的示例显示了如何定义函数 greetings()。括号为空,因此没有任何参数。

第一行是文档字符串。函数块以 return 语句结束。当调用此函数时, Hello world 消息将被打印。

def greetings():
   "This is docstring of greetings function"
   print ("Hello World")
   return
greetings()

Calling a Function

定义一个函数只给它一个名字,指定要包含在函数中的参数,并构建代码块。

一旦确定了函数的基本结构,就可以通过从另一个函数中调用它或直接从 Python 提示符中调用它来执行它。以下是调用 printme() 函数的示例 −

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print str
   return;
# Now you can call printme function
printme("I'm first call to user defined function!")
printme("Again second call to the same function")

当执行以上代码时,它会产生以下 output -

I'm first call to user defined function!
Again second call to the same function

Pass by Reference vs Value

Python 的 function calling mechanism 与 C 和 C++ 的 function calling mechanism 不同。有两种主要的函数调用机制: Call by ValueCall by Reference

当一个变量传递给一个函数时,函数对它做了什么?如果对变量的任何更改不会反映在实际参数中,那么它使用按值传递机制。另一方面,如果更改被反映,则它成为按引用传递机制。

pass by reference vs value

C/C functions are said to be called by value 。当 C/C 中的函数被调用时,实际参数的值被复制到表示形式参数的变量中。如果函数修改了形式参数的值,它不会反映传递给它的变量。

Python uses pass by reference mechanism 。由于 Python 中的变量是对内存中对象的标签或引用,因此用作实际参数和形式参数的变量实际上都引用内存中的同一个对象。我们可以通过在传递之前和之后检查传递变量的 id() 来验证此事实。

def testfunction(arg):
   print ("ID inside the function:", id(arg))
var="Hello"
print ("ID before passing:", id(var))
testfunction(var)

如果执行上述代码,传递之前和函数内部的 id() 是相同的。

ID before passing: 1996838294128
ID inside the function: 1996838294128

该行为还取决于传递的对象是可变的还是不可变的。Python 数字对象是不可变的。当传递一个数字对象,然后函数更改形式参数的值时,它实际上会在内存中创建一个新对象,从而使原始变量保持不变。

def testfunction(arg):
   print ("ID inside the function:", id(arg))
   arg=arg+1
   print ("new object after increment", arg, id(arg))

var=10
print ("ID before passing:", id(var))
testfunction(var)
print ("value after function call", var)

它将生成以下 output

ID before passing: 140719550297160
ID inside the function: 140719550297160
new object after increment 11 140719550297192
value after function call 10

现在让我们将一个可变对象(例如列表或字典)传递给函数。它也通过引用传递,因为在传递之前和之后 lidt 的 id() 是相同的。但是,如果我们在函数内部修改列表,其全局表示也将反映该更改。

在这里,我们传递一个列表,附加一个新项目,然后查看原始列表对象的内容,我们会发现它已更改。

def testfunction(arg):
   print ("Inside function:",arg)
   print ("ID inside the function:", id(arg))
   arg=arg.append(100)

var=[10, 20, 30, 40]
print ("ID before passing:", id(var))
testfunction(var)
print ("list after function call", var)

它将生成以下 output

ID before passing: 2716006372544
Inside function: [10, 20, 30, 40]
ID inside the function: 2716006372544
list after function call [10, 20, 30, 40, 100]

Function Arguments

一个函数的过程通常取决于调用它时提供给它的某些数据。在定义函数时,您必须提供一个变量列表,用来收集传递给它的数据。括号中的变量称为形式参数。

当调用该函数时,必须为每个形式参数提供值。这些被称为实际参数。

function arguments

Example

让我们修改 greeting 函数并给 name 一个参数。在调用它时传递给它的字符串将成为函数内的 name 变量。

def greetings(name):
   "This is docstring of greetings function"
   print ("Hello {}".format(name))
   return

greetings("Samay")
greetings("Pratima")
greetings("Steven")

它将生成以下 output

Hello Samay
Hello Pratima
Hello Steven

Function with Return Value

函数定义中最后一条语句中的 return 关键字表示函数块结束,并且程序流返回到调用函数。虽然函数块中最后一条语句之后的缩进减少也表示返回,但使用显式 return 是个好习惯。

除了流程控制之外,函数还可向调用函数返回值。已返回表达式的值可以存储在变量中以进行进一步处理。

Example

让我们定义 add() 函数。它将传递给它的两个值相加,并返回加法。返回的值存储在名为 result 的变量中。

def add(x,y):
   z=x+y
   return z

a=10
b=20
result = add(a,b)
print ("a = {} b = {} a+b = {}".format(a, b, result))

它将生成如下输出:

a = 10 b = 20 a+b = 30

Types of Function Arguments

根据在定义 Python 函数时声明参数的方式,它们被归类为以下类别:

  1. Positional or required arguments

  2. Keyword arguments

  3. Default arguments

  4. Positional-only arguments

  5. Keyword-only arguments

  6. Arbitrary or variable-length arguments

在下一章中,我们将详细讨论这些函数参数。

Order of Arguments

函数可以具有上面定义的任何类型的参数。但是,必须按以下顺序声明参数:

  1. 参数列表以仅位置参数开头,后跟斜杠 (/) 符号。

  2. 紧随其后的是常规位置参数,可以或不可以作为关键字参数调用。

  3. 然后可能有一个或多个具有默认值的参数。

  4. 接下来,由带有单个星号前缀的变量表示的任意位置参数,该变量被视为元组。这是下一步。

  5. 如果函数有任何仅限关键字的参数,请在它们的名称之前加上星号。一些仅限关键字的参数可能具有默认值。

  6. 方括号中的最后一个参数是用两个星号 ** 接受任意数量的关键字参数。

下图显示了形式参数的顺序:

order of formal arguments

Python - Default Arguments

您可以定义一个函数,并为一个或多个形式参数分配默认值。如果没有将值传递给此类参数,Python 会使用默认值。如果传递了任何值,则默认值将被覆盖。

Example

# Function definition is here
def printinfo( name, age = 35 ):
   "This prints a passed info into this function"
   print ("Name: ", name)
   print ("Age ", age)
   return
# Now you can call printinfo function
printinfo( age=50, name="miki" )
printinfo( name="miki" )

它将生成以下 output

Name: miki
Age 50
Name: miki
Age 35

在上面的示例中,对函数的第二次调用没有将值传递给 age 参数,因此使用了其默认值 35。

让我们看另一个为函数参数分配默认值的示例。定义函数 percent() 如下:

def percent(phy, maths, maxmarks=200):
   val = (phy+maths)*100/maxmarks
   return val

假设给每个科目的分数都是满分 100 分,则 argument maxmarks 设置为 200。因此,我们在调用 percent() 函数时可以省略第三个参数的值。

phy = 60
maths = 70
result = percent(phy,maths)

但是,如果每门学科的最大分数不是 100,那么我们在调用 percent() 函数时需要放置第三个参数。

phy = 40
maths = 46
result = percent(phy,maths, 100)

Example

以下是一个完整的示例 −

def percent(phy, maths, maxmarks=200):
   val = (phy+maths)*100/maxmarks
   return val

phy = 60
maths = 70
result = percent(phy,maths)
print ("percentage:", result)

phy = 40
maths = 46
result = percent(phy,maths, 100)
print ("percentage:", result)

它将生成以下 output

percentage: 65.0
percentage: 86.0

Python - Keyword Arguments

关键字参数也称为命名参数。函数定义中的变量用作关键字。当调用函数时,你能明确地提到名称及其值。

Example

# Function definition is here
def printinfo( name, age ):
   "This prints a passed info into this function"
   print ("Name: ", name)
   print ("Age ", age)
   return

# Now you can call printinfo function
# by positional arguments
printinfo ("Naveen", 29)

# by keyword arguments
printinfo(name="miki", age = 30)

默认情况下,函数按出现顺序将值分配给参数。在第二个函数调用中,我们已经将值分配给了特定参数

它将生成以下 output

Name: Naveen
Age 29
Name: miki
Age 30

让我们借助以下函数定义来尝试进一步了解关键字参数 −

def division(num, den):
   quotient = num/den
   print ("num:{} den:{} quotient:{}".format(num, den, quotient))

division(10,5)
division(5,10)

由于值分配是按照位置,输出如下 −

num:10 den:5 quotient:2.0
num:5 den:10 quotient:0.5

传递具备位置参数的值,让我们使用关键字参数调用该函数 −

division(num=10, den=5)
division(den=5, num=10)

它将生成以下 output

num:10 den:5 quotient:2.0
num:10 den:5 quotient:2.0

在使用关键字参数时,不必遵循函数定义中形式参数的顺序。

使用关键字参数是可选的。您可以使用混合调用。您可以不带关键字将值传递给一些参数,而对于其他参数则使用关键字。

division(10, den=5)

但是,在使用混合调用时,位置参数必须在关键字参数之前。

尝试使用以下语句调用 division() 函数。

division(num=5, 10)

由于位置参数不能出现在关键字参数之后,Python 会引发以下错误消息 −

    division(num=5, 10)
                      ^
SyntaxError: positional argument follows keyword argument

Python - Keyword-Only Arguments

您可以使用形式参数列表中的变量作为关键字来传递值。关键字参数的使用是可选的。然而,您可以强制该函数仅通过关键字提供参数。您应该在仅关键字参数列表之前放置一个星号 (*)。

假设我们有一个具有三个参数的函数,我们希望其中的第二个和第三个参数是仅关键字。为此,在第一个参数后放置 *。

内置的 print() 函数是仅关键字参数的一个示例。您可以在括号中给出要打印的表达式列表。默认情况下,打印的值由一个空格分隔。您可以使用 sep 参数指定任何其他分隔符。

print ("Hello", "World", sep="-")

它将打印 −

Hello-World

sep 参数是仅关键字。尝试将其用作非关键字参数。

print ("Hello", "World", "-")

您会得到不同的输出 − 不如你所愿。

Hello World -

Example

在以下用户定义函数 intr() 中有两个参数,即 amt 和 rate。要使 rate 参数仅限关键字,请在它前面加上 “*”。

def intr(amt,*, rate):
   val = amt*rate/100
   return val

若要调用此函数,必须按关键字传递 rate 的值。

interest = intr(1000, rate=10)

但如果您尝试使用默认的位置方式来调用函数,则会收到一条错误信息。

interest = intr(1000, 10)
               ^^^^^^^^^^^^^^
TypeError: intr() takes 1 positional argument but 2 were given

Python - Positional Arguments

函数定义时在圆括号中声明的变量列表被称为 formal arguments 。一个函数可以用任意数量的形式化参数进行定义。

在调用函数时:

  1. 所有参数都是必需的

  2. 实际参数的数量必须等于形式参数的数量。

  3. 形式化参数是位置的。它们按照定义的顺序拾取值。

  4. 参数类型必须匹配。

  5. 形式参数和实际参数的名称不必相同。

Example

def add(x,y):
   z=x+y
   print ("x={} y={} x+y={}".format(x,y,z))

a=10
b=20
add(a,b)

它将生成以下 output

x=10 y=20 x+y=30

此处,add() 函数有两个形式化参数,它们都是数字。它传递了整数 10 和 20。变量 a 取 10,b 取 20,按照声明的顺序。add() 函数显示相加。

当参数数量不匹配时 Python 也会发出错误。仅给出 1 个参数,然后检查结果。

add(b)
TypeError: add() missing 1 required positional argument: 'y'

传递多个形式化参数,然后检查结果 −

add(10, 20, 30)
TypeError: add() takes 2 positional arguments but 3 were given

相应的实在参数和形式化参数的数据类型必须匹配。将 a 更改为字符串值,并查看结果。

a="Hello"
b=20
add(a,b)

它将生成以下 output

z=x+y
     ~^~
TypeError: can only concatenate str (not "int") to str

Python - Positional-Only Arguments

可以定义一个函数,其中的一个或多个参数不能通过关键字接受其值。这些参数可以称为仅限于位置的参数。

Python 的内置 input() 函数是仅限于位置的参数的示例。input 函数的语法为 −

input(prompt = "")

提示是为了用户方便的解释性字符串。例如 −

name = input("enter your name ")

但是,您无法在括号内使用 prompt 关键字。

   name = input (prompt="Enter your name ")
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: input() takes no keyword arguments

若使参数仅限于位置,请使用 “/” 符号。此符号之前的参数都将视作仅限于位置。

Example

我们将 intr() 函数的两个参数都放在 “/” 的末尾,将其设为仅限于位置。

def intr(amt, rate, /):
   val = amt*rate/100
   return val

如果我们尝试将参数用作关键字,Python 会引发以下错误信息 −

   interest = intr(amt=1000, rate=10)
              ^^^^^^^^^^^^^^^^^^^^^^^
TypeError: intr() got some positional-only arguments passed as keyword arguments: 'amt, rate'

一个函数可以用某些仅限于关键字和一些仅限于位置的参数的方式进行定义。

def myfunction(x, /, y, *, z):
   print (x, y, z)

在此函数中,x 是必需的仅限于位置的参数,y 是常规位置参数(您可以将其用作关键字,如果您愿意的话),z 是仅限于关键字的参数。

下面的函数调用是有效的 −

myfunction(10, y=20, z=30)
myfunction(10, 20, z=30)

然而,这些调用将引发错误 −

   myfunction(x=10, y=20, z=30)
TypeError: myfunction() got some positional-only arguments passed as keyword arguments: 'x'

   myfunction(10, 20, 30)
TypeError: myfunction() takes 2 positional arguments but 3 were given

Python - Arbitrary Arguments

你可能想定义一个能够接受任意数量或可变数量参数的函数。此外,任意的参数数量可能是位置参数或关键字参数。

  1. 用单个星号 * 前缀的参数表示任意位置参数。

  2. 用两个星号 ** 前缀的参数表示任意关键字参数。

Example

以下是任意或可变长度位置参数的示例 −

# sum of numbers
def add(*args):
   s=0
   for x in args:
      s=s+x
   return s
result = add(10,20,30,40)
print (result)

result = add(1,2,3)
print (result)

args 变量用 “*" 前缀存储传递给它的所有值。这里,args 变成了元组。我们可以对其项运行一个循环来添加数字。

它将生成以下 output

100
6

在可变数量的值序列之前带有一些必需参数的函数也是可能的。

Example

以下示例有 avg() 函数。假设一个学生可以参加任意数量的测试。第一个测试是强制性的。他可以参加任意数量的测试来提高他的分数。该函数计算第一个测试中的分数平均值和其余测试中的最高分。

该函数有两个参数,第一个是必需的参数,第二个是用来保存任意数量的值。

#avg of first test and best of following tests
def avg(first, *rest):
   second=max(rest)
   return (first+second)/2

result=avg(40,30,50,25)
print (result)

下列调用 avg() 函数首先将第一个值传递给必需的参数,然后将剩余的值传递给名为 rest 的元组。然后我们找到最大值并使用它来计算平均值。

它将生成以下 output

45.0

如果参数列表中的变量有加星号,那么函数就能接受任意数量的关键字参数。该变量变成了关键词:值对的字典。

Example

下面的代码是带任意关键字参数的函数示例。addr() 函数有一个参数 **kwargs,能够接受任意数量的地址元素,如名称、城市、电话号码、邮政编码等。在函数内部,kwargs 关键字:值对的字典使用 items() 方法进行遍历。

def addr(**kwargs):
   for k,v in kwargs.items():
      print ("{}:{}".format(k,v))

print ("pass two keyword args")
addr(Name="John", City="Mumbai")
print ("pass four keyword args")

# pass four keyword args
addr(Name="Raam", City="Mumbai", ph_no="9123134567", PIN="400001")

它将生成以下 output

pass two keyword args
Name:John
City:Mumbai
pass four keyword args
Name:Raam
City:Mumbai
ph_no:9123134567
PIN:400001

如果函数使用混合类型的参数,则任意关键字参数应该在参数列表中的位置参数、关键字和任意位置参数之后。

Example

试想一下,科学和数学是必修科目,除此之外,学生可以选择任意数量的选修课。

以下代码定义一个 percent() 函数,其中科学中的分数和数学中的分数存储在必需参数中,而可变数量的选修科目中的分数存储在 **optional 参数中。

def percent(math, sci, **optional):
   print ("maths:", math)
   print ("sci:", sci)
   s=math+sci
   for k,v in optional.items():
      print ("{}:{}".format(k,v))
      s=s+v
   return s/(len(optional)+2)

result=percent(math=80, sci=75, Eng=70, Hist=65, Geo=72)
print ("percentage:", result)

它将生成以下 output

maths: 80
sci: 75
Eng:70
Hist:65
Geo:72
percentage: 72.4

Python - Variable Scope

Python 中的变量是计算机内存中的对象的符号名称。Python 采用命名空间的概念为各种标识符(如函数、变量等)定义上下文。命名空间是当前上下文中定义的符号名称的集合。

Python 提供以下类型的命名空间 −

  1. Built-in namespace 包含内置函数和内置异常。一旦 Python 解释器加载,它们就会加载到内存中,并且会一直保留到解释器正在运行为止。

  2. Global namespace 包含主程序中定义的任何名称。这些名称在程序运行时会一直保留在内存中。

  3. Local namespace 包含在函数内部定义的名称。它们在函数运行时可用。

这些名称空间嵌套在彼此内部。下图显示了名称空间之间的关系。

types of namespace

特定变量的生命周期仅限于其定义所在的名称空间中。因此,无法从任何外部名称空间访问存在于内部名称空间中的变量。

globals() Function

Python 的标准库包含了一个内置函数 globals()。它会返回一个在全局名称空间中当前可用的符号字典。

直接从 Python 提示符运行 globals() 函数。

>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}

可以看到会加载包含所有内置函数和内置异常定义的 builtins 模块。

保存以下代码,其中包含少量变量以及一个包含少量其他变量的函数。

name = 'TutorialsPoint'
marks = 50
result = True
def myfunction():
   a = 10
   b = 20
   return a+b

print (globals())

从此脚本内部调用 globals() 会返回以下字典对象 −

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000263E7255250>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\user\\examples\\main.py', '__cached__': None, 'name': 'TutorialsPoint', 'marks': 50, 'result': True, 'myfunction': <function myfunction at 0x00000263E72004A0>}

全局名称空间现在包含程序中的变量和它们的值以及其中的函数对象(而不是函数中的变量)。

locals() Function

Python 的标准库包含了一个内置函数 locals()。它会返回函数的名称空间中当前可用的符号字典。

修改上述脚本,以便从函数内部打印全局和局部名称空间的字典。

name = 'TutorialsPoint'
marks = 50
result = True
def myfunction():
   a = 10
   b = 20
   c = a+b
   print ("globals():", globals())
   print ("locals():", locals())
   return c
myfunction()

output 中的 locals() 声明会返回一个包含函数中当前可用的变量和它们的值的字典。

globals(): {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000169AE265250>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\mlath\\examples\\main.py', '__cached__': None, 'name': 'TutorialsPoint', 'marks': 50, 'result': True, 'myfunction': <function myfunction at 0x00000169AE2104A0>}
locals(): {'a': 10, 'b': 20, 'c': 30}

由于 globals() 和 locals 函数都会返回字典,因此你可以使用字典的 get() 方法或索引运算符从各自的名称空间访问变量的值。

print (globals()['name']) #displays TutorialsPoint
   print (locals().get('a')) #displays 10

Namespace Conflict

如果在全局和局部作用域都存在一个同名变量,Python 解释器会优先考虑局部名称空间中的那个。

marks = 50 # this is a global variable
def myfunction():
   marks = 70 # this is a local variable
   print (marks)

myfunction()
print (marks) # prints global value

它将生成以下 output

70
50

如果你尝试从函数内部修改全局变量的值,Python 会引发 UnboundLocalError

marks = 50 # this is a global variable
def myfunction():
   marks = marks + 20
   print (marks)

myfunction()
print (marks) # prints global value

它将生成以下 output

   marks = marks + 20
           ^^^^^
UnboundLocalError: cannot access local variable 'marks' where it is not associated with a value

要修改全局变量,你可以通过字典语法进行更新,或使用 global 关键字在修改之前引用它。

var1 = 50 # this is a global variable
var2 = 60 # this is a global variable
def myfunction():
   "Change values of global variables"
   globals()['var1'] = globals()['var1']+10
   global var2
   var2 = var2 + 20

myfunction()
print ("var1:",var1, "var2:",var2) #shows global variables with changed values

它将生成以下 output

var1: 60 var2: 80

最后,如果你尝试在全局作用域中访问局部变量,Python 会引发 NameError,因为局部作用域中的变量不能在外部访问。

var1 = 50 # this is a global variable
var2 = 60 # this is a global variable
def myfunction(x, y):
   total = x+y
   print ("Total is a local variable: ", total)

myfunction(var1, var2)
print (total) # This gives NameError

它将生成如下输出:

Total is a local variable: 110
Traceback (most recent call last):
   File "C:\Users\user\examples\main.py", line 9, in <module>
   print (total) # This gives NameError
          ^^^^^
NameError: name 'total' is not defined

Python - Function Annotations

Python 的函数注解功能使你能够添加有关在函数定义中声明的参数以及返回数据类型的附加说明性元数据。

尽管你可以使用 Python 的文档字符串功能对函数进行说明,但如果对函数的原型的某些更改进行更改,该功能可能会过时。因此,注解功能被引入 Python 中,这是 PEP 3107 的结果。

函数执行期间,注释不会被 Python 解释器考虑。它们主要用于为程序员提供详细文档的 Python IDE。

注释是可以添加到参数或返回数据类型的任何有效的 Python 表达式。注释最简单的示例是规定参数的数据类型。注释在参数前面加冒号后以表达式的形式提及。

def myfunction(a: int, b: int):
   c = a+b
   return c

请记住,Python 是一种动态类型语言,并且在运行时不会强制进行任何类型检查。因此,用数据类型注释参数并不会在调用函数时产生任何影响。即使给出了非整数参数,Python 也不会检测到任何错误。

def myfunction(a: int, b: int):
   c = a+b
   return c

print (myfunction(10,20))
print (myfunction("Hello ", "Python"))

它将生成以下 output

30
Hello Python

注释在运行时会被忽略,但对于 IDE 和 mypy 等静态类型检查器库很有用。

您还可以为返回数据类型提供注释。在括号后和冒号符号前,放置一个箭头 (→),后跟注释。例如 -

def myfunction(a: int, b: int) -> int:
   c = a+b
   return c

由于在运行时会忽略使用数据类型作为注释,因此您可以放置任何充当参数元数据的表达式。因此,函数可以具有任何任意表达式作为注释,如下例所示 -

def total(x : 'marks in Physics', y: 'marks in chemistry'):
   return x+y

如果您想在注释的同时指定默认参数,则需要在注释表达式后放置它。在参数列表中,默认参数必须位于必需参数之后。

def myfunction(a: "physics", b:"Maths" = 20) -> int:
   c = a+b
   return c
print (myfunction(10))

Python 中的函数也是一个对象,并且它的一个属性是 annotations 。您可以使用 dir() 函数进行检查。

print (dir(myfunction))

这将打印包含 annotations 作为其中一个属性的 myfunction 对象的列表。

['__annotations__', '__builtins__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__getstate__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

annotations 属性本身是一个字典,其中参数是键,而注释是其值。

def myfunction(a: "physics", b:"Maths" = 20) -> int:
   c = a+b
   return c
print (myfunction.__annotations__)

它将生成以下 output

{'a': 'physics', 'b': 'Maths', 'return': <class 'int'>}

您可以为函数指定任意位置和/或任意关键字参数。也可以为它们提供注释。

def myfunction(*args: "arbitrary args", **kwargs: "arbitrary keyword args") -> int:
   pass
print (myfunction.__annotations__)

它将生成以下 output

{'args': 'arbitrary args', 'kwargs': 'arbitrary keyword args', 'return': <class 'int'>}

如果您需要为函数参数提供多个注释表达式,请以字典对象的形式将其放在参数本身前面。

def division(num: dict(type=float, msg='numerator'), den: dict(type=float, msg='denominator')) -> float:
   return num/den
print (division.__annotations__)

它将生成以下 output

{'num': {'type': <class 'float'>, 'msg': 'numerator'}, 'den': {'type': <class 'float'>, 'msg': 'denominator'}, 'return': <class 'float'>}

Python - Modules

函数是一个组织良好的、可重复使用的代码块,用于执行一个单独的相关操作。函数为你的应用程序提供了更好的模块化和高度代码重用。

Python 中的模块概念进一步增强了模块性。您可以同时定义多个相关函数并加载所需的函数。模块是一个包含函数、类、变量、常量或任何其他 Python 对象定义的文件。此文件的内容可以供任何其他程序使用。Python 有 import 关键字用于此目的。

Example

import math
print ("Square root of 100:", math.sqrt(100))

它将生成以下 output

Square root of 100: 10.0

Built in Modules

Python 的标准库附带了大量模块。它们被称为内置模块。大多数这些内置模块是用 C 编写的(因为 Python 的参考实现是 C),并且预编译到库中。这些模块封装了有用的功能,如特定于系统操作系统的管理、磁盘 IO、网络等。

以下是内置模块的选择列表 -

User Defined Modules

带有 .py 扩展名的任何文本文件和包含 Python 代码的文本文件基本上都是一个模块。它可以包含一个或多个函数、变量、常量的定义以及类。来自模块的任何 Python 对象都可以通过 import 语句在解释器会话或另一个 Python 脚本中使用。模块还可以包含可运行的代码。

Create a Module

创建模块只不过是用任何编辑器的帮助保存 Python 代码。让我们将以下代码保存在 mymodule.py

def SayHello(name):
   print ("Hi {}! How are you?".format(name))
   return

您现在可以在当前 Python 终端中导入 mymodule。

>>> import mymodule
>>> mymodule.SayHello("Harish")
Hi Harish! How are you?

您还可以在另一个 Python 脚本中导入一个模块。将以下代码保存在 example.py 中

import mymodule
mymodule.SayHello("Harish")

从终端命令行运行此脚本

C:\Users\user\examples> python example.py
Hi Harish! How are you?

The import Statement

在 Python 中, import 关键字用于从一个模块加载 Python 对象。该对象可以是函数、类、变量等。如果一个模块包含多个定义,则所有这些定义都将被加载到名称空间中。

让我们将具有三个函数的下列代码保存为 mymodule.py.

def sum(x,y):
   return x+y

def average(x,y):
   return (x+y)/2

def power(x,y):
   return x**y

import mymodule 语句加载这个模块中的所有函数到当前名称空间中。导入模块中的每个函数都是这个模块对象的属性。

>>> dir(mymodule)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'average', 'power', 'sum']

要调用任何函数,请使用模块对象的引用。例如,mymodule.sum()。

import mymodule
print ("sum:",mymodule.sum(10,20))
print ("average:",mymodule.average(10,20))
print ("power:",mymodule.power(10, 2))

它将生成以下 output

sum:30
average:15.0
power:100

The from …​ import Statement

import 语句将会加载模块的所有资源到当前名称空间中。可以通过使用此语法从模块中导入特定对象。例如 −

mymodule 中的三个函数中,只有两个被导入到以下可执行脚本 example.py

from mymodule import sum, average
print ("sum:",sum(10,20))
print ("average:",average(10,20))

它将生成如下输出:

sum: 30
average: 15.0

注意,不需要通过给函数加上其模块名前缀来调用它。

The from…​import * Statement

还可以通过使用以下 import 语句将模块中的所有名称导入到当前名称空间中 −

from modname import *

这提供了一种将模块中的所有项导入当前名称空间的简单方法;但是,此语句应该谨慎使用。

The import …​ as Statement

您可以为导入的模块指定一个别名。

from modulename as alias

调用时 alias 应该加在函数前面。

看看以下 example

import mymodule as x
print ("sum:",x.sum(10,20))
print ("average:", x.average(10,20))
print ("power:", x.power(10, 2))

Module Attributes

在 Python 中,模块是模块类的一个对象,因此它以属性为特征。

以下为模块属性 −

  1. file 返回模块的物理名称。

  2. package 返回模块所属的包。

  3. doc 返回模块顶部的文档字符串(如果有)。

  4. dict 返回模块的整个作用域

  5. name 返回模块的名称

Example

假设以下代码已保存为 mymodule.py

"The docstring of mymodule"
def sum(x,y):
   return x+y

def average(x,y):
   return (x+y)/2

def power(x,y):
   return x**y

让我们导入以下脚本中的 mymodule 来检查其属性−

import mymodule

print ("__file__ attribute:", mymodule.__file__)
print ("__doc__ attribute:", mymodule.__doc__)
print ("__name__ attribute:", mymodule.__name__)

它将生成以下 output

__file__ attribute: C:\Users\mlath\examples\mymodule.py
__doc__ attribute: The docstring of mymodule
__name__ attribute: mymodule

The _name_Attribute

Python 模块的 name 属性非常重要。让我们详细了解一下。

在交互式 shell 中, name 属性会返回“ main

>>> __name__
'__main__'

如果你在解释器会话中导入任何模块,它会返回模块的名称作为该模块的 name 属性。

>>> import math
>>> math.__name__
'math'

从 Python 脚本内部, name 属性会返回“ main

#example.py
print ("__name__ attribute within a script:", __name__)

在命令终端中运行此代码−

__name__ attribute within a script: __main__

此属性允许将 Python 脚本用作可执行文件或模块。与 C++、Java、C# 等不同,在 Python 中,不存在 main() 函数的概念。带 .py 扩展名的 Python 程序脚本可以包含函数定义以及可执行语句。

保存 mymodule.py 及其以下代码−

"The docstring of mymodule"
def sum(x,y):
   return x+y

print ("sum:",sum(10,20))

你可以看到 sum() 函数在其被定义的同一脚本中被调用。

C:\Users\user\examples> python mymodule.py
sum: 30

现在让我们在另一个脚本 example.py 中导入此函数。

import mymodule
print ("sum:",mymodule.sum(10,20))

它将生成以下 output

C:\Users\user\examples> python example.py
sum: 30
sum: 30

输出 “sum:30” 出现了两次。一次是在导入 mymodule 模块时。导入模块中的可执行语句也会运行。第二个输出来自调用脚本,即 example.py 程序。

我们希望看到的是当导入模块时,只导入函数,而不运行其可执行语句。这可以通过检查 name 的值来完成。如果它是 main ,则表示它正在运行,未导入。有条件地包含函数调用等可执行语句。

mymodule.py 中添加 if 语句,如图所示−

"The docstring of mymodule"
def sum(x,y):
   return x+y

if __name__ == "__main__":
   print ("sum:",sum(10,20))

现在,如果你运行 example.py 程序,你会发现 sum:30 输出只出现了一次。

C:\Users\user\examples> python example.py
sum: 30

The reload() Function

有时,你可能需要重新加载模块,尤其是在使用 Python 的交互式解释器会话时。

假设我们有一个测试模块 (test.py),其中有以下函数−

def SayHello(name):
   print ("Hi {}! How are you?".format(name))
   return

我们可以导入该模块并从 Python 提示符调用其函数,如下所示−

>>> import test
>>> test.SayHello("Deepak")
Hi Deepak! How are you?

但是,假设你需要修改 SayHello() 函数,比如−

def SayHello(name, course):
   print ("Hi {}! How are you?".format(name))
   print ("Welcome to {} Tutorial by TutorialsPoint".format(course))
   return

即使编辑 test.py 文件并保存它,内存中加载的函数也不会更新。你需要重新加载它,使用 imp 模块中的 reload() 函数。

>>> import imp
>>> imp.reload(test)
>>> test.SayHello("Deepak", "Python")
Hi Deepak! How are you?
Welcome to Python Tutorial by TutorialsPoint

Python - Built-in Functions

截至 Python 3.11.2 版本,Python 中有 71 个内置函数。内置函数的列表如下 −

Built-in Mathematical Functions

以下是内置到 Python 解释器中的数学函数,因此你无需从任何模块导入它们。

Python - Strings

在 Python 中,字符串是 Unicode 字符的不可变序列。根据 UNICODE 标准,每个字符都有一个唯一的数字值。但是,序列作为一个整体没有数字值,即使所有字符都是数字。为了将字符串与数字和其他标识符区分开来,在字符串字面表示中,字符序列被包含在单引号、双引号或三引号中。因此,1234 是数字(整数),但 '1234' 是字符串。

只要括起来的是同一个字符序列,单引号还是双引号还是三单引号都没关系。因此,以下字符串表示是等价的。

>>> 'Welcome To TutorialsPoint'
'Welcome To TutorialsPoint'
>>> "Welcome To TutorialsPoint"
'Welcome To TutorialsPoint'
>>> '''Welcome To TutorialsPoint'''
'Welcome To TutorialsPoint'
>>> """Welcome To TutorialsPoint"""
'Welcome To TutorialsPoint'

查看以上语句,很明显,Python 在内部以包含在单引号中的方式存储字符串。

Python 中的字符串是 str 类的一个对象。它可以用 type() 函数验证。

var = "Welcome To TutorialsPoint"
print (type(var))

它将生成以下 output

<class 'str'>

您想将一些文本作为字符串的一部分嵌入到双引号中,那么字符串本身应该放在单引号中。要嵌入单引号文本,则应在双引号中编写字符串。

var = 'Welcome to "Python Tutorial" from TutorialsPoint'
print ("var:", var)

var = "Welcome to 'Python Tutorial' from TutorialsPoint"
print ("var:", var)

要使用三引号来形成一个字符串,你可以使用三个单引号或三个双引号 − 两个版本是类似的。

var = '''Welcome to TutorialsPoint'''
print ("var:", var)

var = """Welcome to TutorialsPoint"""
print ("var:", var)

三引号字符串对形成多行字符串很有用。

var = '''
Welcome To
Python Tutorial
from TutorialsPoint
'''
print ("var:", var)

它将生成以下 output

var:
Welcome To
Python Tutorial
from TutorialsPoint

字符串是一个非数字数据类型。显然,我们不能对字符串操作数使用算术运算符。在这种情况下,Python 会引发 TypeError。

>>> "Hello"-"World"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Python Slicing Strings

在 Python 中,字符串是有序的 Unicode 字符序列。字符串中的每个字符在序列中具有一个唯一索引。索引从 0 开始。字符串中的第一个字符的位置索引为 0。索引会不断递增到字符串的末尾。

如果字符串变量被声明为 var="HELLO PYTHON",那么字符串中各个字符的索引如下 −

string variable

Python 允许你通过字符串的索引访问字符串中的任何单个字符。在这种情况下,0 是字符串的下界,11 是字符串的上界。所以,var[0] 返回 H,var[6] 返回 P。如果方括号中的索引超过上界,Python 会引发 IndexError。

>>> var="HELLO PYTHON"
>>> var[0]
'H'
>>> var[7]
'Y'
>>> var[11]
'N'
>>> var[12]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range

Python 序列类型(因此也是字符串对象)的一个独特特性是,它还具有负索引方案。在上面的示例中,使用了正索引方案,其中索引从左到右递增。在负索引的情况下,末尾的字符具有 -1 索引,索引从右到左递减,结果第一个字符 H 具有 -12 索引。

negative indexing

让我们使用负索引获取 N、Y 和 H 字符。

>>> var[-1]
'N'
>>> var[-5]
'Y'
>>> var[-12]
'H'
>>> var[-13]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range

再次,如果索引超出了范围,则会遇到 IndexError。

因此,我们可以使用正索引或负索引来从字符串中检索字符。

>>> var[0], var[-12]
('H', 'H')
>>> var[7], var[-5]
('Y', 'Y')
>>> var[11], var[-1]
('N', 'N')

在 Python 中,字符串是一个不可变对象。如果一个对象不能在特定内存位置存储后被修改,则该对象是不可变的。你可以借助字符串的索引从字符串中检索任何字符,但不能用另一个字符替换它。在我们的示例中,Y 字符在 HELLO PYTHON 中的索引为 7。试着将 Y 替换为 y,看看会发生什么。

var="HELLO PYTHON"
var[7]="y"
print (var)

它将生成以下 output

Traceback (most recent call last):
 File "C:\Users\users\example.py", line 2, in <module>
  var[7]="y"
  ~~~^^^
TypeError: 'str' object does not support item assignment

TypeError 是因为字符串是不可变的。

Python 将“:”定义为字符串切片运算符。它从原始字符串返回一个子串。其一般用法为 −

substr=var[x:y]

“:”运算符需要两个整数操作数(两个操作数都可以省略,如我们在后续示例中看到的)。第一个操作数 x 是所需的切片第一个字符的索引。第二个操作数 y 是所需的字符串中倒数第二个字符的索引。因此,var(x:y] 将字符从第 x 个位置分隔到第 (y-1) 个位置,从原始字符串中分隔。

var="HELLO PYTHON"

print ("var:",var)
print ("var[3:8]:", var[3:8])

它将生成以下 output

var: HELLO PYTHON
var[3:8]: LO PY

负索引也可用于切片。

var="HELLO PYTHON"
print ("var:",var)
print ("var[3:8]:", var[3:8])
print ("var[-9:-4]:", var[-9:-4])

它将生成以下 output

var: HELLO PYTHON
var[3:8]: LO PY
var[-9:-4]: LO PY

Python Slice 运算符的两个操作数均为可选。第一个操作数默认为零,这意味着如果没有给出第一个操作数,那么切片从第 0 个索引处的字符开始,即第一个字符。它将切片左起 "y-1" 个字符的子字符串。

var="HELLO PYTHON"
print ("var:",var)
print ("var[0:5]:", var[0:5])
print ("var[:5]:", var[:5])

它将生成以下 output

var: HELLO PYTHON
var[0:5]: HELLO
var[:5]: HELLO

类似地,y 操作数也是可选的。默认值为 "-1",这意味着字符串将从第 x 个位置切片到字符串末尾。

var="HELLO PYTHON"
print ("var:",var)
print ("var[6:12]:", var[6:12])
print ("var[6:]:", var[6:])

它将生成如下输出:

var: HELLO PYTHON
var[6:12]: PYTHON
var[6:]: PYTHON

显然,如果两个操作数都没有使用,那么切片将等于原始字符串。这是因为 "x" 是 0,"y" 默认是最后一个索引加 1(或 -1)。

var="HELLO PYTHON"
print ("var:",var)
print ("var[0:12]:", var[0:12])
print ("var[:]:", var[:])

它将生成以下 output

var: HELLO PYTHON
var[0:12]: HELLO PYTHON
var[:]: HELLO PYTHON

左操作数必须小于右操作数,才能获取原始字符串的一个子字符串。如果左操作数更大,Python 不会引发任何错误,但会返回一个空字符串。

var="HELLO PYTHON"
print ("var:",var)
print ("var[-1:7]:", var[-1:7])
print ("var[7:0]:", var[7:0])

它将生成以下 output

var: HELLO PYTHON
var[-1:7]:
var[7:0]:

切片返回一个新字符串。你完全可以在切片字符串上执行字符串操作,如连接或切片。

var="HELLO PYTHON"

print ("var:",var)
print ("var[:6][:2]:", var[:6][:2])

var1=var[:6]
print ("slice:", var1)
print ("var1[:2]:", var1[:2])

它将生成以下 output

var: HELLO PYTHON
var[:6][:2]: HE
slice: HELLO
var1[:2]: HE

Python - Modify Strings

在 Python 中,字符串( str 类的对象)是不可变类型。不可变对象是可以就地修改的,是在内存中创建的。因此,与列表不同,序列中的任何字符都不能被覆盖,也不能插入或追加字符,除非使用某些返回新字符串对象的字符串方法。

但是,我们可以使用以下技巧之一作为解决方法来修改字符串。

Converting a String to a List

由于字符串和列表对象都是序列,因此它们可以相互转换。因此,如果我们将字符串对象转换为列表,通过 insert()、append() 或 remove() 方法修改列表并将列表转换回字符串,以获取修改后的版本。

我们有一个字符串变量 s1,其值为 WORD。使用 list() 内置函数,让我们将其转换为 l1 列表对象,并在索引 3 处插入一个字符 L。然后我们使用 str 类的 join() 方法连接所有字符。

s1="WORD"
print ("original string:", s1)
l1=list(s1)

l1.insert(3,"L")

print (l1)

s1=''.join(l1)
print ("Modified string:", s1)

它将生成以下 output

original string: WORD
['W', 'O', 'R', 'L', 'D']
Modified string: WORLD

Using the Array Module

要修改字符串,请构造一个数组对象。Python 标准库包含 array 模块。我们可以从一个字符串变量得到一个 Unicode 类型的数组。

import array as ar
s1="WORD"
sar=ar.array('u', s1)

数组中的项目从零开始索引。因此,我们可以执行诸如追加、插入、删除等的数组操作。让我们在字符 D 之前插入 L

sar.insert(3,"L")

现在,借助 tounicode() 方法,取回已修改的字符串

import array as ar

s1="WORD"
print ("original string:", s1)

sar=ar.array('u', s1)
sar.insert(3,"L")
s1=sar.tounicode()

print ("Modified string:", s1)

它将生成以下 output

original string: WORD
Modified string: WORLD

Using the StringIO Class

Python 的 io 模块定义了处理流的类。StringIO 类使用内存中的文本缓冲区表示文本流。从字符串获得的 StringIO 对象表现得像一个文件对象。因此,我们可以在其上执行读/写操作。StringIO 类的 getvalue() 方法返回一个字符串。

让我们在以下程序中使用此原理来修改一个字符串。

import io

s1="WORD"
print ("original string:", s1)

sio=io.StringIO(s1)
sio.seek(3)
sio.write("LD")
s1=sio.getvalue()

print ("Modified string:", s1)

它将生成以下 output

original string: WORD
Modified string: WORLD

Python - String Concatenation

"" 运算符众所周知是一个加法运算符,返回两个数字的和。但是,"" 符号在 Python 中用作字符串 concatenation operator 。它使用两个字符串操作数,并产生两个字符串的连接。

加号符号右侧字符串的字符附加到其左侧的字符串上。连接的结果是新字符串。

str1="Hello"
str2="World"
print ("String 1:",str1)
print ("String 2:",str2)
str3=str1+str2
print("String 3:",str3)

它将生成以下 output

String 1: Hello
String 2: World
String 3: HelloWorld

要在两者之间插入空格,请使用第三个空字符串。

str1="Hello"
str2="World"
blank=" "
print ("String 1:",str1)
print ("String 2:",str2)
str3=str1+blank+str2
print("String 3:",str3)

它将生成以下 output

String 1: Hello
String 2: World
String 3: Hello World

另一个符号 ,我们通常用于两个数字的乘法,也可以用于字符串操作数。在这里, 在 Python 中用作重复运算符。其中一个操作数必须是整数,另一个操作数必须是字符串。运算符连接字符串的多个副本。例如 -

>>> "Hello"*3
'HelloHelloHello'

整数操作数是要连接的字符串操作数的副本数。

这两个字符串操作符( ) the repetition operator and () the concatenation operator, can be used in a single expression. The " ” 操作符的优先级高于“" 操作符。

str1="Hello"
str2="World"
print ("String 1:",str1)
print ("String 2:",str2)
str3=str1+str2*3
print("String 3:",str3)
str4=(str1+str2)*3
print ("String 4:", str4)

若要形成 str3 字符串,Python 会先连接 3 个 World 副本,然后将结果附加到 Hello

String 3: HelloWorldWorldWorld

在第二种情况下,字符串 str1 和 str2 位于括号中,因此它们的连接首先发生。然后将结果复制三次。

String 4: HelloWorldHelloWorldHelloWorld

除了 + 和 * 之外,不能将其他算术运算符符号与字符串操作数一起使用。

Python - String Formatting

字符串格式化是通过在现有字符串中插入数字表达式的值来动态构建字符串表示形式的过程。 Python 的字符串连接运算符不接受非字符串操作数。因此, Python 提供了以下字符串格式化技术 −

Python - Escape Characters

在 Python 中,如果在引号之前加上“r”或“R”,则字符串将成为原始字符串。因此,'Hello' 是一个普通字符串,而 r’Hello' 是一个原始字符串。

>>> normal="Hello"
>>> print (normal)
Hello
>>> raw=r"Hello"
>>> print (raw)
Hello

在正常情况下,两者之间没有区别。但是,当转义字符嵌入在字符串中时,普通字符串实际上会解释转义序列,而原始字符串不会处理转义字符。

>>> normal="Hello\nWorld"
>>> print (normal)
Hello
World
>>> raw=r"Hello\nWorld"
>>> print (raw)
Hello\nWorld

在上面的示例中,打印普通字符串时,转义字符 '\n' 会被处理,以引入新行。但是,由于原始字符串操作符 'r',转义字符的效果不会按照其含义进行转换。

换行字符 \n 是 Python 识别的转义序列之一。转义序列调用替代实现字符子序列到“\”。在 Python 中,“\”用作转义字符。下表显示了转义序列列表。

除非存在 'r' 或 'R' 前缀,否则字符串和字节文字中的转义序列会根据类似于标准 C 使用的规则进行解释。识别的转义序列如下 −

Example

以下代码显示了上表中列出的转义序列的用法:

# ignore \
s = 'This string will not include \
backslashes or newline characters.'
print (s)

# escape backslash
s=s = 'The \\character is called backslash'
print (s)

# escape single quote
s='Hello \'Python\''
print (s)

# escape double quote
s="Hello \"Python\""
print (s)

# escape \b to generate ASCII backspace
s='Hel\blo'
print (s)

# ASCII Bell character
s='Hello\a'
print (s)

# newline
s='Hello\nPython'
print (s)

# Horizontal tab
s='Hello\tPython'
print (s)

# form feed
s= "hello\fworld"
print (s)

# Octal notation
s="\101"
print(s)

# Hexadecimal notation
s="\x41"
print (s)

它将生成以下 output

This string will not include backslashes or newline characters.
The \character is called backslash
Hello 'Python'
Hello "Python"
Helo
Hello
Hello
Python
Hello Python
hello
world
A
A

Python - String Methods

Python 的内置 str 类定义了不同的方法。它们有助于操作字符串。由于字符串是不可变对象,因此这些方法返回原始字符串的副本,在其上执行相应的处理。

字符串方法可分类为以下类别 −

Python - String Exercises

Example 1

查找给定字符串中元音数量的 Python 程序。

mystr = "All animals are equal. Some are more equal"
vowels = "aeiou"
count=0
for x in mystr:
   if x.lower() in vowels: count+=1
print ("Number of Vowels:", count)

它将生成以下 output

Number of Vowels: 18

Example 2

将二进制位字符串转换为整数的 Python 程序。

mystr = '10101'

def strtoint(mystr):
   for x in mystr:
      if x not in '01': return "Error. String with non-binary characters"
   num = int(mystr, 2)
   return num
print ("binary:{} integer: {}".format(mystr,strtoint(mystr)))

它将生成以下 output

binary:10101 integer: 21

mystr 更改为 '10, 101'

binary:10,101 integer: Error. String with non-binary characters

Example 3

从字符串中删除所有数字的 Python 程序。

digits = [str(x) for x in range(10)]
mystr = 'He12llo, Py00th55on!'
chars = []
for x in mystr:
   if x not in digits:
      chars.append(x)
newstr = ''.join(chars)
print (newstr)

它将生成以下 output

Hello, Python!

Exercise Programs

  1. 对字符串中的字符进行排序的 Python 程序

  2. 从字符串中删除重复字符的 Python 程序

  3. 列出字符串中唯一字符及其计数的 Python 程序

  4. 在字符串中查找单词数量的 Python 程序

  5. Python 程序将所有非字母字符从字符串中删除

Python - Lists

列表是 Python 中内置的数据类型之一。Python 列表是由逗号分隔的项目序列,用方括号 [ ] 括起来。Python 列表中的项目不必是相同的数据类型。

以下是一些 Python 列表示例:

list1 = ["Rohan", "Physics", 21, 69.75]
list2 = [1, 2, 3, 4, 5]
list3 = ["a", "b", "c", "d"]
list4 = [25.50, True, -55, 1+2j]

在 Python 中,列表是序列数据类型。它是项目的有序集合。列表中的每个项目都有一个唯一的位置索引,从 0 开始。

Python 中的列表类似于 C、C 或 Java 中的数组。但是,主要区别在于在 C/C/Java 中,数组元素必须是相同类型。另一方面,Python 列表可以包含不同数据类型的对象。

Python 列表是可变的。可以使用其索引访问列表中的任何项目,并且可以修改它。可以从列表中删除或添加一个或多个对象。列表可以在多个索引位置具有相同的项目。

Python List Operations

在 Python 中,列表是一个序列。因此,我们可以使用“+”运算符连接两个列表,并使用“*”运算符连接列表的多个副本。成员运算符“in”和“not in”与列表对象一起使用。

Python - Access List Items

在 Python 中,列表是一个序列。列表中的每个对象都可以通过其索引访问。索引从 0 开始。索引或列表中的最后一个项目是“length-1”。要访问列表中的值,请使用方括号进行切片,并使用索引或索引来获取该索引处的值。

切片运算符从列表中获取一个或多个项目。将索引放在方括号上以在对应位置检索项目。

obj = list1[i]

Example 1

请看以下示例:

list1 = ["Rohan", "Physics", 21, 69.75]
list2 = [1, 2, 3, 4, 5]

print ("Item at 0th index in list1: ", list1[0])
print ("Item at index 2 in list2: ", list2[2])

它将生成以下 output

Item at 0th index in list1: Rohan
Item at index 2 in list2: 3

Python 允许将负索引与任何序列类型一起使用。“-1”索引指向列表中的最后一个项目。

Example 2

让我们再举一个例子:

list1 = ["a", "b", "c", "d"]
list2 = [25.50, True, -55, 1+2j]

print ("Item at 0th index in list1: ", list1[-1])
print ("Item at index 2 in list2: ", list2[-3])

它将生成以下 output

Item at 0th index in list1: d
Item at index 2 in list2: True

切片运算符从原始列表中提取一个子列表。

Sublist = list1[i:j]

Parameters

  1. i - 子列表中第一个项目索引

  2. j - 子列表中倒数第二个项目的索引

这将返回 list1 中第 i 个到第 (j-1) 个项目的一个切片。

Example 3

在切片时,操作数“i”和“j”都是可选的。如果没有使用,则“i”是 0,“j”是列表中的最后一个项目。负索引可用于切片。请看以下示例:

list1 = ["a", "b", "c", "d"]
list2 = [25.50, True, -55, 1+2j]

print ("Items from index 1 to 2 in list1: ", list1[1:3])
print ("Items from index 0 to 1 in list2: ", list2[0:2])

它将生成以下 output

Items from index 1 to 2 in list1: ['b', 'c']
Items from index 0 to 1 in list2: [25.5, True]

Example 4

list1 = ["a", "b", "c", "d"]
list2 = [25.50, True, -55, 1+2j]
list4 = ["Rohan", "Physics", 21, 69.75]
list3 = [1, 2, 3, 4, 5]

print ("Items from index 1 to last in list1: ", list1[1:])
print ("Items from index 0 to 1 in list2: ", list2[:2])
print ("Items from index 2 to last in list3", list3[2:-1])
print ("Items from index 0 to index last in list4", list4[:])

它将生成以下 output

Items from index 1 to last in list1: ['b', 'c', 'd']
Items from index 0 to 1 in list2: [25.5, True]
Items from index 2 to last in list3 [3, 4]
Items from index 0 to index last in list4 ['Rohan', 'Physics', 21, 69.75]

Python - Change List Items

列表是 Python 中的可变数据类型。这意味着在将对象存储在内存中后,列表的内容可以就地修改。您可以在列表中给定索引位置分配新值

Syntax

list1[i] = newvalue

Example 1

在以下代码中,我们更改了给定列表中索引 2 的值。

list3 = [1, 2, 3, 4, 5]
print ("Original list ", list3)
list3[2] = 10
print ("List after changing value at index 2: ", list3)

它将生成以下 output

Original list [1, 2, 3, 4, 5]
List after changing value at index 2: [1, 2, 10, 4, 5]

您可以用另一个子列表替换列表中连续的更多项。

Example 2

在以下代码中,用另一个子列表中的项替换了索引 1 和 2 处的项。

list1 = ["a", "b", "c", "d"]

print ("Original list: ", list1)

list2 = ['Y', 'Z']
list1[1:3] = list2

print ("List after changing with sublist: ", list1)

它将生成以下 output

Original list: ['a', 'b', 'c', 'd']
List after changing with sublist: ['a', 'Y', 'Z', 'd']

Example 3

如果源子列表的项多于要替换的部分,则会插入源中的额外项。请看以下代码 −

list1 = ["a", "b", "c", "d"]
print ("Original list: ", list1)
list2 = ['X','Y', 'Z']
list1[1:3] = list2
print ("List after changing with sublist: ", list1)

它将生成以下 output

Original list: ['a', 'b', 'c', 'd']
List after changing with sublist: ['a', 'X', 'Y', 'Z', 'd']

Example 4

如果要用来替换原始列表的部分的子列表的项较少,则将匹配的项替换,并删除原始列表中的其余项。

在以下代码中,我们尝试用“Z”(少于要替换的项)替换“b”和“c”。其结果是 Z 替换 b 并删除 c。

list1 = ["a", "b", "c", "d"]
print ("Original list: ", list1)
list2 = ['Z']
list1[1:3] = list2
print ("List after changing with sublist: ", list1)

它将生成以下 output

Original list: ['a', 'b', 'c', 'd']
List after changing with sublist: ['a', 'Z', 'd']

Python - Add List Items

list 类有两种方法,append() 和 insert(),用于将项目添加到现有列表中。

Example 1

append() 方法将项添加到现有列表的末尾。

list1 = ["a", "b", "c", "d"]
print ("Original list: ", list1)
list1.append('e')
print ("List after appending: ", list1)

Output

Original list: ['a', 'b', 'c', 'd']
List after appending: ['a', 'b', 'c', 'd', 'e']

Example 2

insert() 方法将项插入到列表中指定索引处。

list1 = ["Rohan", "Physics", 21, 69.75]
print ("Original list ", list1)

list1.insert(2, 'Chemistry')
print ("List after appending: ", list1)

list1.insert(-1, 'Pass')
print ("List after appending: ", list1)

Output

Original list ['Rohan', 'Physics', 21, 69.75]
List after appending: ['Rohan', 'Physics', 'Chemistry', 21, 69.75]
List after appending: ['Rohan', 'Physics', 'Chemistry', 21, 'Pass', 69.75]

我们知道“-1”索引指向列表中的最后一项。但请注意,原列表中索引“-1”项为 69.75。附加“化学”后,此索引不会刷新。因此,“通过”未插入到更新的索引“-1”,而是前面的索引“-1”。

Python - Remove List Items

列表类方法 remove()pop() 两种都可以从列表中删除一项。它们之间的区别在于,remove() 删除给定的对象作为参数,而 pop() 删除给定索引处的项。

Using the remove() Method

以下示例显示如何使用 remove() 方法删除列表项 −

list1 = ["Rohan", "Physics", 21, 69.75]
print ("Original list: ", list1)

list1.remove("Physics")
print ("List after removing: ", list1)

它将生成以下 output

Original list: ['Rohan', 'Physics', 21, 69.75]
List after removing: ['Rohan', 21, 69.75]

Using the pop() Method

以下示例显示如何使用 pop() 方法删除列表项 −

list2 = [25.50, True, -55, 1+2j]
print ("Original list: ", list2)
list2.pop(2)
print ("List after popping: ", list2)

它将生成以下 output

Original list: [25.5, True, -55, (1+2j)]
List after popping: [25.5, True, (1+2j)]

Using the "del" Keyword

Python 具有“del”关键字,可从内存中删除任何 Python 对象。

Example

我们可使用“del”从列表中删除一项。请看以下示例 −

list1 = ["a", "b", "c", "d"]
print ("Original list: ", list1)
del list1[2]
print ("List after deleting: ", list1)

它将生成以下 output

Original list: ['a', 'b', 'c', 'd']
List after deleting: ['a', 'b', 'd']

Example

可以使用切片运算符从列表中删除一系列连续项。请看以下示例 −

list2 = [25.50, True, -55, 1+2j]
print ("List before deleting: ", list2)
del list2[0:2]
print ("List after deleting: ", list2)

它将生成以下 output

List before deleting: [25.5, True, -55, (1+2j)]
List after deleting: [-55, (1+2j)]

Python - Loop Lists

可以使用 Python 的 for 循环构造遍历列表中的项。遍历可使用列表作为迭代器或借助于索引进行。

Syntax

Python 列表提供一个迭代器对象。要遍历列表,请按如下方式使用 for 语句 −

for obj in list:
   . . .
   . . .

Example 1

请看以下示例:

lst = [25, 12, 10, -21, 10, 100]
for num in lst:
   print (num, end = ' ')

Output

25 12 10 -21 10 100

Example 2

要遍历列表中的项,获取从“0”到“len-1”的整数范围对象。请看以下示例 −

lst = [25, 12, 10, -21, 10, 100]
indices = range(len(lst))
for i in indices:
   print ("lst[{}]: ".format(i), lst[i])

Output

lst[0]: 25
lst[1]: 12
lst[2]: 10
lst[3]: -21
lst[4]: 10
lst[5]: 100

Python - List Comprehension

列表解析是一个非常强大的编程工具。它类似于数学中的集合生成器符号。它是一种简洁的方法,可通过对现有列表中的每一项执行某种处理来创建新列表。列表解析比通过 for 循环处理列表快得多。

Example 1

假设我们想要分离字符串中的每个字母并将所有非元音字母放入列表对象中。我们可以通过 for 循环执行,如下所示 −

chars=[]
for ch in 'TutorialsPoint':
   if ch not in 'aeiou':
      chars.append(ch)
print (chars)

chars 列表对象显示如下:

['T', 't', 'r', 'l', 's', 'P', 'n', 't']

List Comprehension Technique

我们可以通过列表解析技术轻松获得相同的结果。列表解析的常规用法如下:

listObj = [x for x in iterable]

应用此规则,chars 列表可通过以下语句构造:

chars = [ char for char in 'TutorialsPoint' if char not in 'aeiou']
print (chars)

chars 列表将像以前一样显示:

['T', 't', 'r', 'l', 's', 'P', 'n', 't']

Example 2

以下示例使用列表解析来构建 1 到 10 之间的数字的平方列表

squares = [x*x for x in range(1,11)]
print (squares)

squares 列表对象为:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Nested Loops in List Comprehension

在以下示例中,以元组形式来自两个列表的所有项的组合被添加到第三个列表对象中。

Example 3

list1=[1,2,3]
list2=[4,5,6]
CombLst=[(x,y) for x in list1 for y in list2]
print (CombLst)

它将生成以下 output

[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

Condition in List Comprehension

以下语句将创建 1 到 20 之间所有偶数的列表。

Example 4

list1=[x for x in range(1,21) if x%2==0]
print (list1)

它将生成以下 output

[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Python - Sort Lists

列表类的 sort() 方法使用词典排序机制,以升序或降序重新排列项。该排序是就地进行的,这意味着重新排列在同一列表对象中进行,并且它不返回新对象。

Syntax

list1.sort(key, reverse)

Parameters

  1. Key − 应用于列表中每一项的功能。返回值用于执行排序。可选

  2. reverse − 布尔值。如果设置为 True,则按降序排序。可选

Return value

此方法返回无。

Example 1

现在,我们举几个例子来了解如何在 Python 中对列表进行排序 −

list1 = ['physics', 'Biology', 'chemistry', 'maths']
print ("list before sort", list1)
list1.sort()
print ("list after sort : ", list1)

print ("Descending sort")

list2 = [10,16, 9, 24, 5]
print ("list before sort", list2)
list2.sort()
print ("list after sort : ", list2)

它将生成以下 output

list before sort ['physics', 'Biology', 'chemistry', 'maths']
list after sort: ['Biology', 'chemistry', 'maths', 'physics']
Descending sort
list before sort [10, 16, 9, 24, 5]
list after sort : [5, 9, 10, 16, 24]

Example 2

在此示例中,str.lower() 方法用作 sort() 方法中的键参数。

list1 = ['Physics', 'biology', 'Biomechanics', 'psychology']
print ("list before sort", list1)
list1.sort(key=str.lower)
print ("list after sort : ", list1)

它将生成以下 output

list before sort ['Physics', 'biology', 'Biomechanics', 'psychology']
list after sort : ['biology', 'Biomechanics', 'Physics', 'psychology']

Example 3

让我们将用户定义函数用作 sort() 方法中的键参数。myfunction() 使用 % 运算符返回余数,并根据余数执行排序。

def myfunction(x):
   return x%10
list1 = [17, 23, 46, 51, 90]
print ("list before sort", list1)
list1.sort(key=myfunction)
print ("list after sort : ", list1)

它将生成以下 output

list before sort [17, 23, 46, 51, 90]
list after sort: [90, 51, 23, 46, 17]

Python - Copy Lists

在 Python 中,变量只是一个标签或对内存中对象的引用。因此,赋值“lst1 = lst”是指内存中同一个列表对象。请看以下示例 −

lst = [10, 20]
print ("lst:", lst, "id(lst):",id(lst))
lst1 = lst
print ("lst1:", lst1, "id(lst1):",id(lst1))

它将生成以下 output

lst: [10, 20] id(lst): 1677677188288
lst1: [10, 20] id(lst1): 1677677188288

于是,如果我们更新“lst”,它会自动反映到“lst1”中。 将 lst[0] 更改为 100

lst[0]=100
print ("lst:", lst, "id(lst):",id(lst))
print ("lst1:", lst1, "id(lst1):",id(lst1))

它将生成以下 output

lst: [100, 20] id(lst): 1677677188288
lst1: [100, 20] id(lst1): 1677677188288

因此,我们可以说“lst1”不是“lst”的物理副本。

Using the Copy Method of List Class

Python 的列表类有 copy() 方法,用于创建列表对象的新的物理副本。

Syntax

lst1 = lst.copy()

新的列表对象将有不同的 id() 值。以下示例演示了这一点 −

lst = [10, 20]
lst1 = lst.copy()
print ("lst:", lst, "id(lst):",id(lst))
print ("lst1:", lst1, "id(lst1):",id(lst1))

它将生成以下 output

lst: [10, 20] id(lst): 1677678705472
lst1: [10, 20] id(lst1): 1677678706304

即使这两个列表有相同的数据,它们也有不同的 id() 值,因此它们是两个不同的对象,“lst1”是“lst”的副本。

如果我们尝试修改“lst”,它不会反映在“lst1”中。请看以下示例 −

lst[0]=100
print ("lst:", lst, "id(lst):",id(lst))
print ("lst1:", lst1, "id(lst1):",id(lst1))

它将生成以下 output

lst: [100, 20] id(lst): 1677678705472
lst1: [10, 20] id(lst1): 1677678706304

Python - Join Lists

在 Python 中,列表被归类为序列类型对象。它是一个项集合,可以是不同的数据类型,每个项都有一个从 0 开始的位置索引。您可以使用不同的方法来联接两个 Python 列表。

所有序列类型对象都支持连接运算符,两个列表可以用该运算符连接。

L1 = [10,20,30,40]
L2 = ['one', 'two', 'three', 'four']
L3 = L1+L2
print ("Joined list:", L3)

它将生成以下 output

Joined list: [10, 20, 30, 40, 'one', 'two', 'three', 'four']

您还可以使用带有“+=”符号的增强连接运算符将 L2 追加到 L1

L1 = [10,20,30,40]
L2 = ['one', 'two', 'three', 'four']
L1+=L2
print ("Joined list:", L1)

使用 extend() 方法也可以获得相同的结果。此处,我们需要扩展 L1 以便在其中添加来自 L2 的元素。

L1 = [10,20,30,40]
L2 = ['one', 'two', 'three', 'four']
L1.extend(L2)
print ("Joined list:", L1)

要将一个列表中的项添加到另一个列表中,一个经典的迭代解决方案也可以使用。使用 for 循环遍历第二个列表中的项,并将每个项追加到第一个列表中。

L1 = [10,20,30,40]
L2 = ['one', 'two', 'three', 'four']

for x in L2:
   L1.append(x)

print ("Joined list:", L1)

合并两个列表的一种稍复杂的做法是使用列表解析,如下面的代码所示 −

L1 = [10,20,30,40]
L2 = ['one', 'two', 'three', 'four']
L3 = [y for x in [L1, L2] for y in x]
print ("Joined list:", L3)

Python - List Methods

Python 的 list 类包括以下方法,您可以使用这些方法添加、更新和删除列表项 −

Python - List Exercises

Example 1

Python程序查找给定列表中的唯一数字。

L1 = [1, 9, 1, 6, 3, 4, 5, 1, 1, 2, 5, 6, 7, 8, 9, 2]
L2 = []
for x in L1:
   if x not in L2:
      L2.append(x)
print (L2)

它将生成以下 output

[1, 9, 6, 3, 4, 5, 2, 7, 8]

Example 2

python程序查找列表中所有数字的和。

L1 = [1, 9, 1, 6, 3, 4]
ttl = 0
for x in L1:
   ttl+=x
print ("Sum of all numbers Using loop:", ttl)
ttl = sum(L1)
print ("Sum of all numbers sum() function:", ttl)

它将生成以下 output

Sum of all numbers Using loop: 24
Sum of all numbers sum() function: 24

Example 3

Python程序创建5个随机整数的列表。

import random
L1 = []
for i in range(5):
   x = random.randint(0, 100)
   L1.append(x)
print (L1)

它将生成以下 output

[77, 3, 20, 91, 85]

Exercise Programs

  1. Python程序从列表中删除所有奇数。

  2. Python程序根据每个单词中的字母数量对字符串列表进行排序。

  3. python程序在单独的列表中列出非数字项。

  4. Python程序创建表示字符串中每个字符的整数列表

  5. Python程序查找两个列表中通用的数字。

Python - Tuples

元组是 Python 中的一个内置数据类型。Python 元组是用括号 () 括起来的逗号分隔项的序列。Python 元组中的项不需要是相同的数据类型。

以下是 Python 元组的一些示例 −

tup1 = ("Rohan", "Physics", 21, 69.75)
tup2 = (1, 2, 3, 4, 5)
tup3 = ("a", "b", "c", "d")
tup4 = (25.50, True, -55, 1+2j)

在 Python 中,元组是一个序列数据类型。它是项的有序集合。元组中的每个项都具有一个唯一的位置索引,从 0 开始。

在 C/C++/Java 数组中,数组元素必须具有相同的类型。另一方面,Python 元组可以包含不同数据类型对象。

Python 元组和列表都是序列。两者之间的一个主要区别是:Python 列表是可变的,而元组是不可变的。虽然可以使用索引访问元组中的任何项,但不能修改、删除或添加它们。

Python Tuple Operations

在 Python 中,元组是一个序列。因此,我们可以使用 + 运算符连接两个元组,并使用 * 运算符连接元组的多个副本。成员运算符“in”和“not in”与元组对象一起使用。

请注意,即使元组中只有一个对象,也必须在其后面加逗号。否则,它将被视为一个字符串。

Python - Access Tuple Items

在Python中,元组是一个序列。可以通过索引访问列表中的每个对象。索引从“0”开始。元组中的索引或最后一项是“长度-1”。要访问元组中的值,请使用方括号与索引或索引一起切片,以获取该索引处可用的值。

切片运算符从元组中获取一个或多个项目。

obj = tup1(i)

Example 1

将索引放在方括号中以检索其位置的项目。

tup1 = ("Rohan", "Physics", 21, 69.75)
tup2 = (1, 2, 3, 4, 5)

print ("Item at 0th index in tup1tup2: ", tup1[0])
print ("Item at index 2 in list2: ", tup2[2])

它将生成以下 output

Item at 0th index in tup1: Rohan
Item at index 2 in tup2: 3

Example 2

Python允许将负索引与任何序列类型一起使用。“-1”索引表示元组中的最后一项。

tup1 = ("a", "b", "c", "d")
tup2 = (25.50, True, -55, 1+2j)
print ("Item at 0th index in tup1: ", tup1[-1])
print ("Item at index 2 in tup2: ", tup2[-3])

它将生成以下 output

Item at 0th index in tup1: d
Item at index 2 in tup2: True

Extracting a Subtuple from a Tuple

切片运算符从原始元组中提取子元组。

Subtup = tup1[i:j]

Parameters

  1. i - subtup中第一个项目的索引

  2. j - 子组中最后一个项目旁边的项目的索引

这将从tup1中返回第i个到第(j-1)个项目的切片。

Example 3

请看以下示例:

tup1 = ("a", "b", "c", "d")
tup2 = (25.50, True, -55, 1+2j)

print ("Items from index 1 to 2 in tup1: ", tup1[1:3])
print ("Items from index 0 to 1 in tup2: ", tup2[0:2])

它将生成以下 output

Items from index 1 to 2 in tup1: ('b', 'c')
Items from index 0 to 1 in tup2: (25.5, True)

Example 4

切片时,两个操作数“i”和“j”都是可选的。如果不使用,“i”为0,“j”为元组中的最后一项。可以在切片中使用负索引。请看以下示例-

tup1 = ("a", "b", "c", "d")
tup2 = (25.50, True, -55, 1+2j)
tup4 = ("Rohan", "Physics", 21, 69.75)
tup3 = (1, 2, 3, 4, 5)

print ("Items from index 1 to last in tup1: ", tup1[1:])
print ("Items from index 0 to 1 in tup2: ", tup2[:2])
print ("Items from index 2 to last in tup3", tup3[2:-1])
print ("Items from index 0 to index last in tup4", tup4[:])

它将生成以下 output

Items from index 1 to last in tup1: ('b', 'c', 'd')
Items from index 0 to 1 in tup2: (25.5, True)
Items from index 2 to last in tup3: (3, 4)
Items from index 0 to index last in tup4: ('Rohan', 'Physics', 21, 69.75)

Python - Update Tuples

在python中,元组是不可变的数据类型。一旦在内存中创建不可变对象,就无法对其进行修改。

Example 1

如果我们尝试使用切片运算符给元组项分配一个新值,Python 将引发 TypeError。请参见以下示例 −

tup1 = ("a", "b", "c", "d")
tup1[2] = 'Z'
print ("tup1: ", tup1)

它将生成以下 output

Traceback (most recent call last):
 File "C:\Users\mlath\examples\main.py", line 2, in <module>
  tup1[2] = 'Z'
  ~~~~^^^
TypeError: 'tuple' object does not support item assignment

因此,无法更新元组。因此,元组类不提供用于从元组对象中添加、插入、删除、排序项的方法,就像列表类一样。

How to Update a Python Tuple?

你可以使用一个解决方法来更新元组。使用 list() 函数将元组转换为列表,执行所需的追加/插入/删除操作,然后将列表解析回元组对象。

Example 2

在此,我们把元组转换为列表,更新现有项,追加一个新项,并对列表进行排序。该列表再被转换为元组。

tup1 = ("a", "b", "c", "d")
print ("Tuple before update", tup1, "id(): ", id(tup1))

list1 = list(tup1)
list1[2]='F'
list1.append('Z')
list1.sort()
print ("updated list", list1)

tup1 = tuple(list1)
print ("Tuple after update", tup1, "id(): ", id(tup1))

它将生成以下 output

Tuple before update ('a', 'b', 'c', 'd') id(): 2295023084192
updated list ['F', 'Z', 'a', 'b', 'd']
Tuple after update ('F', 'Z', 'a', 'b', 'd') id(): 2295021518128

但是,请注意在更新前后 tup1 的 id() 是不同的。这意味着将创建新的元组对象,并且不会在当地修改原始元组对象。

Python - Unpack Tuple Items

术语“拆包”指对单独变量进行元组项解析的过程。在 Python 中,括号是序列对象的文字表示的默认分隔符。

声明元组的以下语句是相同的。

>>> t1 = (x,y)
>>> t1 = x,y
>>> type (t1)
<class 'tuple'>

Example 1

若要将元组项存储在单独的变量中,请在赋值运算符的左侧使用多个变量,如此处所示 −

tup1 = (10,20,30)
x, y, z = tup1
print ("x: ", x, "y: ", "z: ",z)

它将生成以下 output

x: 10 y: 20 z: 30

这就是在单独变量中拆解元组方法。

Using to Unpack a T uple

在上例中,赋值运算符左侧的变量数等于元组中的项数。如果数量不相等怎么办?

Example 2

如果变量数多于或少于元组的长度,Python 会引发 ValueError。

tup1 = (10,20,30)
x, y = tup1
x, y, p, q = tup1

它将生成以下 output

  x, y = tup1
  ^^^^
ValueError: too many values to unpack (expected 2)
  x, y, p, q = tup1
  ^^^^^^^^^^
ValueError: not enough values to unpack (expected 4, got 3)

在这种情况下,将“ " symbol is used for unpacking. Prefix " ”变为“y”,如下所示 −

tup1 = (10,20,30)
x, *y = tup1
print ("x: ", "y: ", y)

它将生成以下 output

x: y: [20, 30]

元组中的第一个值被分配给“x”,其余的项分配给了变为列表的“y”。

Example 3

在本例中,元组包含 6 个值,待拆包的变量有 3 个。我们在第二个变量前加上“*”。

tup1 = (10,20,30, 40, 50, 60)
x, *y, z = tup1
print ("x: ",x, "y: ", y, "z: ", z)

它将生成以下 output

x: 10 y: [20, 30, 40, 50] z: 60

在这里,值首先被拆包成“x”和“z”,然后其余的值作为列表分配给“y”。

Example 4

如果我们在第一个变量中加上“*”会怎么样?

tup1 = (10,20,30, 40, 50, 60)
*x, y, z = tup1
print ("x: ",x, "y: ", y, "z: ", z)

它将生成以下 output

x: [10, 20, 30, 40] y: 50 z: 60

在此同样地,元组以这样的方式被拆包:各个变量首先获取值,剩下的值留给列表“x”。

Python - Loop Tuples

你可以使用 Python 的 for 循环构造遍历元组中的项。可使用元组作为迭代器进行遍历或借助于索引。

Syntax

Python 元组提供了一个迭代器对象。若要迭代元组,请使用 for 语句,如下所示 −

for obj in tuple:
   . . .
   . . .

Example 1

以下示例展示了一个简单的 Python for 循环构造−

tup1 = (25, 12, 10, -21, 10, 100)
for num in tup1:
   print (num, end = ' ')

它将生成以下 output

25 12 10 -21 10 100

Example 2

若要遍历元组中的项,获取整数的范围对象 “0” 到 “len-1”。

tup1 = (25, 12, 10, -21, 10, 100)
indices = range(len(tup1))
for i in indices:
   print ("tup1[{}]: ".format(i), tup1[i])

它将生成以下 output

tup1[0]: 25
tup1 [1]: 12
tup1 [2]: 10
tup1 [3]: -21
tup1 [4]: 10
tup1 [5]: 100

Python - Join Tuples

在 Python 中,将元组归类为序列类型对象。它是项的集合,它们可能属于不同的数据类型,并且每个项具有从 0 开始的位置索引。虽然此定义也适用于列表,但列表和元组之间存在两个主要差异。首先,如果列表中的项放在方括号中(例如:[10,20,30,40]),则通过将项放在括号中形成元组(例如:(10,20,30,40))。

在 Python 中,元组是一个不可变的对象。因此,一旦在内存中形成元组,便无法修改其内容。

但是,你可以使用不同的方式将两个 Python 元组连接起来。

Example 1

所有序列类型对象都支持连接运算符,两个列表可以用该运算符连接。

T1 = (10,20,30,40)
T2 = ('one', 'two', 'three', 'four')
T3 = T1+T2
print ("Joined Tuple:", T3)

它将生成以下 output

Joined Tuple: (10, 20, 30, 40, 'one', 'two', 'three', 'four')

Example 2

你还可以使用带有 “+=” 符号的增强连接运算符将 T2 附加到 T1

T1 = (10,20,30,40)
T2 = ('one', 'two', 'three', 'four')
T1+=T2
print ("Joined Tuple:", T1)

Example 3

可以使用 extend() 方法获得相同的结果。这里,我们需要将两个元组对象强制转换为列表,扩展的方式是将一个列表中的元素添加到另一个列表中,并将连接的列表转换回元组。

T1 = (10,20,30,40)
T2 = ('one', 'two', 'three', 'four')
L1 = list(T1)
L2 = list(T2)
L1.extend(L2)
T1 = tuple(L1)
print ("Joined Tuple:", T1)

Example 4

Python 的内置 sum() 函数也有助于连接元组。我们使用一个表达式

sum((t1, t2), ())

首先将第一个元组的元素附加到一个空元组,然后附加第二个元组的元素,并返回一个新的元组,即两个元组的连接。

T1 = (10,20,30,40)
T2 = ('one', 'two', 'three', 'four')
T3 = sum((T1, T2), ())
print ("Joined Tuple:", T3)

Example 5

合并两个元组的一种稍微复杂的方法是使用列表解析,如下代码所示−

T1 = (10,20,30,40)
T2 = ('one', 'two', 'three', 'four')
L1, L2 = list(T1), list(T2)
L3 = [y for x in [L1, L2] for y in x]
T3 = tuple(L3)
print ("Joined Tuple:", T3)

Example 6

你可以在第二个循环中的项上运行一个 for 循环,将每个项转换为一个单项元组,并使用 “+=” 运算符将其连接到第一个元组

T1 = (10,20,30,40)
T2 = ('one', 'two', 'three', 'four')
for t in T2:
   T1+=(t,)
print (T1)

Python - Tuple Methods

由于 Python 中的元组是不可变的,因此元组类没有定义用于添加或删除项的方法。元组类仅定义了两种方法。

Finding the Index of a Tuple Item

元组类的 index() 方法返回给定项的第一次出现的索引。

Syntax

tuple.index(obj)

Return value

index() 方法返回一个整数,表示 “obj” 的第一次出现的索引。

Example

请看以下示例:

tup1 = (25, 12, 10, -21, 10, 100)
print ("Tup1:", tup1)
x = tup1.index(10)
print ("First index of 10:", x)

它将生成以下 output

Tup1: (25, 12, 10, -21, 10, 100)
First index of 10: 2

Counting Tuple Items

元组类中的 count() 方法返回给定对象在元组中出现的次数。

Syntax

tuple.count(obj)

Return Value

对象的出现次数。count() 方法返回一个整数。

Example

tup1 = (10, 20, 45, 10, 30, 10, 55)
print ("Tup1:", tup1)
c = tup1.count(10)
print ("count of 10:", c)

它将生成以下 output

Tup1: (10, 20, 45, 10, 30, 10, 55)
count of 10: 3

Example

即使元组中的项包含表达式,也会对它们进行求值以获得计数。

Tup1 = (10, 20/80, 0.25, 10/40, 30, 10, 55)
print ("Tup1:", tup1)
c = tup1.count(0.25)
print ("count of 10:", c)

它将生成以下 output

Tup1: (10, 0.25, 0.25, 0.25, 30, 10, 55)
count of 10: 3

Python Tuple Exercises

Example 1

Python 程序,用于查找给定元组中的唯一数字−

T1 = (1, 9, 1, 6, 3, 4, 5, 1, 1, 2, 5, 6, 7, 8, 9, 2)
T2 = ()
for x in T1:
   if x not in T2:
      T2+=(x,)
print ("original tuple:", T1)
print ("Unique numbers:", T2)

它将生成以下 output

original tuple: (1, 9, 1, 6, 3, 4, 5, 1, 1, 2, 5, 6, 7, 8, 9, 2)
Unique numbers: (1, 9, 6, 3, 4, 5, 2, 7, 8)

Example 2

Python 程序,用于查找元组中所有数字的总和−

T1 = (1, 9, 1, 6, 3, 4)
ttl = 0
for x in T1:
   ttl+=x

print ("Sum of all numbers Using loop:", ttl)

ttl = sum(T1)
print ("Sum of all numbers sum() function:", ttl)

它将生成以下 output

Sum of all numbers Using loop: 24
Sum of all numbers sum() function: 24

Example 3

创建 5 个随机整数的元组的 Python 程序 -

import random
t1 = ()
for i in range(5):
   x = random.randint(0, 100)
   t1+=(x,)
print (t1)

它将生成以下 output

(64, 21, 68, 6, 12)

Exercise Programs

  1. 移除列表中所有重复数字的 Python 程序。

  2. 对元组中的字符串按照每个单词的字母数量进行排序的 Python 程序。

  3. 准备一个元组,包含给定元组中的非数字项的 Python 程序。

  4. 创建表示字符串中每个字符的整数元组的 Python 程序

  5. 查找两个元组中常见数字的 Python 程序。

Python - Sets

集合是 Python 中内置的数据类型之一。在数学上,集合是不同对象的集合。集合数据类型是 Python 对集合的实现。集合中的对象可以是任何数据类型。

在 Python 中,集合也是一种集合数据类型,如列表或元组。但是,它不是有序集合,即集合中的项或无法按其位置索引访问。集合对象是一个集合,其中包含一对花括号 {} 括起来的不可变对象。

Example 1

集合对象的某些示例如下所示 -

s1 = {"Rohan", "Physics", 21, 69.75}
s2 = {1, 2, 3, 4, 5}
s3 = {"a", "b", "c", "d"}
s4 = {25.50, True, -55, 1+2j}
print (s1)
print (s2)
print (s3)
print (s4)

它将生成以下 output

{'Physics', 21, 'Rohan', 69.75}
{1, 2, 3, 4, 5}
{'a', 'd', 'c', 'b'}
{25.5, -55, True, (1+2j)}

以上结果表明,集合对象中不会必然保留分配中对象的顺序。这是因为 Python 优化了用于集合运算的集合结构。

除了集合的文字表示形式(将项放在花括号中)以外,Python 的内置 set() 函数还构造集合对象。

set() Function

set() 是内置函数之一。它将任何序列对象(列表、元组或字符串)作为参数,并返回一个集合对象

Syntax

Obj = set(sequence)

Parameters

  1. sequence - 列表、元组或 str 类型的一个对象

Return value

set() 函数从序列中返回一个集合对象,并丢弃其中的重复元素。

Example 2

L1 = ["Rohan", "Physics", 21, 69.75]
s1 = set(L1)
T1 = (1, 2, 3, 4, 5)
s2 = set(T1)
string = "TutorialsPoint"
s3 = set(string)

print (s1)
print (s2)
print (s3)

它将生成以下 output

{'Rohan', 69.75, 21, 'Physics'}
{1, 2, 3, 4, 5}
{'u', 'a', 'o', 'n', 'r', 's', 'T', 'P', 'i', 't', 'l'}

Example 3

集合是一个不同对象的集合。即使您在集合中重复一个对象,也只会保留一个副本。

s2 = {1, 2, 3, 4, 5, 3,0, 1, 9}
s3 = {"a", "b", "c", "d", "b", "e", "a"}
print (s2)
print (s3)

它将生成以下 output

{0, 1, 2, 3, 4, 5, 9}
{'a', 'b', 'd', 'c', 'e'}

Example 4

只能使用不可变对象来形成集合对象。允许任何数字类型、字符串和元组,但不能将列表或字典放入集合中。

s1 = {1, 2, [3, 4, 5], 3,0, 1, 9}
print (s1)
s2 = {"Rohan", {"phy":50}}
print (s2)

它将生成以下 output

   s1 = {1, 2, [3, 4, 5], 3,0, 1, 9}
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'
   s2 = {"Rohan", {"phy":50}}
        ^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'dict'

Python 引发 TypeError,并显示消息不可散列的类型 'list' 或 'dict'。散列为不可变项生成一个唯一的数字,从而能够在计算机内存中快速搜索。Python 具有内置的 hash() 函数。列表或字典不支持此函数。

即使集合中未存储可变对象,但集合本身是一个可变对象。Python 有一个特殊运算符用于处理集合,且在集合类中有不同的方法用于对集合对象中的元素执行添加、删除、更新运算。

Python - Access Set Items

由于集合不是序列数据类型,因此其项不能单独访问,因为它们没有位置索引(如列表或元组中的)。集合项也没有用于访问的键(如字典中的)。您只能使用 for 循环遍历集合项。

Example 1

langs = {"C", "C++", "Java", "Python"}
for lang in langs:
   print (lang)

它将生成以下 output

Python
C
C++
Java

Example 2

Python 的成员运算符允许您检查集中是否存在某个特定项目。请看下面的示例 −

langs = {"C", "C++", "Java", "Python"}
print ("PHP" in langs)
print ("Java" in langs)

它将生成以下 output

False
True

Python - Add Set Items

即使一个集合仅包含不可变对象,集合本身也是可变的。我们可以通过以下任何一种方式在其中添加新项目 −

add() Method

集合类中的 add() 方法添加了一个新元素。如果元素已存在集合中,则集合不会发生改变。

Syntax

set.add(obj)

Parameters

  1. obj − 任何不可变类型的对象。

Example

请看以下示例:

lang1 = {"C", "C++", "Java", "Python"}
lang1.add("Golang")
print (lang1)

它将生成以下 output

{'Python', 'C', 'Golang', 'C++', 'Java'}

update() Method

集合类的 update() 方法包含作为参数给出的集合的项。如果其他集合中的元素包含一个或多个已经存在的项,则这些项不会被包含。

Syntax

set.update(obj)

Parameters

  1. obj − 一个集合或一个序列对象(列表,元组,字符串)

Example

以下示例显示了 update() 方法的工作原理 −

lang1 = {"C", "C++", "Java", "Python"}
lang2 = {"PHP", "C#", "Perl"}
lang1.update(lang2)
print (lang1)

它将生成以下 output

{'Python', 'Java', 'C', 'C#', 'PHP', 'Perl', 'C++'}

Example

update() 方法还接受任何序列对象作为参数。这里,一个元组是 update() 方法的参数。

lang1 = {"C", "C++", "Java", "Python"}
lang2 = ("PHP", "C#", "Perl")
lang1.update(lang2)
print (lang1)

它将生成以下 output

{'Java', 'Perl', 'Python', 'C++', 'C#', 'C', 'PHP'}

Example

在此示例中,一个集合是从一个字符串构造的,另一个字符串用作 update() 方法的参数。

set1 = set("Hello")
set1.update("World")
print (set1)

它将生成以下 output

{'H', 'r', 'o', 'd', 'W', 'l', 'e'}

union() Method

集合类的 union() 方法也组合了两个集合中唯一的项,但它返回一个新的集合对象。

Syntax

set.union(obj)

Parameters

  1. obj − 一个集合或一个序列对象(列表,元组,字符串)

Return value

union() 方法返回一个集合对象

Example

以下示例显示了 union() 方法的工作原理 −

lang1 = {"C", "C++", "Java", "Python"}
lang2 = {"PHP", "C#", "Perl"}
lang3 = lang1.union(lang2)
print (lang3)

它将生成以下 output

{'C#', 'Java', 'Perl', 'C++', 'PHP', 'Python', 'C'}

Example

如果一个序列对象被作为参数传递给 union() 方法,Python 会自动将其先转换为一个集合,然后执行并集。

lang1 = {"C", "C++", "Java", "Python"}
lang2 = ["PHP", "C#", "Perl"]
lang3 = lang1.union(lang2)
print (lang3)

它将生成以下 output

{'PHP', 'C#', 'Python', 'C', 'Java', 'C++', 'Perl'}

Example

在此示例中,一个集合是从一个字符串构造的,另一个字符串用作 union() 方法的参数。

set1 = set("Hello")
set2 = set1.union("World")
print (set2)

它将生成以下 output

{'e', 'H', 'r', 'd', 'W', 'o', 'l'}

Python - Remove Set Items

Python 的集合类提供了不同的方法从集合对象中删除一个或多个项。

remove() Method

remove() 方法从集合集中删除给定的项,如果该项在集合中存在。但是,如果该项不存在,则会引发 KeyError。

Syntax

set.remove(obj)

Parameters

  1. obj − 一个不可变对象

Example

lang1 = {"C", "C++", "Java", "Python"}
print ("Set before removing: ", lang1)
lang1.remove("Java")
print ("Set after removing: ", lang1)
lang1.remove("PHP")

它将生成以下 output

Set before removing: {'C', 'C++', 'Python', 'Java'}
Set after removing: {'C', 'C++', 'Python'}
   lang1.remove("PHP")
KeyError: 'PHP'

discard() Method

集合类中的 discard() 方法类似于 remove() 方法。唯一不同的是,即使要删除的对象尚未存在于集合集中,它也不会引发错误。

Syntax

set.discard(obj)

Parameters

  1. obj − 一个不可变对象

Example

lang1 = {"C", "C++", "Java", "Python"}
print ("Set before discarding C++: ", lang1)
lang1.discard("C++")
print ("Set after discarding C++: ", lang1)
print ("Set before discarding PHP: ", lang1)
lang1.discard("PHP")
print ("Set after discarding PHP: ", lang1)

它将生成以下 output

Set before discarding C++: {'Java', 'C++', 'Python', 'C'}
Set after discarding C++: {'Java', 'Python', 'C'}
Set before discarding PHP: {'Java', 'Python', 'C'}
Set after discarding PHP: {'Java', 'Python', 'C'}

pop() Method

set 类中的 pop() 方法从集合中删除一个任意项。被删除的项由该方法返回。从空集合中弹出将导致 KeyError。

Syntax

obj = set.pop()

Return value

pop() 方法返回从集合中删除的对象。

Example

lang1 = {"C", "C++"}
print ("Set before popping: ", lang1)
obj = lang1.pop()
print ("object popped: ", obj)
print ("Set after popping: ", lang1)
obj = lang1.pop()
obj = lang1.pop()

它将生成以下 output

Set before popping: {'C++', 'C'}
object popped: C++
Set after popping: {'C'}
Traceback (most recent call last):
   obj = lang1.pop()
         ^^^^^^^^^^^
KeyError: 'pop from an empty set'

第三次调用 pop() 时,集合为空,因此引发 KeyError。

clear() Method

set 类中的 clear() 方法删除 set 对象中的所有项,留空集合。

Syntax

set.clear()

Example

lang1 = {"C", "C++", "Java", "Python"}
print (lang1)
print ("After clear() method")
lang1.clear()
print (lang1)

它将生成以下 output

{'Java', 'C++', 'Python', 'C'}
After clear() method
set()

difference_update() Method

set 类中的 difference_update() 方法通过删除自身与给定为参数的另一集合的共有项来更新集合。

Syntax

set.difference_update(obj)

Parameters

  1. obj − 一个 set 对象

Example

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
print ("s1 before running difference_update: ", s1)
s1.difference_update(s2)
print ("s1 after running difference_update: ", s1)

它将生成以下 output

s1 before running difference_update: {1, 2, 3, 4, 5}
s1 after running difference_update: {1, 2, 3}
set()

difference() Method

difference() 方法与 difference_update() 方法类似,不过它会返回一个包含两个现有集合差分的新集合对象。

Syntax

set.difference(obj)

Parameters

  1. obj − 一个 set 对象

Return value

difference() 方法返回一个新集合,其中包含移除 obj 中的项目后保留的项目。

Example

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
print ("s1: ", s1, "s2: ", s2)
s3 = s1.difference(s2)
print ("s3 = s1-s2: ", s3)

它将生成以下 output

s1: {1, 2, 3, 4, 5} s2: {4, 5, 6, 7, 8}
s3 = s1-s2: {1, 2, 3}

intersection_update() Method

由于 intersection_update() 方法,集合对象只会保留它本身与此方法作为参数传递的其他集合对象中公有项。

Syntax

set.intersection_update(obj)

Parameters

  1. obj − 一个 set 对象

Return value

intersection_update() 方法会删除非公有项,并仅保留它自身和 obj 中的公有项。

Example

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
print ("s1: ", s1, "s2: ", s2)
s1.intersection_update(s2)
print ("a1 after intersection: ", s1)

它将生成以下 output

s1: {1, 2, 3, 4, 5} s2: {4, 5, 6, 7, 8}
s1 after intersection: {4, 5}

intersection() Method

set 类中的 intersection() 方法与 intersection_update() 方法类似,不过它会返回一个仅包含现有集合中公有项的新集合对象。

Syntax

set.intersection(obj)

Parameters

  1. obj − 一个 set 对象

Return value

intersection() 方法返回一个集合对象,其中仅保留它本身和 obj 中的公有项。

Example

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
print ("s1: ", s1, "s2: ", s2)
s3 = s1.intersection(s2)
print ("s3 = s1 & s2: ", s3)

它将生成以下 output

s1: {1, 2, 3, 4, 5} s2: {4, 5, 6, 7, 8}
s3 = s1 & s2: {4, 5}

symmetric_difference_update() method

两个集合之间的对称差集是所有非公有项的集合,排除了公有元素。symmetric_difference_update() 方法将集合更新为它本身与其作为参数传递的集合之间的对称差集。

Syntax

set.symmetric_difference_update(obj)

Parameters

  1. obj − 一个 set 对象

Example

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
print ("s1: ", s1, "s2: ", s2)
s1.symmetric_difference_update(s2)
print ("s1 after running symmetric difference ", s1)

它将生成以下 output

s1: {1, 2, 3, 4, 5} s2: {4, 5, 6, 7, 8}
s1 after running symmetric difference {1, 2, 3, 6, 7, 8}

symmetric_difference() Method

set 类中的 symmetric_difference() 方法与 symmetric_difference_update() 方法类似,不过它会返回一个新集合对象,其中包含来自两个集合的全部项目,减去公有项目。

Syntax

set.symmetric_difference(obj)

Parameters

  1. obj − 一个 set 对象

Return value

symmetric_difference() 方法返回一个仅包含两个集合对象之间非公有项的新集合。

Example

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
print ("s1: ", s1, "s2: ", s2)
s3 = s1.symmetric_difference(s2)
print ("s1 = s1^s2 ", s3)

它将生成以下 output

s1: {1, 2, 3, 4, 5} s2: {4, 5, 6, 7, 8}
s1 = s1^s2 {1, 2, 3, 6, 7, 8}

Python - Loop Sets

Python 中的集合既不是序列,也不是映射类型类。因此,无法使用索引或键遍历集合中的对象。不过,可以使用 for 循环,遍历集合中的各个项目。

Example 1

以下示例显示如何使用 for 循环遍历集合:

langs = {"C", "C++", "Java", "Python"}
for lang in langs:
   print (lang)

它将生成以下 output

C
Python
C++
Java

Example 2

以下示例显示如何使用 for 循环遍历一个集合中的元素,并使用 add() 方法将 set 类添加到另一个集合中。

s1={1,2,3,4,5}
s2={4,5,6,7,8}
for x in s2:
   s1.add(x)
print (s1)

它将生成以下 output

{1, 2, 3, 4, 5, 6, 7, 8}

Python - Join Sets

在 Python 中,集合是项目的有序集合。这些项目可以是不同的类型。但是,集合中的项目必须是不变对象。这意味着,我们只能在集合中包含数字、字符串和元组,不能包含列表。Python 的 set 类具有不同的规定来联接 set 对象。

Using the "|" Operator

"|" 符号(管道)被定义为并集运算符。它执行 A∪B 操作,并返回 A、B 或两者中的一组项。集合不允许重复项。

s1={1,2,3,4,5}
s2={4,5,6,7,8}
s3 = s1|s2
print (s3)

它将生成以下 output

{1, 2, 3, 4, 5, 6, 7, 8}

Using the union() Method

集合类具有 union() 方法,该方法执行的操作与 | 运算符相同。它返回一个集合对象,其中包含这两个集合中的所有项,并丢弃重复项。

s1={1,2,3,4,5}
s2={4,5,6,7,8}
s3 = s1.union(s2)
print (s3)

Using the update() Method

update() 方法也会连接两个集合,与 union() 方法一样。但是它不会返回一个新的集合对象。相反,它将第二个集合的元素添加到第一个集合中,不允许重复项。

s1={1,2,3,4,5}
s2={4,5,6,7,8}
s1.update(s2)
print (s1)

Using the unpacking Operator

在 Python 中,"*" 符号用作解包运算符。解包运算符在内部将集合中的每个元素分配给一个单独的变量。

s1={1,2,3,4,5}
s2={4,5,6,7,8}
s3 = {*s1, *s2}
print (s3)

Python - Copy Sets

set 类中的 copy() 方法创建 set 对象的浅拷贝。

Syntax

set.copy()

Return Value

copy() 方法返回一个新的集合,它是现有集合的浅拷贝。

Example

lang1 = {"C", "C++", "Java", "Python"}
print ("lang1: ", lang1, "id(lang1): ", id(lang1))
lang2 = lang1.copy()
print ("lang2: ", lang2, "id(lang2): ", id(lang2))
lang1.add("PHP")
print ("After updating lang1")
print ("lang1: ", lang1, "id(lang1): ", id(lang1))
print ("lang2: ", lang2, "id(lang2): ", id(lang2))

Output

lang1: {'Python', 'Java', 'C', 'C++'} id(lang1): 2451578196864
lang2: {'Python', 'Java', 'C', 'C++'} id(lang2): 2451578197312
After updating lang1
lang1: {'Python', 'C', 'C++', 'PHP', 'Java'} id(lang1): 2451578196864
lang2: {'Python', 'Java', 'C', 'C++'} id(lang2): 2451578197312

Python - Set Operators

在数学的集合论中,定义了并集、交集、差集和对称差运算。Python 使用以下运算符来实现这些运算:

Union Operator (|)

两个集合的并集是包含 A 中、B 中或同时在 A 和 B 中的所有元素的一个集合。例如,

{1,2}∪{2,3}={1,2,3}

下图展示了两个集合的并集。

union of two sets

Python 使用 "|" 符号作为并集运算符。以下示例使用 "|" 运算符并返回两个集合的并集。

Example

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
s3 = s1 | s2
print ("Union of s1 and s2: ", s3)

它将生成以下 output

Union of s1 and s2: {1, 2, 3, 4, 5, 6, 7, 8}

Intersection Operator (&)

两个集合 A 和 B 的交集,表示为 A∩B,包含同时在 A 和 B 中的所有元素。例如,

{1,2}∩{2,3}={2}

下图展示了两个集合的交集。

intersection operator

Python 使用 "&" 符号作为交集运算符。以下示例使用 & 运算符并返回两个集合的交集。

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
s3 = s1 & s2
print ("Intersection of s1 and s2: ", s3)

它将生成以下 output

Intersection of s1 and s2: {4, 5}

Difference Operator (-)

差集(减法)定义如下。集合 A-B 包含 A 中但不包含 B 中的元素。例如,

If A={1,2,3} and B={3,5}, then A−B={1,2}

下图说明了两个集合之间的差 -

difference operator

Python 使用 "-" 符号作为差集运算符。

Example

以下示例使用 "-" 运算符并返回两个集合的差集。

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
s3 = s1 - s2
print ("Difference of s1 - s2: ", s3)
s3 = s2 - s1
print ("Difference of s2 - s1: ", s3)

它将生成以下 output

Difference of s1 - s2: {1, 2, 3}
Difference of s2 - s1: {8, 6, 7}

请注意,“s1-s2”与“s2-s1”不同。

Symmetric Difference Operator

A 和 B 的对称差表示为“A Δ B”,定义为

A Δ B = (A − B) ⋃ (B − A)

如果 A = {1, 2, 3, 4, 5, 6, 7, 8} 且 B = {1, 3, 5, 6, 7, 8, 9},则 A Δ B = {2, 4, 9}。

下图说明了两个集合之间的对称差 -

symmetric difference

Python 使用 "^" 符号作为对称差运算符。

Example

以下示例使用 "^" 运算符并返回两个集合的对称差。

s1 = {1,2,3,4,5}
s2 = {4,5,6,7,8}
s3 = s1 - s2
print ("Difference of s1 - s2: ", s3)
s3 = s2 - s1
print ("Difference of s2 - s1: ", s3)
s3 = s1 ^ s2
print ("Symmetric Difference in s1 and s2: ", s3)

它将生成以下 output

Difference of s1 - s2: {1, 2, 3}
Difference of s2 - s1: {8, 6, 7}
Symmetric Difference in s1 and s2: {1, 2, 3, 6, 7, 8}

Python - Set Methods

以下方法在 Python 的 set 类中定义:

Python - Set Exercises

Example 1

使用集合运算查找两个列表中共同元素的 Python 程序:

l1=[1,2,3,4,5]
l2=[4,5,6,7,8]
s1=set(l1)
s2=set(l2)
commons = s1&s2 # or s1.intersection(s2)
commonlist = list(commons)
print (commonlist)

它将生成以下 output

[4, 5]

Example 2

检查一个集合是否是另一个集合子集的 Python 程序:

s1={1,2,3,4,5}
s2={4,5}
if s2.issubset(s1):
   print ("s2 is a subset of s1")
else:
   print ("s2 is not a subset of s1")

它将生成以下 output

s2 is a subset of s1

Example 3

获取列表中唯一元素列表的 Python 程序:

T1 = (1, 9, 1, 6, 3, 4, 5, 1, 1, 2, 5, 6, 7, 8, 9, 2)
s1 = set(T1)
print (s1)

它将生成以下 output

{1, 2, 3, 4, 5, 6, 7, 8, 9}

Exercise Programs

  1. 查找 set 对象大小的 Python 程序。

  2. 将集合根据奇数/偶数拆分为两个集合的 Python 程序。

  3. 从集合中删除所有负数的 Python 程序。

  4. Python 程序,用集合中的每个数字的绝对值来构建另一个集合。

  5. Python 程序,用于从集合中移除元素类型不同的所有字符串。

Python - Dictionaries

字典是 Python 中的一种内置数据类型。Python 的字典是映射类型的示例。映射对象将一个对象的 "值" 与另一个对象 "映射"。

在语言字典中,我们有成对的单词及其相应的含义。一对中的两个部分是键(单词)和值(含义)。同样,Python 字典也是键值对的集合。这些键值对由逗号分隔,并置于花括号 {} 内。

为了建立键和值之间的映射,两个键之间放置冒号 ":" 符号。

以下是一些 Python 字典对象示例 -

capitals = {"Maharashtra":"Mumbai", "Gujarat":"Gandhinagar", "Telangana":"Hyderabad", "Karnataka":"Bengaluru"}
numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}

Example 1

只能使用数字、字符串或元组作为键。所有这些都是不可变的。可以使用任何类型的对象作为值。因此,词典的以下定义也是有效的 −

d1 = {"Fruit":["Mango","Banana"], "Flower":["Rose", "Lotus"]}
d2 = {('India, USA'):'Countries', ('New Delhi', 'New York'):'Capitals'}
print (d1)
print (d2)

它将生成以下 output

{'Fruit': ['Mango', 'Banana'], 'Flower': ['Rose', 'Lotus']}
{'India, USA': 'Countries', ('New Delhi', 'New York'): 'Capitals'}

Example 2

Python 不接受可变对象,如列表作为键,并引发 TypeError

d1 = {["Mango","Banana"]:"Fruit", "Flower":["Rose", "Lotus"]}
print (d1)

它将引发 TypeError

Traceback (most recent call last):
   File "C:\Users\Sairam\PycharmProjects\pythonProject\main.py", line 8, in <module>
d1 = {["Mango","Banana"]:"Fruit", "Flower":["Rose", "Lotus"]}
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'

Example 3

可以在词典中为多个键分配一个值,但一个键在词典中不能出现多次。

d1 = {"Banana":"Fruit", "Rose":"Flower", "Lotus":"Flower", "Mango":"Fruit"}
d2 = {"Fruit":"Banana","Flower":"Rose", "Fruit":"Mango", "Flower":"Lotus"}
print (d1)
print (d2)

它将生成以下 output

{'Banana': 'Fruit', 'Rose': 'Flower', 'Lotus': 'Flower', 'Mango': 'Fruit'}
{'Fruit': 'Mango', 'Flower': 'Lotus'}

Python Dictionary Operators

在 Python 中,定义了以下运算符与字典操作数一起使用。在这个示例中,使用了以下词典对象。

d1 = {'a': 2, 'b': 4, 'c': 30}
d2 = {'a1': 20, 'b1': 40, 'c1': 60}

Python - Access Dictionary Items

Using the "[ ]" Operator

Python 中的字典不是序列,因为字典中的元素没有索引。但是,你仍可以使用方括号 "[ ]" 运算符来获取字典对象中与某个键关联的值。

Example 1

capitals = {"Maharashtra":"Mumbai", "Gujarat":"Gandhinagar", "Telangana":"Hyderabad", "Karnataka":"Bengaluru"}
print ("Capital of Gujarat is : ", capitals['Gujarat'])
print ("Capital of Karnataka is : ", capitals['Karnataka'])

它将生成以下 output

Capital of Gujarat is: Gandhinagar
Capital of Karnataka is: Bengaluru

Example 2

如果方括号中给出的键在字典对象中不存在,Python 会引发 KeyError。

capitals = {"Maharashtra":"Mumbai", "Gujarat":"Gandhinagar", "Telangana":"Hyderabad", "Karnataka":"Bengaluru"}
print ("Captial of Haryana is : ", capitals['Haryana'])

它将生成以下 output

   print ("Captial of Haryana is : ", capitals['Haryana'])
                                      ~~~~~~~~^^^^^^^^^^^
KeyError: 'Haryana'

Using the get() Method

Python 的 dict 类中的 get() 方法返回映射到给定键的值。

Syntax

Val = dict.get("key")

Parameters

  1. key - 用作字典对象中键的不变对象

Return Value

get() 方法返回与给定键映射的对象。

Example 3

capitals = {"Maharashtra":"Mumbai", "Gujarat":"Gandhinagar", "Telangana":"Hyderabad", "Karnataka":"Bengaluru"}
print ("Capital of Gujarat is: ", capitals.get('Gujarat'))
print ("Capital of Karnataka is: ", capitals.get('Karnataka'))

它将生成以下 output

Capital of Gujarat is: Gandhinagar
Capital of Karnataka is: Bengaluru

Example 4

与 "[]" 运算符不同,get() 方法在找不到键时不会引发错误;它会返回 None。

capitals = {"Maharashtra":"Mumbai", "Gujarat":"Gandhinagar", "Telangana":"Hyderabad", "Karnataka":"Bengaluru"}
print ("Capital of Haryana is : ", capitals.get('Haryana'))

它将生成以下 output

Capital of Haryana is : None

Example 5

get() 方法接受一个可选的字符串参数。如果给出了这个参数,并且找不到键,这个字符串就会成为返回值。

capitals = {"Maharashtra":"Mumbai", "Gujarat":"Gandhinagar", "Telangana":"Hyderabad", "Karnataka":"Bengaluru"}
print ("Capital of Haryana is : ", capitals.get('Haryana', 'Not found'))

它将生成以下 output

Capital of Haryana is: Not found

Python - Change Dictionary Items

除了用花括号表示字典的每个用逗号分隔的键值对的文字表示形式之外,我们还可以使用内置的 dict() 函数来创建字典对象。

Empty Dictionary

在不带任何参数的情况下使用 dict() 函数会创建一个空字典对象。这相当于在花括号中不放置任何内容。

Example

d1 = dict()
d2 = {}
print ('d1: ', d1)
print ('d2: ', d2)

它将生成以下 output

d1: {}
d2: {}

Dictionary from List of Tuples

dict() 函数从包含双项元组的列表或元组中构造一个字典。元组中的第一个项被视为键,第二个项被视为其值。

Example

d1=dict([('a', 100), ('b', 200)])
d2 = dict((('a', 'one'), ('b', 'two')))
print ('d1: ', d1)
print ('d2: ', d2)

它将生成以下 output

d1: {'a': 100, 'b': 200}
d2: {'a': 'one', 'b': 'two'}

Dictionary from Keyword Arguments

dict() 函数可以接受任意数量带有 name=value 对的关键字参数。它返回一个字典对象,其中 name 作为键,并将其与 value 相关联。

Example

d1=dict(a= 100, b=200)
d2 = dict(a='one', b='two')
print ('d1: ', d1)
print ('d2: ', d2)

它将生成以下 output

d1: {'a': 100, 'b': 200}
d2: {'a': 'one', 'b': 'two'}

Python - Add Dictionary Items

Using the Operator

"[]" 运算符(用于访问映射到字典键的值)用于更新现有的键值对,以及添加新的键值对。

Syntax

dict["key"] = val

如果键已经存在于字典对象中,则其值将更新为 val。如果键不存在于字典中,则将添加一个新的键值对。

Example

在此示例中,"Laxman" 的成绩更新为 95。

marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}
print ("marks dictionary before update: ", marks)
marks['Laxman'] = 95
print ("marks dictionary after update: ", marks)

它将生成以下 output

marks dictionary before update: {'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49}
marks dictionary after update: {'Savita': 67, 'Imtiaz': 88, 'Laxman': 95, 'David': 49}

Example

但是,字典中没有键为“Krishnan”的项目,因此添加了新的键值对。

marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}
print ("marks dictionary before update: ", marks)
marks['Krishan'] = 74
print ("marks dictionary after update: ", marks)

它将生成以下 output

marks dictionary before update: {'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49}
marks dictionary after update: {'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49, 'Krishan': 74}

Using the update() Method

在 dict 类中,你可以用三种不同的方式使用 update() 方法:

Update with Another Dictionary

在这个情形中,update() 方法的参数是另一个字典。在两个字典中通用的键的值将更新。对于新键,键值对将添加到现有字典中。

Syntax

d1.update(d2)

Return value

使用新键值对更新现有字典,并将其添加到现有字典中。

Example

marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}
print ("marks dictionary before update: \n", marks)
marks1 = {"Sharad": 51, "Mushtaq": 61, "Laxman": 89}
marks.update(marks1)
print ("marks dictionary after update: \n", marks)

它将生成以下 output

marks dictionary before update:
{'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49}
marks dictionary after update:
{'Savita': 67, 'Imtiaz': 88, 'Laxman': 89, 'David': 49, 'Sharad': 51, 'Mushtaq': 61}

Update with Iterable

如果传递给 update() 方法的参数是两项元组组成的列表或元组,则会向现有字典中添加每个项目,或在键已存在的情况下更新键。

Syntax

d1.update([(k1, v1), (k2, v2)])

Return value

使用新键更新现有字典。

Example

marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}
print ("marks dictionary before update: \n", marks)
marks1 = [("Sharad", 51), ("Mushtaq", 61), ("Laxman", 89)]
marks.update(marks1)
print ("marks dictionary after update: \n", marks)

它将生成以下 output

marks dictionary before update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49}
marks dictionary after update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 89, 'David': 49, 'Sharad': 51, 'Mushtaq': 61}

Update with Keyword Arguments

update() 方法的第三个版本接受 name=value 格式的关键字参数列表。添加新键值对,或更新现有键的值。

Syntax

d1.update(k1=v1, k2=v2)

Return value

使用新键值对更新现有字典。

Example

marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}
print ("marks dictionary before update: \n", marks)
marks.update(Sharad = 51, Mushtaq = 61, Laxman = 89)
print ("marks dictionary after update: \n", marks)

它将生成以下 output

marks dictionary before update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49}
marks dictionary after update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 89, 'David': 49, 'Sharad': 51, 'Mushtaq': 61}

Using the Unpack Operator

*" symbol prefixed to a dictionary object unpacks it to a list of tuples, each tuple with key and value. Two *dict ”对象会被解压缩并合并在一起,得到一个新的字典。

Syntax

d3 = {**d1, **d2}

Return value

合并两个字典,返回一个新对象。

Example

marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}
print ("marks dictionary before update: \n", marks)
marks1 = {"Sharad": 51, "Mushtaq": 61, "Laxman": 89}
newmarks = {**marks, **marks1}
print ("marks dictionary after update: \n", newmarks)

它将生成以下 output

marks dictionary before update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49}
marks dictionary after update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 89, 'David': 49, 'Sharad': 51, 'Mushtaq': 61}

Using the Union Operator (|)

Python 引入了 “|”(管道符号)作为字典操作数的并集运算符。它更新了左侧字典对象中的现有键,并添加新的键值对以返回一个新的字典对象。

Syntax

d3 = d1 | d2

Return value

并集运算符在合并两个字典操作数后返回一个新的字典对象。

Example

marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}
print ("marks dictionary before update: \n", marks)
marks1 = {"Sharad": 51, "Mushtaq": 61, "Laxman": 89}
newmarks = marks | marks1
print ("marks dictionary after update: \n", newmarks)

它将生成以下 output

marks dictionary before update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49}
marks dictionary after update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 89, 'David': 49, 'Sharad': 51, 'Mushtaq': 61}

Using "|=" Operator

“|=”运算符是一个增强型并集运算符。它通过添加右侧操作数中的新键,以及更新现有键,对左侧的字典操作数执行就地更新。

Syntax

d1 |= d2

Example

marks = {"Savita":67, "Imtiaz":88, "Laxman":91, "David":49}
print ("marks dictionary before update: \n", marks)
marks1 = {"Sharad": 51, "Mushtaq": 61, "Laxman": 89}
marks |= marks1
print ("marks dictionary after update: \n", marks)

它将生成以下 output

marks dictionary before update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 91, 'David': 49}
marks dictionary after update:
 {'Savita': 67, 'Imtiaz': 88, 'Laxman': 89, 'David': 49, 'Sharad': 51, 'Mushtaq': 61}

Python - Remove Dictionary Items

Using del Keyword

Python 的 del 关键字从内存中删除任何对象。这里我们用它删除字典中的键值对。

Syntax

del dict['key']

Example

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
print ("numbers dictionary before delete operation: \n", numbers)
del numbers[20]
print ("numbers dictionary before delete operation: \n", numbers)

它将生成以下 output

numbers dictionary before delete operation:
 {10: 'Ten', 20: 'Twenty', 30: 'Thirty', 40: 'Forty'}
numbers dictionary before delete operation:
 {10: 'Ten', 30: 'Thirty', 40: 'Forty'}

Example

使用 dict 对象本身的 del 关键字将其从内存中删除。

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
print ("numbers dictionary before delete operation: \n", numbers)
del numbers
print ("numbers dictionary before delete operation: \n", numbers)

它将生成以下 output

numbers dictionary before delete operation:
 {10: 'Ten', 20: 'Twenty', 30: 'Thirty', 40: 'Forty'}
Traceback (most recent call last):
 File "C:\Users\mlath\examples\main.py", line 5, in <module>
  print ("numbers dictionary before delete operation: \n", numbers)
                                                           ^^^^^^^
NameError: name 'numbers' is not defined

Using pop() Method

dict 类的 pop() 方法导致具有指定键的元素从字典中删除。

Syntax

val = dict.pop(key)

Return value

pop() 方法在删除键值对后返回指定键的值。

Example

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
print ("numbers dictionary before pop operation: \n", numbers)
val = numbers.pop(20)
print ("nubvers dictionary after pop operation: \n", numbers)
print ("Value popped: ", val)

它将生成以下 output

numbers dictionary before pop operation:
 {10: 'Ten', 20: 'Twenty', 30: 'Thirty', 40: 'Forty'}
nubvers dictionary after pop operation:
 {10: 'Ten', 30: 'Thirty', 40: 'Forty'}
Value popped:  Twenty

Using popitem() Method

dict() 类中的 popitem() 方法不接受任何参数。它弹出最后插入的键值对,并将其作为元组返回。

Syntax

val = dict.popitem()

Return Value

popitem() 方法返回一个元组,其中包含从字典中删除的项目的键和值。

Example

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
print ("numbers dictionary before pop operation: \n", numbers)
val = numbers.popitem()
print ("numbers dictionary after pop operation: \n", numbers)
print ("Value popped: ", val)

它将生成以下 output

numbers dictionary before pop operation:
 {10: 'Ten', 20: 'Twenty', 30: 'Thirty', 40: 'Forty'}
numbers dictionary after pop operation:
 {10: 'Ten', 20: 'Twenty', 30: 'Thirty'}
Value popped:  (40, 'Forty')

Using clear() Method

dict 类中的 clear() 方法从字典对象中移除所有元素并返回一个空对象。

Syntax

dict.clear()

Example

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
print ("numbers dictionary before clear method: \n", numbers)
numbers.clear()
print ("numbers dictionary after clear method: \n", numbers)

它将生成以下 output

numbers dictionary before clear method:
 {10: 'Ten', 20: 'Twenty', 30: 'Thirty', 40: 'Forty'}
numbers dictionary after clear method:
 {}

Python - Dictionary View Objects

dict 类的 items()、keys() 和 values() 方法返回视图对象。每当它们的源字典对象的内容发生更改时,这些视图都会动态刷新。

items() Method

items() 方法返回一个 dict_items 视图对象。它包含元组列表,每个元组由各个键值对组成。

Syntax

Obj = dict.items()

Return value

items() 方法返回 dict_items 对象,它是 (key,value) 元组的动态视图。

Example

在以下示例中,我们首先使用 items() 方法获取 dict_items() 对象,并查看字典对象更新后它是如何动态更新的。

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
obj = numbers.items()
print ('type of obj: ', type(obj))
print (obj)
print ("update numbers dictionary")
numbers.update({50:"Fifty"})
print ("View automatically updated")
print (obj)

它将生成以下 output

type of obj: <class 'dict_items'>
dict_items([(10, 'Ten'), (20, 'Twenty'), (30, 'Thirty'), (40, 'Forty')])
update numbers dictionary
View automatically updated
dict_items([(10, 'Ten'), (20, 'Twenty'), (30, 'Thirty'), (40, 'Forty'), (50, 'Fifty')])

keys() Method

dict 类的 keys() 方法返回 dict_keys 对象,该对象是字典中定义的所有键的列表。它是一个视图对象,因为每当对字典对象执行任何更新操作时,它都会自动更新。

Syntax

Obj = dict.keys()

Return value

keys() 方法返回 dict_keys 对象,它是字典中键的视图。

Example

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
obj = numbers.keys()
print ('type of obj: ', type(obj))
print (obj)
print ("update numbers dictionary")
numbers.update({50:"Fifty"})
print ("View automatically updated")
print (obj)

它将生成以下 output

type of obj: <class 'dict_keys'>
dict_keys([10, 20, 30, 40])
update numbers dictionary
View automatically updated
dict_keys([10, 20, 30, 40, 50])

values() Method

values() 方法返回字典中存在的所有值的视图。该对象为 dict_value 类型,可自动更新。

Syntax

Obj = dict.values()

Return value

values() 方法返回一个 dict_values 视图,该视图包含字典中存在的全部值。

Example

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
obj = numbers.values()
print ('type of obj: ', type(obj))
print (obj)
print ("update numbers dictionary")
numbers.update({50:"Fifty"})
print ("View automatically updated")
print (obj)

它将生成以下 output

type of obj: <class 'dict_values'>
dict_values(['Ten', 'Twenty', 'Thirty', 'Forty'])
update numbers dictionary
View automatically updated
dict_values(['Ten', 'Twenty', 'Thirty', 'Forty', 'Fifty'])

Python - Loop Dictionaries

与列表、元祖或字符串不同,Python 中的字典数据类型不是序列,因为项目没有索引值。但是,仍然可以使用不同的技术遍历字典。

Example 1

对字典对象运行一个简单的 for 可以遍历其中使用的键。

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x in numbers:
   print (x)

它将生成以下 output

10
20
30
40

Example 2

一旦我们能够获取密钥,便可以通过使用方括号运算符或 get() 方法轻松地访问其关联的值。

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x in numbers:
   print (x,":",numbers[x])

它将生成以下 output

10 : Ten
20 : Twenty
30 : Thirty
40 : Forty

dict 类的 items()、keys() 和 values() 方法分别返回视图对象 dict_items、dict_keys 和 dict_values。这些对象是迭代器,因此我们可以使用 for 循环来遍历它们。

Example 3

dict_items 对象是可以在其上运行 for 循环的键值元组列表,如下所示:

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x in numbers.items():
   print (x)

它将生成以下 output

(10, 'Ten')
(20, 'Twenty')
(30, 'Thirty')
(40, 'Forty')

此处,“x”是 dict_items 迭代器中的元组元素。我们可以在两个不同的变量中进一步解构此元组。

Example 4

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x,y in numbers.items():
   print (x,":", y)

它将生成以下 output

10 : Ten
20 : Twenty
30 : Thirty
40 : Forty

Example 5

类似地,可以迭代 dict_keys 对象中的键集合。

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
for x in numbers.keys():
   print (x, ":", numbers[x])

dict_keys 和 dict_values 中的各自键和值位于同一索引中。在以下示例中,我们有一个从 0 到 dict 长度的 for 循环,并使用循环变量作为索引并打印键及其对应值。

Example 6

numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
l = len(numbers)
for x in range(l):
   print (list(numbers.keys())[x], ":", list(numbers.values())[x])

以上两个代码段生成相同的 output

10 : Ten
20 : Twenty
30 : Thirty
40 : Forty

Python - Copy Dictionaries

由于 Python 中的变量只是对内存中对象的标签或引用,因此简单的赋值运算符不会创建对象的副本。

Example 1

在此示例中,我们有一个字典 “d1”,我们将其赋值给另一个变量 “d2”。如果更新 “d1”,这些更改也会反映在 “d2” 中。

d1 = {"a":11, "b":22, "c":33}
d2 = d1
print ("id:", id(d1), "dict: ",d1)
print ("id:", id(d2), "dict: ",d2)

d1["b"] = 100
print ("id:", id(d1), "dict: ",d1)
print ("id:", id(d2), "dict: ",d2)

Output

id: 2215278891200 dict: {'a': 11, 'b': 22, 'c': 33}
id: 2215278891200 dict: {'a': 11, 'b': 22, 'c': 33}
id: 2215278891200 dict: {'a': 11, 'b': 100, 'c': 33}
id: 2215278891200 dict: {'a': 11, 'b': 100, 'c': 33}

为避免这种情况并创建字典的浅拷贝,请使用 copy() 方法代替赋值。

Example 2

d1 = {"a":11, "b":22, "c":33}
d2 = d1.copy()
print ("id:", id(d1), "dict: ",d1)
print ("id:", id(d2), "dict: ",d2)
d1["b"] = 100
print ("id:", id(d1), "dict: ",d1)
print ("id:", id(d2), "dict: ",d2)

Output

当“d1”更新时,“d2”现在不会更改,因为“d2”是字典对象的副本,而不仅仅是一个引用。

id: 1586671734976 dict: {'a': 11, 'b': 22, 'c': 33}
id: 1586673973632 dict: {'a': 11, 'b': 22, 'c': 33}
id: 1586671734976 dict: {'a': 11, 'b': 100, 'c': 33}
id: 1586673973632 dict: {'a': 11, 'b': 22, 'c': 33}

Python - Nested Dictionaries

如果一个或多个键的值是另一个字典,则 Python 字典被称为具有嵌套结构。嵌套字典通常用于存储复杂的数据结构。

以下代码段表示嵌套字典:

marklist = {
   "Mahesh" : {"Phy" : 60, "maths" : 70},
   "Madhavi" : {"phy" : 75, "maths" : 68},
   "Mitchell" : {"phy" : 67, "maths" : 71}
}

Example 1

您还可以构成一个 for 循环来遍历嵌套字典,如同前一节所述。

marklist = {
   "Mahesh" : {"Phy" : 60, "maths" : 70},
   "Madhavi" : {"phy" : 75, "maths" : 68},
   "Mitchell" : {"phy" : 67, "maths" : 71}
}
for k,v in marklist.items():
   print (k, ":", v)

它将生成以下 output

Mahesh : {'Phy': 60, 'maths': 70}
Madhavi : {'phy': 75, 'maths': 68}
Mitchell : {'phy': 67, 'maths': 71}

Example 2

可以使用 [] 符号或 get()方法从内部字典访问值。

print (marklist.get("Madhavi")['maths'])
obj=marklist['Mahesh']
print (obj.get('Phy'))
print (marklist['Mitchell'].get('maths'))

它将生成以下 output

68
60
71

Python - Dictionary Methods

Python 中的字典是内置 dict 类的对象,该类定义了以下方法: -

Python - Dictionary Exercises

Example 1

Python 程序通过从给定的字典中提取键来创建一个新字典。

d1 = {"one":11, "two":22, "three":33, "four":44, "five":55}
keys = ['two', 'five']
d2={}
for k in keys:
   d2[k]=d1[k]
print (d2)

它将生成以下 output

{'two': 22, 'five': 55}

Example 2

Python 程序将字典转换为 (k,v) 元组列表。

d1 = {"one":11, "two":22, "three":33, "four":44, "five":55}
L1 = list(d1.items())
print (L1)

它将生成以下 output

[('one', 11), ('two', 22), ('three', 33), ('four', 44), ('five', 55)]

Example 3

Python 程序将具有相同值的键从字典中删除。

d1 = {"one":"eleven", "2":2, "three":3, "11":"eleven", "four":44, "two":2}
vals = list(d1.values())#all values
uvals = [v for v in vals if vals.count(v)==1]#unique values
d2 = {}
for k,v in d1.items():
   if v in uvals:
      d = {k:v}
      d2.update(d)
print ("dict with unique value:",d2)

它将生成以下 output

dict with unique value: {'three': 3, 'four': 44}

Exercise Programs

  1. Python 程序通过值对字典列表进行排序。

  2. Python 程序从给定的字典中提取具有非数字值的各个键的字典。

  3. Python 程序通过列出两个项目 (k,v) 元组来构建字典。

  4. Python 程序使用解包运算符合并两个字典对象。

Python - Arrays

Python 的标准数据类型 list, tuplestring 是序列。序列对象是有序的项目集合。每个项目都以从零开始的递增索引来表征。此外,序列中的项目不必具有相同的类型。换句话说,一个列表或元组可能包含不同数据类型的项目。

此功能不同于 C 或 C 中的数组概念。在 C/C 中,数组也是项目的索引集合,但这些项目必须具有相似的数据类型。在 C/C 中,您有一个整数或浮点数或字符串的数组,但是您不能拥有具有某些整数类型元素和某些不同类型元素的数组。因此,C/C 数组是数据类型的一个同构集合。

Python 的标准库包含数组模块。其中的数组类允许您构建一个三种基本类型(整数、浮点数和 Unicode 字符)的数组。

Syntax

创建数组的语法为: -

import array
obj = array.array(typecode[, initializer])

Parameters

  1. typecode - 用于创建数组的类型码字符。

  2. initializer - 从可选值初始化的数组,该值必须是列表、字节状对象或通过适当类型的元素进行迭代。

Return type

array() 构造函数返回 array.array 类的对象。

Example

import array as arr

# creating an array with integer type
a = arr.array('i', [1, 2, 3])
print (type(a), a)

# creating an array with char type
a = arr.array('u', 'BAT')
print (type(a), a)

# creating an array with float type
a = arr.array('d', [1.1, 2.2, 3.3])
print (type(a), a)

它将生成以下 output

<class 'array.array'> array('i', [1, 2, 3])
<class 'array.array'> array('u', 'BAT')
<class 'array.array'> array('d', [1.1, 2.2, 3.3])

数组是序列类型并且非常类似于列表,只不过它们存储的对象类型受到限制。

Python 数组类型由单个字符类型代码参数决定。类型代码和数组的目标数据类型如下所列: -

Python - Access Array Items

由于数组对象的行为非常类似于一个序列,你可以对其执行索引和切片操作。

Example

import array as arr
a = arr.array('i', [1, 2, 3])
#indexing
print (a[1])
#slicing
print (a[1:])

Changing Array Items

你可以向数组中的一个条目分配值,就像你向列表中的条目分配值一样。

Example

import array as arr
a = arr.array('i', [1, 2, 3])
a[1] = 20
print (a[1])

在这里,你会得到“20”作为输出。但是,Python不允许分配与创建数组时所用的类型代码类型不同的其他类型的值。下面的赋值会引发TypeError。

import array as arr
a = arr.array('i', [1, 2, 3])
# assignment
a[1] = 'A'

它将生成以下 output

TypeError: 'str' object cannot be interpreted as an integer

Python - Add Array Items

The append() Method

append()方法会在给定数组的末尾添加一个新元素。

Syntax

array.append(v)

Parameters

  1. v −新值会被添加到数组的末尾。新值必须与在声明数组对象时所用的数据类型参数类型相同。

Example

import array as arr
a = arr.array('i', [1, 2, 3])
a.append(10)
print (a)

它将生成以下 output

array('i', [1, 2, 3, 10])

The insert() Method

数组类还定义了insert()方法。可以在指定索引处插入一个新元素。

Syntax

array.insert(i, v)

Parameters

  1. i −要插入新值处的索引。

  2. v −要插入的值。必须是arraytype类型的。

Example

import array as arr
a = arr.array('i', [1, 2, 3])
a.insert(1,20)
print (a)

它将生成以下 output

array('i', [1, 20, 2, 3])

The extend() Method

数组类中的extend()方法可追加来自具有相同类型代码的其他数组的所有元素。

Syntax

array.extend(x)

Parameters

  1. x −array.array类的对象

Example

import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
b = arr.array('i', [6,7,8,9,10])
a.extend(b)
print (a)

它将生成以下 output

array('i', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

Python - Remove Array Items

数组类定义了两个方法,借助它们我们可以从数组中移除一个元素。它有remove()和pop()方法。

array.remove() Method

remove()方法会移除数组中的某个给定值第一次出现的位置

Syntax

array.remove(v)

Parameters

  1. v −要从数组中移除的值

Example

import array as arr
a = arr.array('i', [1, 2, 1, 4, 2])
a.remove(2)
print (a)

它将生成以下 output

array('i', [1, 1, 4, 2])

array.pop() Method

pop()方法会移除数组中指定索引处的某个元素,并返回已移除的元素。

Syntax

array.pop(i)

Parameters

  1. i −要移除元素的索引。该方法会在移除后返回i位置的元素。

Example

import array as arr
a = arr.array('i', [1, 2, 1, 4, 2])
a.pop(2)
print (a)

它将生成以下 output

array('i', [1, 2, 4, 2])

Python - Loop Arrays

由于数组对象的行为类似于一个序列,你可以借助 for 循环或 while 循环遍历它的元素。

"for" Loop with Array

请看以下示例:

import array as arr
a = arr.array('d', [1, 2, 3])
for x in a:
   print (x)

它将生成以下 output

1.0
2.0
3.0

"while L oop with Array

下面的示例演示了如何使用 while 循环遍历数组−

import array as arr
a = arr.array('d', [1, 2, 3])
l = len(a)
idx =0
while idx<l:
   print (a[idx])
   idx+=1

"for Loop with Array I ndex

我们可以使用内置的len()函数查找数组的长度。使用它创建一个范围对象以获取一系列索引,然后在 for 循环中访问数组元素。

import array as arr
a = arr.array('d', [1, 2, 3])
l = len(a)
for x in range(l):
   print (a[x])

你将得到与第一个示例中相同的结果。

Python - Copy Arrays

Python 的内置序列类型,即列表、元组和字符串,是项目索引的集合。但是,与 C/C++、Java 等语言中的数组不像,它们不是同构的,也就是说,其中的元素可以是不同类型的。Python 的数组模块可以帮助你创建类似于 Java 数组的对象。在本章中,我们将讨论如何将一个数组对象复制到另一个数组对象。

Python 数组可以是字符串、整数或浮点型。数组类构造函数的用法如下 −

import array
obj = array.array(typecode[, initializer])

类型代码可以是一个表示数据类型的字符常量。

我们可以使用赋值运算符将一个数组赋值给另一个数组。

a = arr.array('i', [1, 2, 3, 4, 5])
b=a.copy()

但是,此类赋值不会在内存中创建一个新的数组。在 Python 中,变量只是对内存中对象的标注或引用。因此,a 是对一个数组的引用,b 也是。检查 a 和 b 的 id()。相同的 id 值确认简单的赋值不会创建副本

import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
b=a
print (id(a), id(b))

它将生成以下 output

2771967068656 2771967068656

由于 "a" 和 "b" 引用的是同一个数组对象,所以 "a" 的任何变更都会反映到 "b" 中 −

a[2]=10
print (a,b)

它将生成以下 output

array('i', [1, 2, 10, 4, 5]) array('i', [1, 2, 10, 4, 5])

若要创建数组的另一个物理副本,我们将使用 Python 库中的另一个模块,名为 copy,并使用该模块中的 deepcopy() 函数。深度复制会构建一个新的复合对象,然后将原始对象中找到的对象的副本递归插入到这个复合对象中。

import array, copy
a = arr.array('i', [1, 2, 3, 4, 5])
import copy
b = copy.deepcopy(a)

现在检查 "a" 和 "b" 的 id()。你会发现 id 是不同的。

print (id(a), id(b))

它将生成以下 output

2771967069936 2771967068976

这证明创建了一个新对象 "b",它实际上是 "a" 的副本。如果我们在 "a" 中更改一个元素,它不会反映在 "b" 中。

a[2]=10
print (a,b)

它将生成以下 output

array('i', [1, 2, 10, 4, 5]) array('i', [1, 2, 3, 4, 5])

Python - Reverse Arrays

在本章中,我们将探讨以相反索引顺序重新排列给定数组的不同方法。在 Python 中,数组不是内置数据类型之一。但是,Python 的标准库有一个数组模块。array 类可以帮助我们创建字符串、整数或浮点类型的同构集合。

用于创建数组的 syntax 为 −

import array
obj = array.array(typecode[, initializer])

我们首先创建一个包含 int 类型几个对象的数组 −

import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])

数组类没有用于颠倒数组的任何内置方法。因此,我们必须使用另一个数组。空数组 "b" 声明如下 −

b = arr.array('i')

接下来,我们以相反的顺序遍历数组 "a" 中的数字,并将每个元素附加到 "b" 数组 −

for i in range(len(a)-1, -1, -1):
b.append(a[i])

现在,“b”数组以相反的顺序包含原始数组中的数字。

Example 1

以下 complete code 在 Python 中颠倒数组 −

import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
b = arr.array('i')
for i in range(len(a)-1, -1, -1):
   b.append(a[i])
print (a, b)

它将生成以下 output

array('i', [10, 5, 15, 4, 6, 20, 9]) array('i', [9, 20, 6, 4, 15, 5, 10])

我们还可以使用列表类的 reverse() 方法颠倒数组中数字的顺序。列表是 Python 中的内置类型。

我们必须先将数组的内容使用 array 类的 tolist() 方法传输到列表中 −

a = arr.array('i', [10,5,15,4,6,20,9])
b = a.tolist()

我们现在可以调用 reverse() 方法 −

b.reverse()

如果我们现在将列表转换为数组,我们就得到一个顺序相反的数组,

a = arr.array('i')
a.fromlist(b)

Example 2

这是 complete code

from array import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
b = a.tolist()
b.reverse()
a = arr.array('i')
a.fromlist(b)
print (a)

它将生成以下 output

array('i', [10, 5, 15, 4, 6, 20, 9])

Python - Sort Arrays

Python 的数组模块定义了数组类。数组类的对象类似于 Java 或 C/C++ 中存在的数组。不同于 Python 内置序列,数组是字符串、整数或浮点对象的自同集合。

数组类没有任何函数/方法来对它的元素进行排序的排列。然而,我们可以运用下列方法之一来实现它 −

  1. Using a sorting algorithm

  2. 使用列表的 sort() 方法

  3. 使用内置的 sorted() 函数

我们逐一详细讨论这些方法。

Using a Sorting Algorithm

我们将实现经典的 bubble sort algorithm 来获得排序数组。为此,我们使用两个嵌套循环并交换元素以重新排列成排序顺序。

使用 Python 代码编辑器保存以下代码 −

import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
for i in range(0, len(a)):
   for j in range(i+1, len(a)):
      if(a[i] > a[j]):
         temp = a[i];
         a[i] = a[j];
         a[j] = temp;
print (a)

它将生成以下 output

array('i', [4, 5, 6, 9, 10, 15, 20])

Using the sort() Method from List

即使数组没有 sort() 方法,Python 的内置列表类也有一个排序方法。我们将在下一个示例中使用它。

首先,声明一个数组并使用 tolist() 方法从中获取一个列表对象 −

a = arr.array('i', [10,5,15,4,6,20,9])
b=a.tolist()

我们可以轻松地获取排序列表,如下所示 −

b.sort()

我们只需要将此列表重新转换为一个数组对象 −

a.fromlist(b)

这是 complete code

from array import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
b=a.tolist()
b.sort()
a = arr.array('i')
a.fromlist(b)
print (a)

它将生成以下 output

array('i', [4, 5, 6, 9, 10, 15, 20])

Using the Builtin sorted() Function

对数组进行排序的第三种技术是使用 sorted() 函数,这是一个内置函数。

sorted() 函数的 syntax 如下 −

sorted(iterable, reverse=False)

该函数返回一个新列表,包含所有元素按升序排序的 iterable 对象。将逆序参数设置为 True,以获取按降序排序的元素。

sorted() 函数可以与任何 iterable 对象一起使用。Python 数组是一个 iterable 对象,因为它是一个索引集合。因此,一个数组可用作 sorted() 函数的参数。

from array import array as arr
a = arr.array('i', [4, 5, 6, 9, 10, 15, 20])
sorted(a)
print (a)

它将生成以下 output

array('i', [4, 5, 6, 9, 10, 15, 20])

Python - Join Arrays

在 Python 中,数组是 Python 内置数据类型的自同集合,例如字符串、整数或浮点对象。但是,数组本身并不是一个内置类型,相反,我们需要在 Python 的内置数组模块中使用数组类。

First Method

要连接两个数组,我们可以将一个数组中的每个项目附加到另一个数组中。

这里有两个 Python 数组 −

a = arr.array('i', [10,5,15,4,6,20,9])
b = arr.array('i', [2,7,8,11,3,10])

在数组 “b” 上运行 for 循环。从 “b” 中获取每个数字,并使用以下循环语句将其附加到数组 “a” −

for i in range(len(b)):
   a.append(b[i])

数组 “a” 现在包含 “a” 和 “b” 中的元素。

这是 complete code

import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
b = arr.array('i', [2,7,8,11,3,10])
for i in range(len(b)):
   a.append(b[i])
print (a, b)

它将生成以下 output

array('i', [10, 5, 15, 4, 6, 20, 9, 2, 7, 8, 11, 3, 10])

Second Method

使用另一种方法连接两个数组,首先将数组转换为列表对象 −

a = arr.array('i', [10,5,15,4,6,20,9])
b = arr.array('i', [2,7,8,11,3,10])
x=a.tolist()
y=b.tolist()

列表对象可以用 “+” 运算符连接。

z=x+y

如果将“z”列表转换回数组,您将得到一个表示连接数组的数组 −

a.fromlist(z)

这是 complete code

from array import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
b = arr.array('i', [2,7,8,11,3,10])
x=a.tolist()
y=b.tolist()
z=x+y
a=arr.array('i')
a.fromlist(z)
print (a)

Third Method

我们还可以使用 List 类的 extend() 方法从一个列表将元素附加到另一个列表。

首先,将数组转换为列表,然后调用 extend() 方法来合并两个列表 −

from array import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
b = arr.array('i', [2,7,8,11,3,10])
a.extend(b)
print (a)

它将生成以下 output

array('i', [10, 5, 15, 4, 6, 20, 9, 2, 7, 8, 11, 3, 10])

Python - Array Methods

array.reverse() Method

与序列类型类似,数组类也支持 reverse() 方法,该方法按相反的顺序重新排列元素。

Syntax

array.reverse()

Parameters

此方法没有参数

Example

import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
a.reverse()
print (a)

它将生成以下 output

array('i', [5, 4, 3, 2, 1])

数组类还定义了以下有用的方法。

array.count() Method

count() 方法返回给定元素在数组中出现的次数。

Syntax

array.count(v)

Parameters

  1. v − 要计算其出现次数的值

Return value

count() 方法返回一个整数,对应于 v 在数组中出现的次数。

Example

import array as arr
a = arr.array('i', [1, 2, 3, 2, 5, 6, 2, 9])
c = a.count(2)
print ("Count of 2:", c)

它将生成以下 output

Count of 2: 3

array.index() method

数组类中的 index() 方法查找给定元素在数组中首次出现的索引号。

Syntax

array.index(v)

Parameters

  1. v − 要查找其索引号的值

Example

a = arr.array('i', [1, 2, 3, 2, 5, 6, 2, 9])
c = a.index(2)
print ("index of 2:", c)

它将生成以下 output

index of 2: 1

array.fromlist() Method

fromlist() 方法将 Python 列表中的项附加到数组对象。

Syntax

array.fromlist(l)

Parameters

  1. i − 该数组包含附加到该数组的项。列表中的所有项都必须是相同的 arrtype。

Example

import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
lst = [6, 7, 8, 9, 10]
c = a.fromlist(lst)
print (a)

它将生成以下 output

array('i', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

array.tofile() Method

数组类中的 tofile() 方法将数组中的所有项(作为机器值)写入文件对象 f。

Syntax

array.tofile(f)

Parameters

  1. f − 使用 open() 函数获得的文件对象。该文件以 wb 模式打开。

Example

import array as arr
f = open('list.txt','wb')
arr.array("i", [10, 20, 30, 40, 50]).tofile(f)
f.close()

Output

在运行以上代码后,将在当前目录中创建名为“list.txt”的文件。

array.fromfile() Method

fromfile() 方法读取二进制文件,并将指定数量的项附加到数组对象。

Syntax

array.fromfile(f, n)

Parameters

  1. f − 指向以 rb 模式打开磁盘文件的 file 对象

  2. n − 要附加的项的数量

Example

import array as arr
a = arr.array('i', [1, 2, 3, 4, 5])
f = open("list.txt", "rb")
a.fromfile(f, 5)
print (a)

它将生成以下 output

array('i', [1, 2, 3, 4, 5, 10, 20, 30, 40, 50])

Python - Array Exercises

Example 1

Python 程序查找数组中的最大数字 −

import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
print (a)
largest = a[0]
for i in range(1, len(a)):
   if a[i]>largest:
      largest=a[i]
print ("Largest number:", largest)

它将生成以下 output

array('i', [10, 5, 15, 4, 6, 20, 9])
Largest number: 20

Example 2

Python 程序从数组中存储所有偶数到另一个数组中 −

import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
print (a)
b = arr.array('i')
for i in range(len(a)):
   if a[i]%2 == 0:
      b.append(a[i])
print ("Even numbers:", b)

它将生成以下 output

array('i', [10, 5, 15, 4, 6, 20, 9])
Even numbers: array('i', [10, 4, 6, 20])

Example 3

Python 程序查找 Python 数组中所有数字的平均值 −

import array as arr
a = arr.array('i', [10,5,15,4,6,20,9])
print (a)
s = 0
for i in range(len(a)):
   s+=a[i]
avg = s/len(a)
print ("Average:", avg)

# Using sum() function
avg = sum(a)/len(a)
print ("Average:", avg)

它将生成以下 output

array('i', [10, 5, 15, 4, 6, 20, 9])
Average: 9.857142857142858
Average: 9.857142857142858

Exercise Programs

  1. Python 程序查找数组中每个数字与所有数字平均值之间的差

  2. Python 程序将字符串转换为数组

  3. Python 程序将数组分成两个,并将偶数存储在一个数组中,将奇数存储在另一个数组中。

  4. Python 程序对数组执行插入排序。

  5. Python 程序存储给定数组中每个字符的 Unicode 值。

Python - File Handling

当我们使用任何计算机应用程序时,需要提供一些数据。数据存储在计算机的主存储器(RAM)中,直到应用程序正在运行。此后,从 RAM 中擦除内存内容。

我们希望以一种方式存储它,以便可以在持久性介质(例如磁盘文件)中根据需要随时检索它。

Python 使用内置的 input()print() 函数来执行标准输入/输出操作。Python 程序通过 sys 模块中定义的标准流对象 stdin 和 stdout 与这些 IO 设备进行交互。

input() 函数从标准输入流设备(即键盘)读取字节。因此,以下两个语句都从用户那里读取输入。

name = input()
#is equivalent to
import sys
name = sys.stdin.readline()

另一方面,print() 函数将数据发送到标准输出流设备,即显示器。它是一个仿效 stdout 对象的 write() 方法的便捷函数。

print (name)

#is equivalent to
import sys
sys.stdout.write(name)

与输/输出蒸汽交互的任何对象称为文件对象。Python 的内置函数 open() 返回一个文件对象。

The open() Function

此函数创建一个文件对象,该对象将用于调用与它关联的其他支持方法。

Syntax

file object = open(file_name [, access_mode][, buffering])

以下是参数详细信息−

  1. file_name − file_name 参数是一个字符串值,包含要访问的文件的名称。

  2. access_mode − access_mode 确定文件打开的模式,即读取、写入、追加等。下表中给出了可能值的一个完整列表。这是一个可选参数,默认文件访问模式是读取 (r)。

  3. buffering − 如果缓冲值设置为 0,则不进行缓冲。如果缓冲值设置为 1,则在访问文件时执行行缓冲。如果将缓冲值指定为大于 1 的整数,则按照指示的缓冲区大小执行缓冲操作。如果为负数,则缓冲区大小为系统默认值(默认行为)。

File Opening Modes

以下是文件打开模式:

一旦打开了一个文件并且你拥有一个文件对象,你可以获得与该文件相关的各种信息。

Example

# Open a file
fo = open("foo.txt", "wb")
print ("Name of the file: ", fo.name)
print ("Closed or not: ", fo.closed)
print ("Opening mode: ", fo.mode)
fo.close()

它将生成以下 output

Name of the file: foo.txt
Closed or not: False
Opening mode: wb

Python - Write to File

若要向 Python 中的文件写入数据,你需要打开一个文件。任何与输入和输出流进行交互的对象都称为文件对象。Python 的内置函数 open() 将返回一个文件对象。

fileObject = open(file_name [, access_mode][, buffering])

使用 open() 函数获取文件对象后,可以使用 write() 方法向由文件对象表示的文件中写入任何字符串。需要注意的是,Python 字符串可以有二进制数据,而不仅仅是文本。

write() 方法不会在字符串末尾添加换行符 ('\n')。

Syntax

fileObject.write(string)

此处,已传递的参数是要写入已打开文件的内容。

Example

# Open a file
fo = open("foo.txt", "w")
fo.write( "Python is a great language.\nYeah its great!!\n")

# Close opened file
fo.close()

以上方法将创建 foo.txt 文件,并将给定内容写入该文件,最后关闭该文件。程序不显示任何输出,不过如果你使用记事本等任何文本编辑器应用程序打开此文件,它将包含以下内容:

Python is a great language.
Yeah its great!!

Writing in Binary Mode

默认情况下,对文件对象进行读/写操作是在文本字符串数据上执行的。如果我们想处理其他类型的文件,如媒体 (mp3)、可执行文件 (exe)、图片 (jpg) 等,我们需要向读/写模式添加 'b' 前缀。

下面的语句将把一个字符串转换为字节并写入到一个文件中。

f=open('test.bin', 'wb')
data=b"Hello World"
f.write(data)
f.close()

还可以使用 encode() 函数将文本字符串转换为字节。

data="Hello World".encode('utf-8')

Appending to a File

在 'w' 模式下打开任何现有文件以存储附加文本时,其早期内容将被删除。每当以写入权限打开某个文件时,都将其视为一个新文件。若要向现有文件添加数据,请使用 'a' 进行追加模式。

Syntax

fileobject = open(file_name,"a")

Example

# Open a file in append mode
fo = open("foo.txt", "a")
text = "TutorialsPoint has a fabulous Python tutorial"
fo.write(text)

# Close opened file
fo.close()

执行上述程序时,不会显示任何输出,但会在 foo.txt 中添加一个新行。若要验证,请使用文本编辑器打开它。

Python is a great language.
Yeah its great!!
TutorialsPoint has a fabulous Python tutorial

Using the w+ Mode

当打开某个文件以进行写入(使用 'w' 或 'a')时,无法在文件中的任何较早字节位置执行写入操作。'w+' 模式允许使用 write() 和 read() 方法,而无需关闭文件。文件对象支持 seek() 函数,可以将流倒回到任何所需的字节位置。

以下是 seek() 方法的语法:

fileObject.seek(offset[, whence])

Parameters

  1. offset − 这是文件内读/写指针的位置。

  2. whence − 这是可选的,默认为 0,表示绝对文件定位,其他值为 1,表示相对于当前位置查找,2 表示相对于文件末尾查找。

让我们使用 seek() 方法来演示如何对文件执行同时读/写操作。

Example

下列程序以 w+ 模式(这是一种读/写模式)打开文件并添加一些数据。它在文件中查找某个位置并用新文本覆盖其较早的内容。

# Open a file in read-write mode
fo=open("foo.txt","w+")
fo.write("This is a rat race")
fo.seek(10,0)
data=fo.read(3)
fo.seek(10,0)
fo.write('cat')
fo.close()

Output

如果我们在只读模式下打开文件(或在 w+ 模式下查找起始位置)并读取内容,它将显示:

This is a cat race

Python - Read Files

若要使用 Python 从文件中编程读取数据,必须首先打开它。使用内置 open() 函数:

file object = open(file_name [, access_mode][, buffering])

以下是参数详细信息−

  1. file_name − file_name 参数是一个字符串值,包含要访问的文件的名称。

  2. access_mode − access_mode 确定文件的打开模式,即读取、写入、追加等。这是可选参数,默认的文件访问模式为读取 (r)。

这两个语句是相同的 –

fo = open("foo.txt", "r")
fo = open("foo.txt")

要读取打开的文件中的数据,请使用 File 对象的 read() 方法。需要注意的是,Python 字符串可以除了文本数据之外,还可以包含二进制数据。

Syntax

fileObject.read([count])

Parameters

  1. count – 要读取的字节数。

这里,传递的参数是文件中的要读取的字节数。该方法从文件开头开始读取,如果缺少 count,则它尝试尽可能多地读取,可能会持续到文件结尾。

Example

# Open a file
fo = open("foo.txt", "r")
text = fo.read()
print (text)

# Close the opened file
fo.close()

它将生成以下 output

Python is a great language.
Yeah its great!!

Reading in Binary Mode

默认情况下,对文件对象进行读/写操作是在文本字符串数据上执行的。如果我们想处理其他类型的文件,如媒体 (mp3)、可执行文件 (exe)、图片 (jpg) 等,我们需要向读/写模式添加 'b' 前缀。

假设 test.bin 文件已经用二进制模式写入。

f=open('test.bin', 'wb')
data=b"Hello World"
f.write(data)
f.close()

我们需要使用 'rb' 模式来读取二进制文件。在打印之前,先对 read() 方法的返回值进行解码。

f=open('test.bin', 'rb')
data=f.read()
print (data.decode(encoding='utf-8'))

它将生成以下 output

Hello World

Read Integer Data from F ile

为了将整数数据写入二进制文件,整数对象应该通过 to_bytes() 方法转换为字节。

n=25
n.to_bytes(8,'big')
f=open('test.bin', 'wb')
data=n.to_bytes(8,'big')
f.write(data)

要从二进制文件读回数据,请使用 from_bytes() 函数将 read() 函数的输出转换为整数。

f=open('test.bin', 'rb')
data=f.read()
n=int.from_bytes(data, 'big')
print (n)

Read Float Data from File

对于浮点数据,我们需要使用 Python 的标准库中的 struct 模块。

import struct
x=23.50
data=struct.pack('f',x)
f=open('test.bin', 'wb')
f.write(data)

解包 read() 函数的字符串以从二进制文件中检索浮点数据。

f=open('test.bin', 'rb')
data=f.read()
x=struct.unpack('f', data)
print (x)

Using the r+ M ode

当一个文件被打开用于读取(用 'r' 或 'rb'),不能向其中写入数据。我们需要先关闭文件,然后才能执行其他操作。为了同时执行这两个操作,我们在模式参数中必须添加 '' 字符。因此 'w' 或 'r+' 模式可以同时使用 write() 和 read() 方法,而无需关闭文件。

File 对象还支持 seek() 函数,使您可以倒带流以从任何所需的字节位置读取数据。

以下是 seek() 方法的语法:

fileObject.seek(offset[, whence])

Parameters

  1. offset − 这是文件内读/写指针的位置。

  2. whence − 这是可选的,默认为 0,表示绝对文件定位,其他值为 1,表示相对于当前位置查找,2 表示相对于文件末尾查找。

让我们使用 seek() 方法来展示如何从特定字节位置读取数据。

Example

该程序使用 w+ 模式(该模式是可读写的)打开文件,并添加一些数据。它在文件中查找特定位置并用新文本覆盖其早期内容。

fo=open("foo.txt","r+")
fo.seek(10,0)
data=fo.read(3)
print (data)
fo.close()

它将生成以下 output

rat

Python Simultaneous Read/Write

当一个文件被打开用于写入(用 'w' 或 'a'),不能从中读取,反之亦然。这样做会引发 UnSupportedOperation 错误。我们需要先关闭文件,然后才能执行其他操作。

为了同时执行这两个操作,我们在模式参数中 must 添加 '' 字符。因此 'w' 或 'r+' 模式可以同时使用 write() 和 read() 方法,而无需关闭文件。File 对象还支持 seek() 函数,使 pouvez 将数据流倒带到任何所需的字节位置。

The seek() Method

seek() 方法将文件的当前位置设置为偏移量。whence 参数是可选的,默认为 0,这意味着绝对文件定位,其他值是 1,这意味着相对于当前位置查找,2 意味着相对于文件结尾查找。

没有返回值。请注意,如果文件使用 'a' 或 'a+' 打开用于追加,任何 seek() 操作都将在下一次写入时撤消。

如果文件只是使用 'a' 在追加模式下打开用于写入,此方法实际上是一个空操作,但这对于在追加模式下打开且启用了读取的文件仍然是有用的(模式 'a+')。

如果使用 't' 以文本模式打开文件,tell() 返回的偏移量合法。使用其他偏移量将导致未定义的行为。

请注意并非所有文件对象都可寻址。

Syntax

以下是 seek() 方法的语法:

fileObject.seek(offset[, whence])

Parameters

  1. offset − 这是文件内读/写指针的位置。

  2. whence − 这是可选的,默认为 0,表示绝对文件定位,其他值为 1,表示相对于当前位置查找,2 表示相对于文件末尾查找。

让我们使用 seek() 方法来演示如何对文件执行同时读/写操作。

下列程序以 w+ 模式(这是一种读/写模式)打开文件并添加一些数据。它在文件中查找某个位置并用新文本覆盖其较早的内容。

Example

# Open a file in read-write mode
fo=open("foo.txt","w+")
fo.write("This is a rat race")
fo.seek(10,0)
data=fo.read(3)
fo.seek(10,0)
fo.write('cat')
fo.seek(0,0)
data=fo.read()
print (data)
fo.close()

Output

This is a cat race

Python - Renaming and Deleting Files

Python os 模块提供帮助你执行文件处理操作的方法,例如重命名和删除文件。

要使用此模块,需要先导入它,然后可以调用任何相关函数。

rename() Method

rename() 方法采用两个参数,当前文件名和新文件名。

Syntax

os.rename(current_file_name, new_file_name)

Example

以下是将现有文件“test1.txt”重命名为“test2.txt”的一个示例 −

#!/usr/bin/python3
import os
# Rename a file from test1.txt to test2.txt
os.rename( "test1.txt", "test2.txt" )

remove() Method

你可以使用 remove() 方法删除文件,方法是提供要删除的文件名称作为参数。

Syntax

os.remove(file_name)

Example

以下是删除现有文件“test2.txt”的一个示例 −

#!/usr/bin/python3
import os
# Delete file test2.txt
os.remove("text2.txt")

Python - Directories

所有文件都包含在不同的目录中,Python 也可以轻松处理这些文件。 os 模块有几个方法可以帮助你创建、删除和更改目录。

The mkdir() Method

你可以使用 os 模块的 mkdir() 方法在当前目录中创建目录。你需要为此方法提供一个参数,其中包含要创建的目录的名称。

Syntax

os.mkdir("newdir")

Example

以下是创建一个名为 test 的目录的示例 −

#!/usr/bin/python3
import os

# Create a directory "test"
os.mkdir("test")

The chdir() Method

你可以使用 chdir() 方法更改当前目录。chdir() 方法采用一个参数,它是你想将其设为当前目录的目录的名称。

Syntax

os.chdir("newdir")

Example

以下是进入“/home/newdir”目录的一个示例 −

import os

# Changing a directory to "/home/newdir"
os.chdir("/home/newdir")

The getcwd() Method

getcwd() 方法显示当前工作目录。

Syntax

os.getcwd()

Example

以下是提供当前目录的示例 −

#!/usr/bin/python3
import os

# This would give location of the current directory
os.getcwd()

The rmdir() Method

rmdir() 方法删除目录,该目录作为方法中的一个参数传递。

在删除目录之前,应该删除里面的所有内容。

Syntax

os.rmdir('dirname')

Example

以下是删除“/tmp/test”目录的一个示例。需要提供目录的全限定名称,否则它将在当前目录中搜索该目录。

#!/usr/bin/python3
import os

# This would remove "/tmp/test" directory.
os.rmdir( "/tmp/test" )

Python - File Methods

使用 open() 函数创建文件对象。文件类定义了可以拿来执行不同的文件 IO 操作的以下方法。这些方法可用于任何的文件对象,例如字节流或网络流。

让我们简单浏览一下上述方法。

Python - OS File/Directory Methods

os 模块提供了许多有用方法来操作文件。大多数常用方法在此列出 −

Python - OOP Concepts

对象化的 Python 语言自诞生之日起就已存在。由于此功能,创建和使用类和对象极其简单。本章可帮助你成为一名 Python 面向对象编程支持方面的专家。

如果你以前没有过任何面向对象(OO)编程经验,你可能需要咨询该领域的入门课程,或者至少浏览一下教程,以便掌握基本概念。不过,以下是对面向对象编程(OOP)的简要介绍,以帮助你理解。

Procedural Oriented Approach

50 年代和 60 年代开发的早期编程语言被认为是过程化(或面向过程)语言。

计算机程序描述执行特定任务的步骤,通过按逻辑顺序编写一系列指令。更复杂的程序的逻辑被分解为更小但独立且可重用的语句块,称为函数。

每个函数都是以一种可与程序中的其他函数接口的方式编写的。属于函数的数据可以轻松以参数形式与其他函数共享,并且被调用的函数可以将它的结果返回给调用函数。

与过程化方法相关的突出问题如下:

  1. 它的自顶向下方法使得程序难以维护。

  2. 它使用了许多全局数据项,这是不希望的。过多的全局数据项会增加内存开销。

  3. 它更重视过程,并且不考虑相同重要性的数据,并想当然地认为它在程序中自由移动。

  4. 跨函数的数据移动不受限制。在现实场景中,函数与数据有明确的关联,它会处理这些数据。

Python - OOP Concepts

在现实世界中,我们处理的对象(如学生、雇员、发票、汽车等)。对象不仅是数据,也不仅仅是函数,而是两者的结合。每个现实世界对象都有与其相关的属性和行为。

oop concepts

Attributes

  1. 学生的姓名、班级、科目、成绩等。

  2. 雇员的姓名、职务、部门、工资等。

  3. 发票的发票号码、客户、产品代码和名称、价格和数量等。

  4. 汽车的登记号、所有者、公司、品牌、马力、速度等。

每个属性都将具有与之关联的值。属性等同于数据。

Behavior

处理与对象关联的属性。

  1. 计算学生的成绩百分比

  2. 计算应支付给雇员的奖金

  3. 将 GST 应用于发票价值

  4. Measure speed of car

行为等同于函数。在现实生活中,属性和行为并非彼此独立,而是共存的。

面向对象方法最重要的特征是将属性及其功能定义为称为类的单个单元。它用作具有类似属性和行为的所有对象的蓝图。

面向对象编程中,类定义了它的对象拥有什么属性,以及它的行为。另一方面,对象是类的实例。

面向对象编程范例具有以下原则特征:

principles of oop

Class

针对对象的自定义原型,它定义了一组描述该类任意对象的属性。属性为数据成员(类变量和实例变量)和方法,可通过点标记法访问。

Object

某个类的个体对象。例如,属于圆形的类 Circle 的对象 obj 是类 Circle 的一个实例。由其类定义的数据结构的唯一实例。对象包括数据成员(类变量和实例变量)和方法。

Encapsulation

类的数据成员仅供类内定义的函数处理。另一方面,类函数可从类上下文外部访问。因此,对象数据对外部类环境隐藏。类函数(也称为方法)封装对象数据,防止对它的不当访问。

Inheritance

OOP 的软件建模方法,能让你扩展现有类的能力,以便建立新类,而不用从头开始创建。在 OOP 术语中,现有的类称为基类或父类,而新类称为子类。

子类从父类继承数据定义和方法。这有助于重复使用已有的功能。子类可以添加更多定义或重新定义一个基类函数。

Polymorphism

多态是希腊语单词,意为具有多种形式。在 OOP 中,当每个子类为基类中的抽象方法提供自己的实现时,就发生了多态。

Python - Object and Classes

Python 是一种高度的面向对象语言。在 Python 语言中,Python 程序中的每个元素都是某一个类的对象。在程序中使用的数字、字符串、列表、字典等是它们各自内置类中的对象。

Example

num=20
print (type(num))
num1=55.50
print (type(num1))
s="TutorialsPoint"
print (type(s))
dct={'a':1,'b':2,'c':3}
print (type(dct))
def SayHello():
   print ("Hello World")
   return
print (type(SayHello))

执行此代码时,它将生成以下 output -

<class 'int'>
<class 'float'>
<class 'str'>
<class 'dict'>
<class 'function'>

在 Python 中,Object 类是所有类的基础或父类,包括内置类和用户定义的类。

class 关键字用于定义一个新类。类的名称紧跟在关键字类后面,中间用冒号分隔,如下所示:

class ClassName:
   'Optional class documentation string'
   class_suite
  1. 类具有文档字符串,可以通过 ClassName. doc 访问该文档字符串。

  2. class_suite 由定义类成员、数据属性和函数的所有组成语句组成。

Example

class Employee(object):
   'Common base class for all employees'
   pass

Python 中的任何类都是 object 类的子类,因此 object 写在括号中。但是,Python 的后版本不要求将 object 放在括号中。

class Employee:
   'Common base class for all employees'
   pass

要定义此类的对象,请使用以下语法:

e1 = Employee()

Python - Class Attributes

每个 Python 类都保留以下内置属性,可以通过点运算符像访问其他任何属性一样访问它们:

  1. * dict * - 包含类命名空间的字典。

  2. * doc * - 类文档字符串,如未定义,则为无。

  3. * name * - 类名称。

  4. * module * - 定义该类的模块名称。此属性在交互模式中为 " main "。

  5. * bases * - 一个可能为空的元组,其中包含基类,按其在基类列表中出现的顺序排列。

对于上述类,我们尝试访问所有这些属性:

class Employee:
   def __init__(self, name="Bhavana", age=24):
      self.name = name
      self.age = age
   def displayEmployee(self):
      print ("Name : ", self.name, ", age: ", self.age)

print ("Employee.__doc__:", Employee.__doc__)
print ("Employee.__name__:", Employee.__name__)
print ("Employee.__module__:", Employee.__module__)
print ("Employee.__bases__:", Employee.__bases__)
print ("Employee.__dict__:", Employee.__dict__ )

它将生成以下 output

Employee.__doc__: None
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)
Employee.__dict__: {'__module__': '__main__', '__init__': <function Employee.__init__ at 0x0000022F866B8B80>, 'displayEmployee': <function Employee.displayEmployee at 0x0000022F866B9760>, '__dict__': <attribute '__dict__' of 'Employee' objects>, '__weakref__': <attribute '__weakref__' of 'Employee' objects>, '__doc__': None}

Class Variables

在上面的 Employee 类示例中,name 和 age 是实例变量,因为它们的值对于每个对象来说可能是不同的。类属性或变量,其值在该类的所有实例之间共享。类属性表示一个类中所有对象的共同属性。

类属性不会在 init () 构造函数中初始化。它们在类中定义,但不在任何方法中。除对象外,还可以通过类的名称访问它们。换句话说,可以对类及其对象使用类属性。

Example

让我们在 Employee 类中添加一个名为 empCount 的类变量。对于声明的每个对象,系统会自动调用 init () 方法。此方法会初始化实例变量,并使 empCount 加 1。

class Employee:
   empCount = 0
   def __init__(self, name, age):
      self.__name = name
      self.__age = age
      Employee.empCount += 1
      print ("Name: ", self.__name, "Age: ", self.__age)
      print ("Employee Number:", Employee.empCount)

e1 = Employee("Bhavana", 24)
e2 = Employee("Rajesh", 26)
e3 = Employee("John", 27)

Output

我们声明了三个对象。每一次, empCount 增加 1。

Name: Bhavana Age: 24
Employee Number: 1
Name: Rajesh Age: 26
Employee Number: 2
Name: John Age: 27
Employee Number: 3

Python - Class Methods

实例方法访问调用对象的实例变量,因为它获取了对调用对象的引用。但它也可以访问类变量,因为类变量对所有对象是通用的。

Python 具有内置函数 classmethod(),它将实例方法转换为一个类方法,该类方法可以通过对类的引用进行调用,而不能通过对象进行调用。

Syntax

classmethod(instance_method)

Example

在 Employee 类中,使用“ self ”参数(对调用对象的引用)定义 showcount() 实例方法。它打印 empCount 的值。接下来,将方法转换为类方法 counter(),该方法可以通过类引用进行访问。

class Employee:
   empCount = 0
   def __init__(self, name, age):
      self.__name = name
      self.__age = age
      Employee.empCount += 1
   def showcount(self):
         print (self.empCount)
   counter=classmethod(showcount)

e1 = Employee("Bhavana", 24)
e2 = Employee("Rajesh", 26)
e3 = Employee("John", 27)

e1.showcount()
Employee.counter()

Output

使用对象调用 showcount(),使用类调用 count(),两者都显示了员工计数的值。

3
3

使用 @classmethod() 装饰器是对类方法进行定义的指定方式,因为它比先声明一个实例方法,然后再转换为类方法更加方便。

@classmethod
def showcount(cls):
      print (cls.empCount)

Employee.showcount()

类方法充当一个备选构造函数。使用构建新对象所需的参数定义 newemployee() 类方法。它返回构建的对象,这是 init () 方法执行的操作。

   @classmethod
   def showcount(cls):
         print (cls.empCount)
         return
   @classmethod
   def newemployee(cls, name, age):
      return cls(name, age)

e1 = Employee("Bhavana", 24)
e2 = Employee("Rajesh", 26)
e3 = Employee("John", 27)
e4 = Employee.newemployee("Anil", 21)

Employee.showcount()

现在有四个 Employee 对象。

Python - Static Methods

与静态方法不同,它没有强制参数,例如对对象 − self 的引用或对类 − cls 的引用。Python 的标准库函数 staticmethod() 返回一个静态方法。

下面的 Employee 类中,方法被转换为一个静态方法。此静态方法现在可以通过其对象或类的引用进行调用。

class Employee:
   empCount = 0
   def __init__(self, name, age):
      self.__name = name
      self.__age = age
      Employee.empCount += 1

   #@staticmethod
   def showcount():
            print (Employee.empCount)
            return
   counter = staticmethod(showcount)

e1 = Employee("Bhavana", 24)
e2 = Employee("Rajesh", 26)
e3 = Employee("John", 27)

e1.counter()
Employee.counter()

Python 也有 @staticmethod 装饰器,它可以方便地返回一个静态方法。

@staticmethod
   def showcount():
            print (Employee.empCount)
e1.showcount()
Employee.showcount()

Python - Constructors

在面向对象编程中,一个类的对象以一个或多个实例变量或属性为特征,其值对每个对象是唯一的。例如,如果 Employee 类具有一个实例属性 name。它的每个对象 e1 和 e2 可能具有 name 变量的不同值。

构造函数是一个类的实例方法,它在类的新对象声明时会自动调用。构造函数的作用是,在声明对象后立即为实例变量赋值。

Python 使用一个名为 init () 的特殊方法为对象初始化实例变量,它在声明对象后立即使用。

init () 方法充当一个构造函数。它需要一个强制参数 self,即对对象的引用。

def __init__(self):
#initialize instance variables

与类中的 init () 方法以及任何实例方法一样,它具有一个强制参数 self 。然而,您可以为第一个参数指定任何名称,而不一定是 self。

我们在 Employee 类中定义构造函数,以初始化 name 和 age 作为实例变量。然后我们可以访问其对象的这些属性。

Example

class Employee:
   'Common base class for all employees'
   def __init__(self):
      self.name = "Bhavana"
      self.age = 24

e1 = Employee()
print ("Name: {}".format(e1.name))
print ("age: {}".format(e1.age))

它将生成以下 output

Name: Bhavana
age: 24

Parameterized Constructor

对于上述 Employee 类,我们声明的每个对象都将对其实例变量 name 和 age 具有相同的值。要声明具有不同属性的对象(而不是默认值),为 init () 方法定义参数。(方法只不过是在类中定义的一个函数。)

Example

在这个示例中, init () 构造函数有两个形式参数。我们声明具有不同值的 Employee 对象 −

class Employee:
   'Common base class for all employees'
   def __init__(self, name, age):
      self.name = name
      self.age = age

e1 = Employee("Bhavana", 24)
e2 = Employee("Bharat", 25)

print ("Name: {}".format(e1.name))
print ("age: {}".format(e1.age))
print ("Name: {}".format(e2.name))
print ("age: {}".format(e2.age))

它将生成以下 output

Name: Bhavana
age: 24
Name: Bharat
age: 25

你可以给构造函数中的形式参数指定默认参数值,以便可以在传递或不传递参数的情况下实例化对象。

class Employee:
   'Common base class for all employees'
   def __init__(self, name="Bhavana", age=24):
      self.name = name
      self.age = age

e1 = Employee()
e2 = Employee("Bharat", 25)

print ("Name: {}".format(e1.name))
print ("age: {}".format(e1.age))
print ("Name: {}".format(e2.name))
print ("age: {}".format(e2.age))

它将生成以下 output

Name: Bhavana
age: 24
Name: Bharat
age: 25

Python - Instance Methods

除了 init () 构造函数以外,一个类中还可能定义一个或多个实例方法。带有一个形式参数 self 的方法称为实例方法,因为它是由特定的对象调用的。

Example

在下面的示例中,定义了一个 displayEmployee() 方法。它返回调用该方法的 Employee 对象的 name 和 age 属性。

class Employee:
   def __init__(self, name="Bhavana", age=24):
      self.name = name
      self.age = age
   def displayEmployee(self):
      print ("Name : ", self.name, ", age: ", self.age)

e1 = Employee()
e2 = Employee("Bharat", 25)

e1.displayEmployee()
e2.displayEmployee()

它将生成以下 output

Name : Bhavana , age: 24
Name : Bharat , age: 25

可以随时添加、移除或修改类的属性和对象:

emp1.salary = 7000 # Add a 'salary' attribute.
emp1.name = 'xyz' # Modify 'name' attribute.
del emp1.salary # Delete 'salary' attribute.

你可以使用以下函数来访问属性,而不是使用普通语句 −

  1. getattr(obj, name[, default]) − 访问对象的属性。

  2. hasattr(obj,name) − 检查属性是否存在。

  3. setattr(obj,name,value) − 设置属性。如果属性不存在,则会创建它。

  4. delattr(obj, name) − 删除属性。

print (hasattr(e1, 'salary')) # Returns true if 'salary' attribute exists
print (getattr(e1, 'name')) # Returns value of 'name' attribute
setattr(e1, 'salary', 7000) # Set attribute 'salary' at 8
delattr(e1, 'age') # Delete attribute 'age'

它将生成以下 output

False
Bhavana

Python - Access Modifiers

C++ 和 Java 等语言使用访问修饰符来限制对类成员(即变量和方法)的访问。这些语言有关键字 public、protected 和 private 来指定访问类型。

如果一个类成员可以在程序中的任何地方访问,则称其为公共的。只能从类内部访问私有成员。

  1. 通常,方法被定义为公有方法,而实例变量则为私有变量。私有实例变量和公有方法的这种安排确保了封装原则的实施。

  2. Protected members 可以从类内部以及从派生自该类的类中访问。

与这些语言不同,Python 没有规定对类成员的访问类型。默认情况下,类中的所有变量和方法都是公共的。

Example

在这里,我们有 Employee 类,其实例变量为 name 和 age。此类的对象具有这两个属性。它们可以从类的外部直接访问,因为它们是公共的。

class Employee:
   'Common base class for all employees'
   def __init__(self, name="Bhavana", age=24):
      self.name = name
      self.age = age

e1 = Employee()
e2 = Employee("Bharat", 25)

print ("Name: {}".format(e1.name))
print ("age: {}".format(e1.age))
print ("Name: {}".format(e2.name))
print ("age: {}".format(e2.age))

它将生成以下 output

Name: Bhavana
age: 24
Name: Bharat
age: 25

Python 不会强制限制访问任何实例变量或方法。然而,Python 规定了一个惯例,用单下划线或双下划线作为变量/方法名称的前缀,以模拟受保护和私有访问修饰符的行为。

要表示一个实例变量为私有的,请在它的前面加上双下划线(如 __age )。要表示某个实例变量是受保护的,请在它的前面加上单下划线(如 _salary )。

Example

让我们修改 Employee 类。添加另一个实例变量 salary。通过分别加上双下划线和单下划线前缀将 age 设置为私有的,将 salary 设置为受保护的。

class Employee:
   def __init__(self, name, age, salary):
      self.name = name # public variable
      self.__age = age # private variable
      self._salary = salary # protected variable
   def displayEmployee(self):
      print ("Name : ", self.name, ", age: ", self.__age, ", salary: ", self._salary)

e1=Employee("Bhavana", 24, 10000)

print (e1.name)
print (e1._salary)
print (e1.__age)

当您运行此代码时,它将生成以下 output

Bhavana
10000
Traceback (most recent call last):
 File "C:\Users\user\example.py", line 14, in <module>
  print (e1.__age)
        ^^^^^^^^
AttributeError: 'Employee' object has no attribute '__age'

Python 显示 AttributeError 是因为 __age 为私有,且不可在类外使用。

Name Mangling

Python 不会阻止对私有数据的访问,它仅仅留给程序员的智慧,不会编写任何可以从类外访问它的代码。您仍然可以通过 Python 的名称混淆技术访问私有成员。

名称混淆是将双下划线成员的名称更改为 object._class__variable 格式的过程。如果需要,仍然可以从类外访问它,但应该避免此做法。

在我们的示例中,私有实例变量 "__name" 被改写为格式以得到破坏

obj._class__privatevar

因此,要获取 "e1" 对象的 "_age" 实例变量值,请将其更改为 "e1._Employee_age"。

将上面程序中的 print() 语句更改为 −

print (e1._Employee__age)

它现在打印 24,即 e1 的年龄。

Python Property Object

Python 的标准库有一个内置的 property() 函数。它返回一个属性对象。它充当 Python 类的实例变量的接口。

面向对象编程的封装原则要求实例变量具有受限制的私有访问。Python 没有高效的机制用于此目的。property() 函数提供了一个替代方案。

property() 函数使用在类中定义的 getter、setter 和 delete 方法来为类定义一个属性对象。

Syntax

property(fget=None, fset=None, fdel=None, doc=None)

Parameters

  1. fget − 一个用于获取实例变量值的实例方法。

  2. fset − 一个用于向实例变量分配值的实例方法。

  3. fdel − 一个用于删除一个实例变量的实例方法。

  4. fdoc − 该属性的文档字符串。

该函数使用 getter 和 setter 方法以返回属性对象。

Getters and Setter Methods

getter 方法获取一个实例变量的值,通常命名为 get_varname,而 setter 方法给这个变量赋值,命名为 set_varname。

让我们给 Employee 类中定义 getter 方法 get_name() 和 get_age(),以及 setter 方法 set_name() 和 set_age()。

Example

class Employee:
   def __init__(self, name, age):
      self.__name = name
      self.__age = age

   def get_name(self):
      return self.__name
   def get_age(self):
      return self.__age
   def set_name(self, name):
      self.__name = name
      return
   def set_age(self, age):
      self.__age=age

e1=Employee("Bhavana", 24)
print ("Name:", e1.get_name(), "age:",

e1.get_age())
e1.set_name("Archana")
e1.set_age(21)
print ("Name:", e1.get_name(), "age:", e1.get_age())

它将生成以下 output

Name: Bhavana age: 24
Name: Archana age: 21

getter 和 setter 方法可以获取或给实例变量赋值。property() 函数利用它们添加属性对象作为类属性。

name 属性的定义如下 −

name = property(get_name, set_name, "name")

类似地,你可以添加 age 属性 −

age = property(get_age, set_age, "age")

属性对象的一个优势是你可以利用它来检索其关联的实例变量的值以及指定值。

例如,

print (e1.name) displays value of e1.__name
e1.name = "Archana" assigns value to e1.__age

Example

包含属性对象及用法的完整程序如下 −

class Employee:
   def __init__(self, name, age):
      self.__name = name
      self.__age = age

   def get_name(self):
      return self.__name
   def get_age(self):
      return self.__age
   def set_name(self, name):
      self.__name = name
      return
   def set_age(self, age):
      self.__age=age
      return
   name = property(get_name, set_name, "name")
   age = property(get_age, set_age, "age")

e1=Employee("Bhavana", 24)
print ("Name:", e1.name, "age:", e1.age)

e1.name = "Archana"
e1.age = 23
print ("Name:", e1.name, "age:", e1.age)

它将生成以下 output

Name: Bhavana age: 24
Name: Archana age: 23

Python - Inheritance

继承是面向对象编程方法论中最重要的一部分。它最常用于使用 Java、PHP、Python 等多种语言的软件开发过程中。

你无需从头开始,可以通过在新建类名的后面列出父类的方式从一个预先存在的类中派生一个类来创建它。

你无需从头开始,可以通过在新建类名的后面列出父类的方式从一个预先存在的类中派生一个类来创建它。

如果你必须设计一个新类,且其大部分属性已经在现有的类中得到了完善定义,那么为什么要重新定义它们呢?继承允许重新使用现有类的功能,并且在需要时扩展它们以便设计新类。

当一个新类与一个现有类具有“是”的关系时,才涉及到继承。汽车是交通工具。公共汽车是一种交通工具;自行车也是一种交通工具。这里的交通工具是父类,而汽车、公共汽车和自行车是子类。

inheritance

Syntax

衍生类被声明的方式与他们的父类非常相似;但是,类名后面给出了要继承的基类的列表:

class SubClassName (ParentClass1[, ParentClass2, ...]):
   'Optional class documentation string'
   class_suite

Example

class Parent: # define parent class
   def __init__(self):
      self.attr = 100
      print ("Calling parent constructor")
   def parentMethod(self):
      print ('Calling parent method')
   def set_attr(self, attr):
      self.attr = attr

   def get_attr(self):
      print ("Parent attribute :", self.attr)

class Child(Parent): # define child class
   def __init__(self):
      print ("Calling child constructor")

   def childMethod(self):
      print ('Calling child method')

c = Child()      # instance of child
c.childMethod()  # child calls its method
c.parentMethod() # calls parent's method
c.set_attr(200)  # again call parent's method
c.get_attr()     # again call parent's method

Output

执行此代码时,将生成以下输出 −

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200

Python - Multiple Inheritance

Python 中的多个继承允许你基于一个以上的父类构建一个类。子类因此可以继承所有父类的属性和方法。子类可以覆盖从任何父类继承的方法。

Syntax

class parent1:
   #statements

class parent2:
   #statements

class child(parent1, parent2):
   #statements

Python 的标准库有一个内置的 divmod()函数,该函数返回一个包含两个元素的元组。第一个数字是两个自变量的商,第二个是两个操作数的模值。

Example

此示例中尝试模拟 divmod()函数。我们定义了两个类,即 division 和 modulus,然后有一个 div_mod 类继承这两个类。

class division:
   def __init__(self, a,b):
      self.n=a
      self.d=b
   def divide(self):
      return self.n/self.d
class modulus:
   def __init__(self, a,b):
      self.n=a
      self.d=b
   def mod_divide(self):
      return self.n%self.d

class div_mod(division,modulus):
   def __init__(self, a,b):
      self.n=a
      self.d=b
   def div_and_mod(self):
      divval=division.divide(self)
      modval=modulus.mod_divide(self)
      return (divval, modval)

这个子类有一个新的方法 div_and_mod(),该方法在内部调用其继承类的 divide() 和 mod_divide() 方法以返回商和模值。

x=div_mod(10,3)
print ("division:",x.divide())
print ("mod_division:",x.mod_divide())
print ("divmod:",x.div_and_mod())

Output

division: 3.3333333333333335
mod_division: 1
divmod: (3.3333333333333335, 1)

Method Resolution Order (MRO)

术语“方法解析顺序”与 Python 中的派生相关。在 Python 中,继承可以分布在多级之上。我们假设 A 是 B 的父级,而 B 是 C 的父级。类 C 可以覆盖继承的方法,或其对象可以按其父级所定义的那样调用它。那么,Python 如何找到适当的方法来调用。

每个 Python 中都有一个 mro() 方法,该方法返回 Python 用于解析要调用的方法的层次顺序。解析顺序是从继承顺序的底部到顶部。

在我们前面的示例中,div_mod 类继承了 division 类和 modulus 类。因此,mro 方法返回以下顺序:

[<class '__main__.div_mod'>, <class '__main__.division'>, <class '__main__.modulus'>, <class 'object'>]

Python - Polymorphism

“多态性”一词是指在不同上下文中以不同形式存在的某个函数或方法。由于 Python 是动态类型语言,所以 Python 中的多态性实现起来非常容易。

如果某个父类中的方法在它的不同子类中由不同的业务逻辑覆盖,则这个基类方法就是一个多态方法。

Example

下面给出了一个多态性示例,我们有抽象类 shape 。它被两个类 circle 和 rectangle 作为父类使用。这两个类均以不同的方式覆盖父类的 draw() 方法。

from abc import ABC, abstractmethod
class shape(ABC):
   @abstractmethod
   def draw(self):
      "Abstract method"
      return

class circle(shape):
   def draw(self):
      super().draw()
      print ("Draw a circle")
      return

class rectangle(shape):
   def draw(self):
      super().draw()
      print ("Draw a rectangle")
      return

shapes = [circle(), rectangle()]
for shp in shapes:
   shp.draw()

Output

执行此代码时,将生成以下输出 −

Draw a circle
Draw a rectangle

变量 shp 首先引用 circle 对象,并从 circle 类中调用 draw() 方法。在下一次迭代中,它引用 rectangle 对象,并从 rectangle 类中调用 draw() 方法。因此 shape 类中的 draw() 方法是多态的。

Python - Method Overriding

你总是可以覆盖父类方法。覆盖父类方法的一个原因是,你可能希望在你的子类中实现特殊或不同的功能。

Example

class Parent: # define parent class
   def myMethod(self):
      print ('Calling parent method')

class Child(Parent): # define child class
   def myMethod(self):
      print ('Calling child method')

c = Child() # instance of child
c.myMethod() # child calls overridden method

当执行以上代码时,它会产生以下 output -

Calling child method

为了理解 Python 中的继承,让我们举另一个例子。以下使用 Employee 类作为父类 −

class Employee:
   def __init__(self,nm, sal):
      self.name=nm
      self.salary=sal
   def getName(self):
      return self.name
   def getSalary(self):
      return self.salary

接下来,我们定义一个 SalesOfficer 类,它使用 Employee 作为父类。它继承父类的 instance 变量 name 和 salary。此外,子类还有另一个 instance 变量 incentive。

我们将使用内置函数 super() ,它返回父类的引用,并在子构造函数 init () 方法中调用父构造函数。

class SalesOfficer(Employee):
   def __init__(self,nm, sal, inc):
      super().__init__(nm,sal)
      self.incnt=inc
   def getSalary(self):
      return self.salary+self.incnt

覆盖 getSalary() 方法可以向薪水中添加奖励。

Example

声明父类和子类的对象,并查看覆盖效果。完整的代码如下 −

class Employee:
   def __init__(self,nm, sal):
      self.name=nm
      self.salary=sal
   def getName(self):
      return self.name
   def getSalary(self):
      return self.salary

class SalesOfficer(Employee):
   def __init__(self,nm, sal, inc):
      super().__init__(nm,sal)
      self.incnt=inc
   def getSalary(self):
      return self.salary+self.incnt

e1=Employee("Rajesh", 9000)
print ("Total salary for {} is Rs {}".format(e1.getName(),e1.getSalary()))
s1=SalesOfficer('Kiran', 10000, 1000)
print ("Total salary for {} is Rs {}".format(s1.getName(),s1.getSalary()))

执行此代码时,它将生成以下 output -

Total salary for Rajesh is Rs 9000
Total salary for Kiran is Rs 11000

Base Overridable Methods

下表列出了 object 类的某些通用功能,object 类是所有 Python 类(class)的父类。你可以在你自己的类中覆盖这些方法 −

Python - Method Overloading

方法重载是面向对象编程的一项重要功能。Java、C++、C# 语言支持方法重载,但在 Python 中不可能执行方法重载。

当你在一个类中定义了多个同名的方法,但使用不同的参数类型和/或返回类型时,这就是方法重载的情况。Python 不支持此机制,如下面的代码所示 −

Example

class example:
   def add(self, a, b):
      x = a+b
      return x
   def add(self, a, b, c):
      x = a+b+c
      return x

obj = example()

print (obj.add(10,20,30))
print (obj.add(10,20))

Output

在使用三个参数首次调用 add() 方法时成功。但是,在使用两个参数调用 add() 方法(如在类中定义的那样)时失败。

60
Traceback (most recent call last):
 File "C:\Users\user\example.py", line 12, in <module>
  print (obj.add(10,20))
         ^^^^^^^^^^^^^^
TypeError: example.add() missing 1 required positional argument: 'c'

输出会告诉你 Python 仅考虑对 add() 方法的最新定义,而丢弃较早的定义。

要模拟方法重载,我们可以使用变通方法,即将方法参数的默认值定义为 None,这样便可以使用一个、两个或三个参数。

Example

class example:
   def add(self, a = None, b = None, c = None):
      x=0
      if a !=None and b != None and c != None:
         x = a+b+c
      elif a !=None and b != None and c == None:
         x = a+b
      return x

obj = example()

print (obj.add(10,20,30))
print (obj.add(10,20))

它将生成以下 output

60
30

通过这种方法,我们能够在 Python 类中加入方法重载。

Python 的标准库没有实现方法重载的任何其他规定。但是,我们可以使用来自名为 MultipleDispatch 的第三方模块的 dispatch 函数来实现此目的。

首先,你需要安装 Multipledispatch 模块。

pip install multipledispatch

此模块具有 @dispatch 装饰器。它获取要传递给被重载的方法的参数数量。如下所示,使用 @dispatch 装饰器定义 add() 方法的多个副本 −

Example

from multipledispatch import dispatch
class example:
   @dispatch(int, int)
   def add(self, a, b):
      x = a+b
      return x
   @dispatch(int, int, int)
   def add(self, a, b, c):
      x = a+b+c
      return x

obj = example()

print (obj.add(10,20,30))
print (obj.add(10,20))

Output

执行此代码时,将生成以下输出 −

60
30

Python - Dynamic Binding

在面向对象编程中,动态绑定概念与多态性紧密相关。在 Python 中,动态绑定是在运行时而不是在编译时解析方法或属性的过程。

根据多态性特性,不同的对象对同一方法调用做出不同的响应,具体取决于它们各自的实现。此行为是通过方法覆盖来实现的,其中子类提供在其超类中定义的方法的自身实现。

Python 解释器确定在运行时基于对象的类型或类层次结构调用哪个适当的方法或属性。这意味着要调用的具体方法或属性是根据对象的实际类型动态确定的。

Example

以下示例说明了 Python 中的动态绑定 −

class shape:
   def draw(self):
      print ("draw method")
      return

class circle(shape):
   def draw(self):
      print ("Draw a circle")
      return

class rectangle(shape):
   def draw(self):
      print ("Draw a rectangle")
      return

shapes = [circle(), rectangle()]
for shp in shapes:
   shp.draw()

它将生成以下 output

Draw a circle
Draw a rectangle

如你所见,draw() 方法会根据对象的类型动态绑定到相应的实现。这就是在 Python 中实现动态绑定的方式。

Duck Typing

另一个与动态绑定紧密相关的概念是 duck typing 。是否一个对象适合某个特定用途由它是否具有某些方法或属性决定,而不是由它的类型决定。这使得 Python 具有更高的灵活性,并能重用代码。

鸭子类型是 Python(Perl、Ruby、PHP、JavaScript 等)等动态类型语言的一项重要特性,它专注于对象的的行为而不是它的具体类型。根据“鸭子类型”概念,“如果它像鸭子一样走路、像鸭子一样嘎嘎叫,那么它一定是鸭子。”

鸭子类型允许不同类型对象的可互换使用,只要它们有必需方法或属性。目标是促进灵活性及代码重用。这是一个更广泛的概念,它强调对象的行为及接口而不是正式类型。

这里是一个鸭子类型的示例 −

class circle:
   def draw(self):
      print ("Draw a circle")
      return

class rectangle:
   def draw(self):
      print ("Draw a rectangle")
      return

class area:
   def area(self):
      print ("calculate area")
      return

def duck_function(obj):
   obj.draw()

objects = [circle(), rectangle(), area()]
for obj in objects:
   duck_function(obj)

它将生成以下 output

Draw a circle
Draw a rectangle
Traceback (most recent call last):
 File "C:\Python311\hello.py", line 21, in <module>
  duck_function(obj)
 File "C:\Python311\hello.py", line 17, in duck_function
 obj.draw()
AttributeError: 'area' object has no attribute 'draw'

鸭子类型的最重要思想是 duck_function() 不会关心它接收的对象的具体类型。它只要求对象具有 draw() 方法。如果一个对象通过具有必要的行为“像鸭子一样嘎嘎叫”,那么它将被视为“鸭子”,用于调用 draw() 方法。

因此,在鸭子类型中,焦点在于对象的的行为,而不是它的明确类型,这允许只要不同类型对象表现出所需的行为,就可以互换使用。

Python - Dynamic Typing

Python 语言最突出的特点之一是它是一种动态类型语言。基于编译器的 C/C++、Java 等语言是静态类型的。让我们尝试了解静态类型和动态类型的区别。

在静态类型语言中,每个变量及其数据类型在给它赋值之前必须声明。任何其他类型的值都不能被编译器接受,并且会引发编译时错误。

我们来看一个 Java 程序的以下代码段:

public class MyClass {
   public static void main(String args[]) {
      int var;
      var="Hello";

      System.out.println("Value of var = " + var);
   }
}

这里, var 被声明为一个整数变量。当我们尝试给它赋予一个字符串值时,编译器给出了以下错误消息:

/MyClass.java:4: error: incompatible types: String cannot be converted to int
   x="Hello";
     ^
1 error

Python 中的变量仅仅是存储在内存中的对象的标签或引用,而不是具名内存位置。因此,不需要事先声明类型。因为它只是一个标签,所以可以把它放在另一个对象上,而这个对象可以是任何类型。

在 Java 中,变量的类型决定了它能存储什么,不能存储什么。在 Python 中则相反。在这里,数据类型(即对象)决定了变量的类型。首先,让我们存储一个字符串在变量中来检查它的类型。

>>> var="Hello"
>>> print ("id of var is ", id(var))
id of var is 2822590451184
>>> print ("type of var is ", type(var))
type of var is <class 'str'>

因此, var 是字符串类型。但是,它不是永久绑定的。它只是一个标签;并且可以被赋予任何其他类型对象,比如一个浮点数,该浮点数将使用不同的 id() 存储:

>>> var=25.50
>>> print ("id of var is ", id(var))
id of var is 2822589562256
>>> print ("type of var is ", type(var))
type of var is <class 'float'>

或者一个元组。var 标签现在位于一个不同的对象上。

>>> var=(10,20,30)
>>> print ("id of var is ", id(var))
id of var is 2822592028992
>>> print ("type of var is ", type(var))
type of var is <class 'tuple'>

我们可以看到, var 的类型每次引用一个新对象时都会改变。这就是 Python 是动态类型语言的原因。

与 C/C++ 和 Java 相比,Python 的动态类型特性使其更灵活。但是,它容易出现运行时错误,因此程序员必须小心。

Python - Abstraction

抽象是面向对象编程的重要原则之一。它指的是一种编程方法,其中只公开对象的相关数据,隐藏所有其他细节。这种方法有助于降低复杂性,提高应用程序开发的效率。

有两种类型的抽象。一种是数据抽象,其中原始数据实体通过数据结构隐藏,数据结构可以在内部通过隐藏的数据实体工作。另一种类型称为过程抽象。它指的是隐藏进程的底层实现细节。

在面向对象编程术语中,如果一个类无法被实例化,即你不能拥有一个抽象类的对象,那么这个类被称为抽象类。但是,你可以把它作为一个基础类或父类来构建其他类。

若要在 Python 中形成一个抽象类,它必须继承 abc 模块中定义的 ABC 类。此模块在 Python 的标准库中提供。此外,该类必须至少有一个抽象方法。同样,抽象方法是不能被调用的方法,但可以被覆盖。你需要用 @abstractmethod 装饰器对其进行装饰。

Example

from abc import ABC, abstractmethod
class demo(ABC):
   @abstractmethod
   def method1(self):
      print ("abstract method")
      return
   def method2(self):
      print ("concrete method")

demo 类继承自 ABC 类。有一个 method1(),它是一个抽象方法。注意,该类可具有其他非抽象(具体)方法。

如果你尝试声明一个 demo 类的对象,Python 会引发 TypeError:

   obj = demo()
         ^^^^^^
TypeError: Can't instantiate abstract class demo with abstract method method1

demo 类可以在此处用作另一个类的父类。但子类必须覆盖父类中的抽象方法。否则,Python 会抛出此错误 −

TypeError: Can't instantiate abstract class concreteclass with abstract method method1

因此,具有重写的抽象方法的子类在以下 example 中给出 −

from abc import ABC, abstractmethod
class democlass(ABC):
   @abstractmethod
   def method1(self):
      print ("abstract method")
      return
   def method2(self):
      print ("concrete method")

class concreteclass(democlass):
   def method1(self):
      super().method1()
      return

obj = concreteclass()
obj.method1()
obj.method2()

Output

执行此代码时,将生成以下输出 −

abstract method
concrete method

Python - Encapsulation

封装原则是面向对象编程范式的主要支柱之一。Python 在实施封装时采用了一种不同的方式。

我们知道一个类是对象的自定义原型。它定义了一组数据成员和方法,可以处理数据。根据数据封装原理,描述对象的成员数据对类外部的环境是隐藏的。它们仅供类内定义的方法处理。另一方面,方法本身可以从类上下文外部访问。因此,对象数据被认为被方法封装。这种封装的结果是防止任何不当访问对象数据。

C++ 和 Java 等语言使用访问修饰符限制对类成员(即变量和方法)的访问。这些语言有关键词public、protected和private来指定访问类型。

如果类成员可以在程序中的任何位置进行访问,则称其为public。私有成员只允许在类内进行访问。通常,方法被定义为公有,实例变量为私有。私有实例变量和公有方法的这种安排确保了封装的实现。

与这些语言不同,Python 没有规定可以具有哪种类型访问的类成员。默认情况下,Python 类中的所有变量和方法都是公有的,如下例所示。

Example 1

在此,我们有一个带有实例变量 nameage 的Employee类。该类的对象具有这两个属性。由于它们是公有的,因此可以从类外部直接访问它们。

class Student:
   def __init__(self, name="Rajaram", marks=50):
      self.name = name
      self.marks = marks

s1 = Student()
s2 = Student("Bharat", 25)

print ("Name: {} marks: {}".format(s1.name, s2.marks))
print ("Name: {} marks: {}".format(s2.name, s2.marks))

它将生成以下 output

Name: Rajaram marks: 50
Name: Bharat marks: 25

在上述示例中,实例变量在类内初始化。但是,对类外部的实例变量值没有任何访问限制,这违背了封装的原则。

尽管没有强制能见性的关键字,但 Python 有一个以奇怪的方式命名实例变量的约定。在 Python 中,使用单下划线或双下划线作为变量/方法名称的前缀来模拟受保护和私有访问修饰符的行为。

如果变量前缀为双下划线(如“ __age ”),则实例变量为私有,同样,如果变量名称前缀为单下划线(如“ _salary ”),则为私有。

Example 2

让我们修改 Student 类。添加另一个实例变量salary。通过给 name 和 marks 加上前缀双下划线,将它们变为私有。

class Student:

   def __init__(self, name="Rajaram", marks=50):
      self.__name = name
      self.__marks = marks
   def studentdata(self):
      print ("Name: {} marks: {}".format(self.__name, self.__marks))

s1 = Student()
s2 = Student("Bharat", 25)

s1.studentdata()
s2.studentdata()
print ("Name: {} marks: {}".format(s1.__name, s2.__marks))
print ("Name: {} marks: {}".format(s2.__name, __s2.marks))

当您运行此代码时,它将生成以下 output

Name: Rajaram marks: 50
Name: Bharat marks: 25
Traceback (most recent call last):
 File "C:\Python311\hello.py", line 14, in <module>
  print ("Name: {} marks: {}".format(s1.__name, s2.__marks))
AttributeError: 'Student' object has no attribute '__name'

以上输出清楚地表明,尽管实例变量name和age可以通过在类内声明的方法(studentdata()方法)进行访问,但由于双下划线前缀使变量变为私有,因此不允许在类外部访问它们,从而引发属性错误。

Python 并不会完全阻止对私有数据的访问。它只是把它留给程序员,让他们不要编写任何从类外对其进行访问的代码。您仍然可以使用 Python 的名称混淆技术访问私有成员。

名称混淆是将双下划线成员的名称更改为 object._class__variable 格式的过程。如果需要,仍然可以从类外访问它,但应该避免此做法。

在我们的示例中,私有实例变量 "__name" 被改写为格式以得到破坏

obj._class__privatevar

因此,要访问“s1”对象的“_marks”实例变量的值,请将其更改为“s1._Student_marks”。

将上面程序中的 print() 语句更改为 −

print (s1._Student__marks)

它现在打印 s1 的分数 50。

因此,我们可以得出结论,Python 并不完全按照面向对象编程的理论来实现封装。通过规定名称约定并允许程序员在公共作用域中确实需要访问私有数据时使用名称混淆,它采取了一种更为成熟的方法。

Python - Interfaces

在软件工程中,接口是一种软件架构模式。接口就像一个类,但其方法只有原型签名定义而没有任何要实现的主体。建议的功能需要由一个具体类来实现。

在 Java 等语言中,有 interface 关键字,可以方便地定义一个接口。Python 没有它或任何类似关键字。因此,与在抽象类中一样,使用相同的 ABC 类和 @abstractmethod 装饰器。

在 Python 中,抽象类和接口看起来类似。两者的唯一区别是抽象类可能有一些非抽象方法,而接口中的所有方法都必须是抽象的,并且实现类必须重写所有抽象方法。

Example

from abc import ABC, abstractmethod
class demoInterface(ABC):
   @abstractmethod
   def method1(self):
      print ("Abstract method1")
      return

   @abstractmethod
   def method2(self):
      print ("Abstract method1")
      return

以上接口有两个抽象方法。与抽象类一样,我们无法实例化一个接口。

   obj = demoInterface()
         ^^^^^^^^^^^^^^^
TypeError: Can't instantiate abstract class demoInterface with abstract methods method1, method2

让我们提供一个同时实现两个抽象方法的类。如果没有包含所有抽象方法的实现,Python 会显示以下错误——

   obj = concreteclass()
         ^^^^^^^^^^^^^^^
TypeError: Can't instantiate abstract class concreteclass with abstract method method2

以下类实现了两个方法——

class concreteclass(demoInterface):
   def method1(self):
      print ("This is method1")
      return

   def method2(self):
      print ("This is method2")
      return

obj = concreteclass()
obj.method1()
obj.method2()

Output

执行此代码时,将生成以下输出 −

This is method1
This is method2

Python - Packages

在 Python 中,模块是一个带有 .py 扩展名的 Python 脚本,包含对象,如类、函数等。Python 中的包进一步扩展了模块化方法的概念。包是一个包含一个或多个模块文件的文件夹;另外一个特殊文件 " init .py",它可以是空的,但可以包含包列表。

让我们使用名称 mypackage 创建一个 Python 包。按照以下步骤操作——

  1. 创建一个外部文件夹来容纳 mypackage 的内容。将其命名为 packagedemo。

  2. 在其中创建另一个文件夹 mypackage。这将是我们准备构建的 Python 包。两个 Python 模块 areafunctions.py 和 mathfunctions.py 将在 mypackage 中创建。

  3. 在 mypackage 文件夹中创建一个空文件 " .init .py"。

  4. 在外部文件夹中,我们稍后将存储一个 Python 脚本 example.py 来测试我们的包。

file/folder structure 应如下所示:

folder structure

使用你喜欢的代码编辑器,将以下两个 Python 模块保存在 mypackage 文件夹中。

# mathfunctions.py
def sum(x,y):
   val = x+y
   return val

def average(x,y):
   val = (x+y)/2
   return val

def power(x,y):
   val = x**y
   return val

创建另一个 Python 脚本:

# areafunctions.py
def rectangle(w,h):
   area = w*h
   return area

def circle(r):
   import math
   area = math.pi*math.pow(r,2)
   return area

现在,让我们使用此包文件夹之上的 Python 脚本来测试 myexample 包。请参阅以上文件夹结构。

#example.py
from mypackage.areafunctions import rectangle
print ("Area :", rectangle(10,20))

from mypackage.mathsfunctions import average
print ("average:", average(10,20))

此程序从 mypackage 导入功能。如果执行以上脚本,您应该获得以下 output

Area : 200
average: 15.0

Define Package List

您可以将包中的选定功能或任何其他资源放置到“ init .py”文件中。让我们将以下代码放入其中。

from .areafunctions import circle
from .mathsfunctions import sum, power

要从该包中导入可用功能,请将以下脚本保存为 testpackage.py,该脚本位于包文件夹的上方,同前。

#testpackage.py
from mypackage import power, circle

print ("Area of circle:", circle(5))
print ("10 raised to 2:", power(10,2))

它将生成以下 output

Area of circle: 78.53981633974483
10 raised to 2: 100

Package Installation

目前,我们只能从包文件夹上方的脚本访问包资源。若要在文件系统中的任何位置使用包,您需要使用 PIP 实用程序对其进行安装。

首先,将以下脚本保存到父文件夹中,它位于包文件夹的级别上。

#setup.py
from setuptools import setup
setup(name='mypackage',
version='0.1',
description='Package setup script',
url='#',
author='anonymous',
author_email='test@gmail.com',
license='MIT',
packages=['mypackage'],
zip_safe=False)

在保持父文件夹状态的同时,运行命令提示符中的 PIP 实用程序。

C:\Users\user\packagedemo>pip3 install .
Processing c:\users\user\packagedemo
 Preparing metadata (setup.py) ... done
Installing collected packages: mypackage
 Running setup.py install for mypackage ... done
Successfully installed mypackage-0.1

你现在应该能够在任何环境中导入包的内容。

C:\Users>python
Python 3.11.2 (tags/v3.11.2:878ead1, Feb 7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import mypackage
>>> mypackage.circle(5)
78.53981633974483

Python - Inner Classes

在 Python 中,在另一个类内定义的类称为内部类。有时内部类也称为嵌套类。如果实例化内部类,父类也可以使用内部类的对象。内部类的对象将成为外部类的一个属性。内部类会自动继承外部类的属性,而不必正式建立继承。

Syntax

class outer:
   def __init__(self):
      pass
   class inner:
      def __init__(self):
         pass

使用内部类可以对类进行分组。嵌套类的优点之一就是可以轻而易举地搞清楚哪些类是相关的。内部类的作用域为局部作用域。它作为外部类的一个属性。

Example

在以下代码中,我们有 student 作为外部类,subjects 作为内部类。student 的 init () 构造器初始化 name 属性和 subjects 类的实例。另一方面,内部类 subjects 的构造器初始化两个实例变量 sub1、sub2。

外部类的 show() 方法调用内部类的方法,并传递已实例化的对象。

class student:
   def __init__(self):
      self.name = "Ashish"
      self.subs = self.subjects()
      return
   def show(self):
      print ("Name:", self.name)
      self.subs.display()
   class subjects:
      def __init__(self):
         self.sub1 = "Phy"
         self.sub2 = "Che"
         return
      def display(self):
         print ("Subjects:",self.sub1, self.sub2)

s1 = student()
s1.show()

执行此代码时,它将生成以下 output -

Name: Ashish
Subjects: Phy Che

完全有可能会独立地声明一个外部类的对象,并使用其自己的 display() 方法。

sub = student().subjects().display()

它会列出科目。

Python - Anonymous Class and Objects

Python 的内置 type() 函数会返回一个对象所属的类。在 Python 中,一个类,无论是内置类还是用户自定义类,都是 type 类的对象。

Example

class myclass:
   def __init__(self):
      self.myvar=10
      return

obj = myclass()

print ('class of int', type(int))
print ('class of list', type(list))
print ('class of dict', type(dict))
print ('class of myclass', type(myclass))
print ('class of obj', type(obj))

它将生成以下 output

class of int <class 'type'>
class of list <class 'type'>
class of dict <class 'type'>
class of myclass <class 'type'>

type() 有一个三参数版本,如下所示 −

Syntax

newclass=type(name, bases, dict)

使用上述语法,可以动态创建类。type 函数的三个参数是 −

  1. name − 类的名称,它将成为新类的 name 属性

  2. bases − 由父类组成的元组。如果不是派生类,则可以为空

  3. dict − 形成新类命名空间的字典,其中包含属性、方法及其值。

我们可以使用上述版本的 type() 函数创建一个匿名类。 name 参数为空字符串,第二个参数是包含一个类的元组,即对象类(请注意,Python 中的每个类都继承自对象类)。我们将某些实例变量作为第三个参数词典进行添加。目前,我们将其保留为空。

anon=type('', (object, ), {})

要创建此匿名类的对象 −

obj = anon()
print ("type of obj:", type(obj))

结果表明对象属于匿名类

type of obj: <class '__main__.'>

Example

我们也可以动态添加实例变量和实例方法。请看此示例 −

def getA(self):
   return self.a
obj = type('',(object,),{'a':5,'b':6,'c':7,'getA':getA,'getB':lambda self : self.b})()
print (obj.getA(), obj.getB())

它将生成以下 output

5 6

Python - Singleton Class

单例类是一个仅能创建单个对象的类。当您执行某些繁重操作时,比如创建数据库连接,这有助于优化内存使用。

Example

class SingletonClass:
   _instance = None

   def __new__(cls):
      if cls._instance is None:
         print('Creating the object')
         cls._instance = super(SingletonClass, cls).__new__(cls)
      return cls._instance

obj1 = SingletonClass()
print(obj1)

obj2 = SingletonClass()
print(obj2)

以上代码工作原理如下 -

当声明 Python 类的一个实例时,它在内部调用 () 方法。当您创建类的对象时,我们重写由 Python 在内部调用的 () 方法。它检查我们的实例变量是否为 None。如果实例变量为 None,它创建一个新对象并调用 super() 方法,然后返回包含该类对象的实例变量。

如果创建了多个对象,则很明显,对象仅在第一次创建时进行创建;之后,将返回相同的对象实例。

Creating the object
<__main__.SingletonClass object at 0x000002A5293A6B50>
<__main__.SingletonClass object at 0x000002A5293A6B50>

Python - Wrapper Classes

Python 中的一个函数是一个一阶对象。一个函数可以将另一个函数作为其参数,并在其内部封装另一个函数定义。这有助于修改一个函数而不实际更改它。此类函数称为装饰器。

此功能也可以用于封装一个类。此技术用于通过将类的逻辑封装在一个装饰器中,在实例化类后管理该类。

Example

def decorator_function(Wrapped):
   class Wrapper:
      def __init__(self,x):
         self.wrap = Wrapped(x)
      def print_name(self):
         return self.wrap.name
   return Wrapper

@decorator_function
class Wrapped:
   def __init__(self,x):
      self.name = x

obj = Wrapped('TutorialsPoint')
print(obj.print_name())

此处, 是要封装的类的名称。它作为参数传递给一个函数。在函数内部,我们有一个 Wrapper 类,通过传递的类的属性修改其行为,并返回修改后的类。对返回的类进行实例化,现在可以调用其方法。

执行此代码时,它将生成以下 output -

TutorialsPoint

Python - Enums

术语“枚举”指的是将固定的常量值分配给一组字符串的过程,从而可以通过与其绑定的值来识别每个字符串。Python 的标准库提供了 module。 module 中包含的 Enum 类用作定义一组标识符(通常写为大写)的枚举的父类。

Example 1

from enum import Enum

class subjects(Enum):
   ENGLISH = 1
   MATHS = 2
   SCIENCE = 3
   SANSKRIT = 4

在以上代码中,“subjects”是枚举。它有不同的枚举成员,例如,subjects.MATHS。每个成员都分配了一个值。

每个成员都是枚举类 subjects 的一个对象,并且具有 name 和 value 属性。

obj = subjects.MATHS
print (type(obj), obj.value)

它导致以下 output

<enum 'subjects'> 2

Example 2

绑定到枚举成员的值不必总是整数,它也可以是一个字符串。请参见以下示例 -

from enum import Enum

class subjects(Enum):
   ENGLISH = "E"
   MATHS = "M"
   GEOGRAPHY = "G"
   SANSKRIT = "S"

obj = subjects.SANSKRIT
print (type(obj), obj.name, obj.value)

它将生成以下 output

<enum 'subjects'> SANSKRIT S

Example 3

您可以按照枚举成员在定义中出现的顺序,借助 for 循环来迭代枚举成员 -

for sub in subjects:
   print (sub.name, sub.value)

它将生成以下 output

ENGLISH E
MATHS M
GEOGRAPHY G
SANSKRIT S

可以通过分配给枚举成员的唯一值或通过其 name 属性来访问枚举成员。因此, subjects("E") 和 subjects["ENGLISH"] 都将返回 subjects.ENGLISH 成员。

Example 4

一个枚举类不能有两个相同的成员出现,但是可以为多个成员分配相同的值。要确保每个成员都有一个唯一的绑定值,请使用 @@ 装饰器。

from enum import Enum, unique

@unique
class subjects(Enum):
   ENGLISH = 1
   MATHS = 2
   GEOGRAPHY = 3
   SANSKRIT = 2

这将引发以下异常 -

   @unique
    ^^^^^^
   raise ValueError('duplicate values found in %r: %s' %
ValueError: duplicate values found in <enum 'subjects'>: SANSKRIT -> MATHS

Enum 类是一个可调用类,因此您可以使用以下替代方法定义枚举 -

from enum import Enum
subjects = Enum("subjects", "ENGLISH MATHS SCIENCE SANSKRIT")

constructor 在此处使用两个参数。第一个是枚举的名称。第二个参数是一个由枚举成员符号名称组成的字符串,这些名称用空格分隔。

Python - Reflection

在面向对象编程中,反射是指提取正在使用的任何对象的信息的能力。您可以了解对象的类型、是否是任何其他类的子类、它的属性等多个方面。Python 的标准库具有许多用于反映对象的不同属性的函数。反射有时也称为自省。

让我们一起回顾一下反射函数。

The type() Function

我们已经多次使用过此函数。它会告诉你某个对象属于哪个类。

Example

以下语句打印不同内置数据类型对象的相应类

print (type(10))
print (type(2.56))
print (type(2+3j))
print (type("Hello World"))
print (type([1,2,3]))
print (type({1:'one', 2:'two'}))

在这里,你会得到以下 output

<class 'int'>
<class 'float'>
<class 'complex'>
<class 'str'>
<class 'list'>
<class 'dict'>

让我们验证一下用户自定义类对象的类型 -

class test:
   pass

obj = test()
print (type(obj))

它将生成以下 output

<class '__main__.test'>

The isinstance() Function

这是 Python 中另一个内置函数,它确定某个对象是否给定类的实例

Syntax

isinstance(obj, class)

此函数始终返回一个布尔值,如果该对象确实属于给定类,则返回 true,否则返回 false。

Example

以下语句返回 True -

print (isinstance(10, int))
print (isinstance(2.56, float))
print (isinstance(2+3j, complex))
print (isinstance("Hello World", str))

相反,这些语句打印 False。

print (isinstance([1,2,3], tuple))
print (isinstance({1:'one', 2:'two'}, set))

它将生成以下 output

True
True
True
True
False
False

你也可以使用用户自定义类进行检查

class test:
   pass

obj = test()
print (isinstance(obj, test))

它将生成以下 output

True

在 Python 中,即使类也是对象。所有类都是 object 类对象。这可以通过以下代码验证 -

class test:
   pass

print (isinstance(int, object))
print (isinstance(str, object))
print (isinstance(test, object))

以上所有 print 语句都打印 True。

The issubclass() Function

此函数检查某个类是否另一个类的子类。它属于类,而不是它们的实例。

如前所述,所有 Python 类都是 object 类的子类。因此,以下 print 语句的输出对于所有类而言都是 True。

class test:
   pass

print (issubclass(int, object))
print (issubclass(str, object))
print (issubclass(test, object))

它将生成以下 output

True
True
True

The callable() Function

如果某个对象调用某个进程,那么它就是可调用的。执行某个进程的 Python 函数就是可调用对象。因此,callable(function) 返回 True。任何函数(内置的、用户定义的或某个方法)都可调用。内置数据类型(如 int、str 等)对象是不可调用的。

Example

def test():
   pass

print (callable("Hello"))
print (callable(abs))
print (callable(list.clear([1,2])))
print (callable(test))

字符串对象是不可调用的。但 abs 是可调用的函数。列表的 pop 方法是可调用的,但 clear() 实际上是对函数的调用而不是函数对象,因此不可调用

它将生成以下 output

False
True
True
False
True

如果某个类实例具有 call () 方法,那么它是可调用的。在下例中,test 类包括 call () 方法。因此,它的对象可以使用,就像我们在调用函数一样。因此,具有 call () 函数的类的对象是可调用的。

class test:
   def __init__(self):
      pass
   def __call__(self):
      print ("Hello")

obj = test()
obj()
print ("obj is callable?", callable(obj))

它将生成以下 output

Hello
obj is callable? True

The getattr() Function

getattr() 内置函数检索对象已命名属性的值。

Example

class test:
   def __init__(self):
      self.name = "Manav"

obj = test()
print (getattr(obj, "name"))

它将生成以下 output

Manav

The setattr() Function

setattr() 内置函数向对象添加一个新的属性,并为其分配一个值。它还可以更改现有属性的值。

在下例中,test 类的对象具有一个属性 - 名称。我们使用 setattr 来添加年龄属性并修改名称属性的值。

class test:
   def __init__(self):
      self.name = "Manav"

obj = test()
setattr(obj, "age", 20)
setattr(obj, "name", "Madhav")
print (obj.name, obj.age)

它将生成以下 output

Madhav 20

The hasattr() Function

此内置函数在给定对象参数可以使用给定属性时返回 True,否则返回 False。我们使用相同的测试类,然后检查它是否有某个属性。

class test:
   def __init__(self):
      self.name = "Manav"

obj = test()
print (hasattr(obj, "age"))
print (hasattr(obj, "name"))

它将生成以下 output

False
True

The dir() Function

如果在未带有参数的情况下调用此内置函数,则返回当前作用域中的名称。对于任何对象作为参数,它都返回一个给定对象的属性以及由此对象可触及的属性的列表。

  1. For a module object − 该函数返回模块的属性。

  2. For a class object − 该函数返回其属性,以及递归返回其基类的属性。

  3. For any other object − 其属性,其类的属性,以及递归返回其类的基类的属性。

Example

print ("dir(int):", dir(int))

它将生成以下 output

dir(int): ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

Example

print ("dir(dict):", dir(dict))

它将生成以下 output

dir(dict): ['__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__ior__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

Example

class test:
   def __init__(self):
      self.name = "Manav"

obj = test()
print ("dir(obj):", dir(obj))

它将生成以下 output

dir(obj): ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']

Python - Syntax Errors

通常,计算机程序中会出现三种类型的错误:语法错误、逻辑错误和运行时错误。语法错误是编写程序时人们面临的最常见类型的错误,无论您是编程新手还是经验丰富的程序员,亦如此。语法错误基本上与特定语言的语法规则有关。

每当不遵循语言制定的规则时,就会出现语法错误。在 Python 中,为标识符(即变量、函数、类、模块或任何 Python 对象)命名制定了明确定义的规则。同样,应根据定义的语法使用 Python 关键字。只要不遵循这些规则,Python 解释器就会显示语法错误消息。

下面给出了在 Python 交互式 shell 中声明变量的一个简单示例。

>>> name="Python
   File "<stdin>", line 1
      name="Python
           ^
SyntaxError: unterminated string literal (detected at line 1)

Python 解释器将显示语法错误以及某个解释性消息。在上面的示例中,由于引号未闭合,因此出现语法错误。

同样,Python 要求每个函数名称随后跟上圆括号,函数参数应放在圆括号内。

在下例中,我们得到一个语法错误 −

>>> print "Hello"
   File "<stdin>", line 1
      print "Hello"
      ^^^^^^^^^^^^^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?

原因可以从错误消息中得知,即 print() 函数缺少圆括号。

有许多流行的用于 Python 编程的 IDE。其中大部分都使用颜色化语法高亮,这使得轻松通过视觉识别错误得以实现。

一个此类 IDE 是 VS Code 。输入指令时,会适当地突出显示语法错误。

syntax error

错误被突出显示。如果您将光标放在那里,VS Code 将详细说明该错误。如果您继续执行该代码,错误信息将显示在命令终端中。

语法错误很容易识别和纠正。VS Code 等 IDE 使此过程变得十分容易。但是,有时,您的代码不会显示任何语法错误,但程序的输出仍然不是您预期的。此类错误是逻辑错误。它们很难检测,因为错误存在于代码中使用的逻辑中。您将通过经验学会如何更正逻辑错误。VS Code 和其他 IDE 具有监视和断点等特性来捕捉这些错误。

第三种类型的错误是运行时错误,也称为异常。您的程序中既没有语法错误,也没有任何逻辑错误。大多数情况下,程序给出的输出是期望的,但在一些特定情况下,程序表现异常,例如程序异常终止或给出一些荒谬的结果。

导致异常的因素通常在程序外部。例如,不正确的输入、类型转换或 IO 设备故障等。

What is Exception?

异常是一种事件,它在程序执行期间发生,会中断程序指令的正常流。通常情况下,当 Python 脚本遇到无法处理的情况时,它会引发异常。异常是表示错误的 Python 对象。

当 Python 脚本引发异常时,它必须立即处理该异常,否则它将终止并退出。

Python 的标准库定义了标准异常类别。与其他 Python 类一样,Exceptions 也是 Object 类的子类。以下是 Python Exceptions 的对象层次结构。

object
   BaseException
      Exception
         ArithmeticError
            FloatingPointError
            OverflowError
            ZeroDivisionError
         AssertionError
         AttributeError
         BufferError
         EOFError
         ImportError
            ModuleNotFoundError
         LookupError
            IndexError
            KeyError
         MemoryError
         NameError
         OSError
         ReferenceError
         RuntimeError
         StopAsyncIteration
         StopIteration
         SyntaxError

Python - Exceptions Handling

如果您有一些可能引发异常的可疑代码,您可以通过将可疑代码放置在 try :块中来防御您的程序。在 try :块后面,包含一个 except :语句,后面是一个以尽可能优雅的方式处理问题的代码块。

  1. try :块包含可能导致异常的语句

  2. 如果发生异常,程序将跳到 except :块。

  3. 如果 try :块中没有异常,则 except :块将被跳过。

Syntax

以下是 try…​except…​else 块的简单语法 −

try:
   You do your operations here
   ......................
except ExceptionI:
   If there is ExceptionI, then execute this block.
except ExceptionII:
   If there is ExceptionII, then execute this block.
   ......................
else:
   If there is no exception then execute this block.

以下关于上述语法是几个重要要点 −

  1. 单个 try 语句可以有许多 except 语句。当 try 块包含可能引发不同类型异常的语句时,这很有用。

  2. 您还可以提供一个通用的 except 子句,它可以处理任何异常。

  3. 在 except 子句之后,您可以包含一个 else 子句。如果 try: 块中的代码不引发异常,则 else 块中的代码将执行。

  4. else 代码块适用于无需 try: 代码块保护的代码。

Example

此示例将打开一个文件,在该文件中写内容,并优雅地退出,因为根本不存在任何问题。

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print ("Error: can\'t find file or read data")
else:
   print ("Written content in the file successfully")
   fh.close()

它将生成以下 output

Written content in the file successfully

但是,将 open() 函数中的模式参数更改为“w”。如果 testfile 尚不存在,则程序在 except 代码块中会遇到 IOError,并打印以下错误消息:

Error: can't find file or read data

Python - The try-except Block

还可以使用 except 语句,如下所示,而不定义任何异常 −

try:
   You do your operations here
   ......................
except:
   If there is any exception, then execute this block.
   ......................
else:
   If there is no exception then execute this block.

这种try-except语句会捕获发生的所有异常。但使用这种try-except语句并不被认为是良好的编程实践,因为它会捕获所有异常,但不会让程序员识别可能发生的根源。

你还可以使用相同的 except 语句来处理多个异常,如下所示:

try:
   You do your operations here
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list,
   then execute this block.
   ......................
else:
   If there is no exception then execute this block.

Python - The try-finally Block

可以使用 finally :块与 try :块配合使用。 finally :块是放置必须执行的任何代码的地方,无论try区块是否引发了异常。

try-finally 语句的语法如下 −

try:
   You do your operations here;
   ......................
   Due to any exception, this may be skipped.
finally:
   This would always be executed.
   ......................

Note − 可以提供except语句或finally语句,但不能同时提供。也不能在finally语句中使用else语句。

Example

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
finally:
   print ("Error: can\'t find file or read data")
   fh.close()

如果您没有以写模式打开文件的权限,那么它将生成以下 output

Error: can't find file or read data

相同的示例可以更简洁地写为如下 −

try:
   fh = open("testfile", "w")
   try:
      fh.write("This is my test file for exception handling!!")
   finally:
      print ("Going to close the file")
      fh.close()
except IOError:
   print ("Error: can\'t find file or read data")

try 块中引发异常时,执行立即传递到 finally 块。 finally 块中的所有语句执行完成后,重新引发异常,并在 try-except 语句的下一个较高层存在时在 except 语句中处理。

Exception with Arguments

异常可以具有一个参数,它是一个关于问题提供附加信息的值。参数的内容根据异常而有所不同。你通过如下在 except 子句中提供一个变量来捕获异常的参数:

try:
   You do your operations here
   ......................
except ExceptionType as Argument:
   You can print value of Argument here...

如果编写代码来处理单个异常,则可以在 except 语句中让一个变量跟在异常名称后面。如果正在捕捉多个异常,则可以让一个变量跟在异常元组的后面。

此变量接收异常的值,该值大多包含异常的成因。此变量可以接收单个值,或以元组形式接收多个值。此元组通常包含错误字符串、错误号和错误位置。

Example

下面是一个处理单个异常的示例:

# Define a function here.
def temp_convert(var):
   try:
      return int(var)
   except ValueError as Argument:
      print("The argument does not contain numbers\n",Argument)
# Call above function here.
temp_convert("xyz")

它将生成以下 output

The argument does not contain numbers
invalid literal for int() with base 10: 'xyz'

Python - Raising Exceptions

可以通过使用raise语句以多种方式引发异常。raise语句的一般语法如下 −

Syntax

raise [Exception [, args [, traceback]]]

在此处,Exception 是异常类型(例如,NameError),而 argument 是异常参数值。argument 是可选的;如果不提供,则异常参数为 None。

最后一个参数traceback也是可选的(实际中很少使用),如果存在,则是用于异常的traceback对象。

Example

异常可以是字符串、类或对象。Python 核心触发的异常大部分都是类,而参数则是类的实例。定义新异常非常简单,可以像下面这样操作:

def functionName( level ):
   if level <1:
      raise Exception(level)
      # The code below to this would not be executed
      # if we raise the exception
   return level

Note − 为了捕获异常,“except”语句必须引用作为类对象或简单字符串抛出的相同异常。例如,为了捕获上述异常,我们必须按如下方式编写except语句 −

try:
   Business Logic here...
except Exception as e:
   Exception handling here using e.args...
else:
   Rest of the code here...

下面的示例说明了引发异常的用法 −

def functionName( level ):
   if level <1:
      raise Exception(level)
      # The code below to this would not be executed
      # if we raise the exception
   return level

try:
   l=functionName(-10)
   print ("level=",l)
except Exception as e:
   print ("error in level argument",e.args[0])

这将产生以下 output

error in level argument -10

Python - Exception Chaining

异常链是一个通过在新的异常中封装捕获的异常后重新引发捕获的异常来处理异常的技术。原始异常被保存为新异常的属性(例如cause)。

在处理一个异常“A”期间,可能会发生另一个异常“B”。了解这两个异常对于调试问题很有用。有时对于异常处理程序故意重新引发异常是有用的,以提供额外的信息或将异常转换为另一种类型。

在Python 3.x中,可以实现异常链。如果except部分内有任何未处理的异常,它将处理正在处理的异常附加到它并包含在错误消息中。

Example

在下面的代码片段中,尝试打开一个不存在的文件会引发FileNotFoundError。它是由except块检测到的。在处理时引发了另一个异常。

try:
   open("nofile.txt")
except OSError:
   raise RuntimeError("unable to handle error")

它将生成以下 output

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 2, in <module>
open("nofile.txt")
FileNotFoundError: [Errno 2] No such file or directory: 'nofile.txt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 4, in <module>
    raise RuntimeError("unable to handle error")
RuntimeError: unable to handle error

raise . . from

如果在raise语句中使用可选的from子句,则表示异常是另一个异常的直接后果。当转换异常时,这一点很有用。from关键字之后的标记应该是异常对象。

try:
   open("nofile.txt")
except OSError as exc:
   raise RuntimeError from exc

它将生成以下 output

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 2, in <module>
    open("nofile.txt")
FileNotFoundError: [Errno 2] No such file or directory: 'nofile.txt'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 4, in <module>
    raise RuntimeError from exc
RuntimeError

raise . . from None

如果我们在from子句中使用None代替异常对象,则会禁用较早示例中找到的自动异常链。

try:
   open("nofile.txt")
except OSError as exc:
   raise RuntimeError from None

它将生成以下 output

Traceback (most recent call last):
 File "C:\Python311\hello.py", line 4, in <module>
  raise RuntimeError from None
RuntimeError

context and cause

在except块中引发异常会自动将捕获的异常添加到新异常的 context 属性。同样,还可以使用 raise …​ from 语法向任何异常添加 cause

try:
   try:
      raise ValueError("ValueError")
   except ValueError as e1:
      raise TypeError("TypeError") from e1
except TypeError as e2:
   print("The exception was", repr(e2))
   print("Its __context__ was", repr(e2.__context__))
   print("Its __cause__ was", repr(e2.__cause__))

它将生成以下 output

The exception was TypeError('TypeError')
Its __context__ was ValueError('ValueError')
Its __cause__ was ValueError('ValueError')

Python - Nested try Block

在一个Python程序中,如果另一个 try-except 构造位于 try 块或其 except 块内,则称为嵌套try块。当不同的块(如外部块和内部块)可能导致不同的错误时,就需要这样做。为了处理它们,我们需要嵌套的try块。

我们从一个具有单个“try - except- finally”构造的示例开始。如果try内部的语句遇到异常,它将由except块处理。无论是否发生异常,finally块总是执行。

Example 1

在这里, try 块有“除以 0”的情况,因此 except 块派上用场了。它配备了一致处理带有 Exception 类的通用异常。

a=10
b=0
try:
   print (a/b)
except Exception:
   print ("General Exception")
finally:
   print ("inside outer finally block")

它将生成以下 output

General Exception
inside outer finally block

Example 2

我们现在来看如何嵌套 try 结构。我们在现有的 try 块中放置另一个“try − except − finally”块。内部 try 的 except 关键词现在处理通用异常,而我们要求外部 try 的 except 块处理 ZeroDivisionError。

因为 try 块中没有发生异常,所以不会调用其对应的通用 Except。由外部 except 从句处理除以 0 的情况。

a=10
b=0
try:
   print (a/b)
   try:
      print ("This is inner try block")
   except Exception:
      print ("General exception")
   finally:
      print ("inside inner finally block")

except ZeroDivisionError:
   print ("Division by 0")
finally:
   print ("inside outer finally block")

它将生成以下 output

Division by 0
inside outer finally block

Example 3

现在,我们逆转这种情况。在嵌套的 try 块之外,外部块没有任何异常引发,但是导致除以 0 的语句在内部 try 内,因此由内部 except 块处理异常。显然,将不会调用对应于外部 tryexcept 部分。

a=10
b=0
try:
   print ("This is outer try block")
   try:
      print (a/b)
   except ZeroDivisionError:
      print ("Division by 0")
   finally:
      print ("inside inner finally block")

except Exception:
   print ("General Exception")
finally:
   print ("inside outer finally block")

它将生成以下 output

This is outer try block
Division by 0
inside inner finally block
inside outer finally block

最后,我们来讨论在嵌套块中可能发生的另一种情况。虽然在外部 try 中没有异常,但是没有合适的 except 块来处理内部 try 中的异常。

Example 4

在以下示例中,内部 try 面临“除以 0”,但其对应的 except: 寻找 KeyError 而不是 ZeroDivisionError。因此,异常对象会传递给后续 except 语句的 except: 块,该 except 语句与外部 try: 语句相匹配。在那里,zeroDivisionError 异常被捕获并处理。

a=10
b=0
try:
   print ("This is outer try block")
   try:
      print (a/b)
   except KeyError:
      print ("Key Error")
   finally:
      print ("inside inner finally block")

except ZeroDivisionError:
   print ("Division by 0")
finally:
   print ("inside outer finally block")

它将生成以下 output

This is outer try block
inside inner finally block
Division by 0
inside outer finally block

Python - User-Defined Exceptions

Python 还允许你通过从标准内置异常派生类来创建自己的异常。

这是一个带有用户定义的 MyException 类的示例。在这里,创建了从基本 Exception 类派生的类。当捕获到异常时,在需要显示更具体信息时,此类很有用。

try 块中,只要 num 变量的值小于 0 或大于 100,就会引发用户定义的异常并在 except 块中捕获。变量 e 用于创建 MyException 类的实例。

Example

class MyException(Exception):
   "Invalid marks"
   pass

num = 10
try:
   if num <0 or num>100:
      raise MyException
except MyException as e:
   print ("Invalid marks:", num)
else:
   print ("Marks obtained:", num)

Output

对于 num 的不同值,程序显示以下 output

Marks obtained: 10
Invalid marks: 104
Invalid marks: -10

Python - Logging

术语“日志记录”是指在特定过程中记录不同中间事件的机制。在软件应用程序中记录日志被证明有助于开发人员调试和跟踪应用程序逻辑中的错误。Python 的标准库包含 logging 模块,可使用该模块生成和记录应用程序日志。

通常的做法是在程序中间歇性地使用 print() 语句来检查不同变量和对象的中间值。它帮助开发人员验证程序是否按预期运行。然而,日志记录比间歇性 print 语句更有益,因为它提供了对事件的更多见解。

Logging Levels

日志记录的一个重要功能是你能够生成具有不同严重级别的日志消息。日志记录模块通过其值定义以下级别。

Example

以下代码说明如何生成日志消息。

import logging

logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

它将生成以下 output

WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message

请注意,这里仅显示 WARNING 级别之后的日志消息。这是因为 root - 默认的记录器忽略了 WARNING 严重级别之上的所有严重级别。注意,严重级别记录在每行的第一個冒号 (:) 之前。类似,记录器的名称 root 也显示在 LogRecord 中。

Logging Configuration

程序生成的日志可以使用 BasicConfig() 方法进行自定义。您可以为以下参数之一或多个定义一个或多个配置 −

  1. filename − 指定创建一个 FileHandler,使用指定的文件名,而不是 StreamHandler。

  2. filemode − 如果指定了 filename,则以这种模式打开文件。默认为 'a'。

  3. datefmt − 使用 time.strftime() 接受的指定日期/时间格式。

  4. style − 如果指定了 format,则将此样式用于格式化字符串。分别代表 printf 样式、str.format() 或 string.Template 的“%”、“{”或“$”之一。默认为“%”。

  5. level − 将根日志级别设置为指定级别。

  6. errors − 如果此关键字参数与 filename 一起指定,则在创建 FileHandler 时使用其值,因此在打开输出文件时使用。如果未指定,则使用值backslashreplace。请注意,如果指定 None,它将按原样传递给 open(),这意味着它将与传递errors的效果相同。

Example

要记录 DEBUG 级别以上的所有消息,请将级别参数设置为 logging.DEBUG

import logging

logging.basicConfig(level=logging.DEBUG)
logging.debug('This message will get logged')

它将生成以下 output

DEBUG:root:This message will get logged

要将日志消息记录在文件中而不是在控制台上回显它们,请使用 filename 参数。

import logging

logging.basicConfig(filename='logs.txt', filemode='w', level=logging.DEBUG)
logging.warning('This messagewill be saved to a file')

控制台上不会显示任何输出。但是,在当前目录中创建了一个 logs.txt 文件,其中包含文本 WARNING:root:This message will be saved to a file

Variable Data in L ogging M essage

大多数情况下,您希望在日志消息中包含一个或多个变量的值,以深入了解应用程序运行时生成错误的原因。为此,可以使用字符串格式化技术,例如 str 类的 format() 方法或 f 字符串。

Example

import logging

logging.basicConfig(level=logging.DEBUG)
marks = 120
logging.error("Invalid marks:{} Marks must be between 0 to 100".format(marks))
subjects = ["Phy", "Maths"]
logging.warning("Number of subjects: {}. Should be at least three".format(len(subjects)))

它将生成以下 output

ERROR:root:Invalid marks:120 Marks must be between 0 to 100
WARNING:root:Number of subjects: 2. Should be at least three

Python - Assertions

断言是一种健全检查,当您完成对程序的测试后,您可以将其开启或关闭。

  1. 最简单的考虑 assertions 的方法是将其比作 raise-if 语句(更准确地说,是 raise-if-not 语句)。测试表达式,如果结果为 false,则引发异常。

  2. assertions 由 assert 语句执行,这是 Python 中最新的关键字,在 1.5 版中引入。

  3. 程序员经常在函数开始时放置断言来检查有效输入,并在函数调用后检查有效输出。

The assert Statement

当遇到 assert 语句时,Python 会计算随附的表达式,希望它为真。如果表达式为假,Python 会引发 AssertionError 异常。

assert 的 syntax 是 −

assert Expression[, Arguments]

如果 assertion 失败,Python 将 ArgumentExpression 作为 AssertionError 的参数使用。AssertionError 异常可以像使用 try-except 语句的其他异常一样捕获和处理。如果不处理它们,它们将终止程序并产生回溯。

Example

print ('enter marks out of 100')
num=75
assert num>=0 and num<=100
print ('marks obtained: ', num)

num=125
assert num>=0 and num<=100
print ('marks obtained: ', num)

它将生成以下 output

enter marks out of 100
marks obtained: 75
Traceback (most recent call last):
 File "C:\Users\user\example.py", line 7, in <module>
  assert num>=0 and num<=100
                    ^^^^^^^^
AssertionError

要在 assert 语句中显示自定义错误消息,请在表达式后面放置一个字符串 −

assert num>=0 and num<=100, "only numbers in 0-100 accepted"

AssertionError 也是一个内置异常。因此它可以用作 except 块中的参数。当输入导致 AssertionError 异常时,它将由 except 块处理。except 块将 assert 语句中的字符串视为异常对象。

try:
   num=int(input('enter a number'))
   assert (num >=0), "only non negative numbers accepted"
   print (num)
except AssertionError as msg:
   print (msg)

Python - Built-in Exceptions

下面是 Python 中提供的标准异常列表:

以下是标准异常的一些示例 -

IndexError

在尝试访问无效索引的项目时显示。

numbers=[10,20,30,40]
for n in range(5):
   print (numbers[n])

它将生成以下 output

10
20
30
40
Traceback (most recent call last):

   print (numbers[n])
IndexError: list index out of range

ModuleNotFoundError

模块未找到时显示。

import notamodule
Traceback (most recent call last):

   import notamodule
ModuleNotFoundError: No module named 'notamodule'

KeyError

字典键未找到时出现。

D1={'1':"aa", '2':"bb", '3':"cc"}
print ( D1['4'])
Traceback (most recent call last):

   D1['4']
KeyError: '4'

ImportError

当指定的函数不可导入时显示。

from math import cube
Traceback (most recent call last):

   from math import cube
ImportError: cannot import name 'cube'

StopIteration

当迭代器流耗尽后调用 next() 函数时出现此错误。

.it=iter([1,2,3])
next(it)
next(it)
next(it)
next(it)
Traceback (most recent call last):

   next(it)
StopIteration

TypeError

当操作符或函数应用于不适当类型对象时显示。

print ('2'+2)
Traceback (most recent call last):

   '2'+2
TypeError: must be str, not int

ValueError

函数参数类型不当时显示。

print (int('xyz'))
Traceback (most recent call last):

   int('xyz')
ValueError: invalid literal for int() with base 10: 'xyz'

NameError

当找到对象时遇到此错误。

print (age)
Traceback (most recent call last):

   age
NameError: name 'age' is not defined

ZeroDivisionError

除数为零时显示。

x=100/0
Traceback (most recent call last):

   x=100/0
ZeroDivisionError: division by zero

KeyboardInterrupt

当用户在程序执行期间按正常中断键(通常为 Control-C)时。

name=input('enter your name')
enter your name^c
Traceback (most recent call last):

   name=input('enter your name')
KeyboardInterrupt

Python - Multithreading

默认情况下,计算机程序从头到尾以顺序方式执行指令。多线程是指将主任务划分为多个子任务并以重叠方式执行它们的机制。与单线程相比,这使执行速度更快。

操作系统能够同时处理多个进程。它为每个进程分配一个单独的内存空间,以便一个进程不能访问或写入其他进程的空间。另一方面,线程可以被认为是单个程序中的一个轻量级子进程。单个程序的线程共享分配给它的内存空间。

进程中的多个线程与主线程共享相同的数据空间,因此比作为独立进程时更容易共享信息或相互通信。

由于它们是轻量级的,不需要大量的内存开销;它们比进程更便宜。

multithreading

一个进程总是从一个线程(主线程)开始。根据需要,可以启动一个新线程并委派子任务给它。现在这两个线程正在以重叠的方式工作。当分配给辅助线程的任务完成后,它会与主线程合并。

Python - Thread Life cycle

线程对象会经历不同的阶段。创建新的线程对象时,必须启动它。这将调用线程类的 run() 方法。此方法包含新线程执行的进程的逻辑。线程在 run() 方法结束后完成其任务,新创建的线程与主线程合并。

当一个线程正在运行时,它可能会暂停一段时间或可能被要求暂停,直到发生某个事件。指定时间间隔过后或进程结束后,线程就会恢复。

thread life cycle

Python 的标准库有两个模块,“_thread”和“threading”,它们包括处理线程的功能。“_thread”模块是一个低级 API。在 Python 3 中已包含 threading module ,它为线程管理提供了更全面的功能。

Python The _thread Module

_thread 模块(早期的 thread 模块)自 2 版以来一直是 Python 标准库的一部分。它是线程管理的低级 API,并作为许多其他高级并发执行功能的模块(如 threading 和 multiprocessing)的支持。

Python - The threading Module

较新的 threading 模块为线程管理提供了更强大、更高级别的支持。

Thread 类表示在一个单独的控制线程中运行的活动。有两种指定活动的方式:向构造函数传递可调用对象或在子类中重写 run() 方法。

threading.Thread(target, name, args, kwarg, daemon)

Parameters

  1. target − 在新的线程开始时调用的函数。默认为空值,表示不调用任何函数。

  2. name − 是线程的名称。默认情况下,它会构造一个唯一名称,比如“Thread-N”。

  3. daemon – 如果设置为 True,新的线程则在后台运行。

  4. args and kwargs − 传递给目标函数的可选参数。

Python - Creating a Thread

start_new_thread() 中包含的 _thread module 函数用于在正在运行的程序中创建一个新线程。

Syntax

_thread.start_new_thread ( function, args[, kwargs] )

此函数会启动一个新线程并返回其标识符。

Parameters

  1. function − 新创建的线程开始运行并调用指定函数。如果函数需要任何参数,可以将其作为参数 args 和 kwargs 传递。

Example

import _thread
import time
# Define a function for the thread
def thread_task( threadName, delay):
   for count in range(1, 6):
      time.sleep(delay)
      print ("Thread name: {} Count: {}".format ( threadName, count ))

# Create two threads as follows
try:
   _thread.start_new_thread( thread_task, ("Thread-1", 2, ) )
   _thread.start_new_thread( thread_task, ("Thread-2", 4, ) )
except:
   print ("Error: unable to start thread")

while True:
   pass

它将生成以下 output

Thread name: Thread-1 Count: 1
Thread name: Thread-2 Count: 1
Thread name: Thread-1 Count: 2
Thread name: Thread-1 Count: 3
Thread name: Thread-2 Count: 2
Thread name: Thread-1 Count: 4
Thread name: Thread-1 Count: 5
Thread name: Thread-2 Count: 3
Thread name: Thread-2 Count: 4
Thread name: Thread-2 Count: 5
Traceback (most recent call last):
 File "C:\Users\user\example.py", line 17, in <module>
  while True:
KeyboardInterrupt

该程序进入一个无限循环。你必须按“Ctrl-C”才能停止。

Python - Starting a Thread

start() 方法启动线程的活动。在创建线程对象后,必须调用它一次。

start() 方法会在一个单独的线程中自动调用对象的 run() 方法。但是,如果调用该方法的次数超过一次,则会引发 RuntimeError。

Syntax

以下是使用 start() 方法启动线程的语法 −

threading.thread.start()

Example

请看以下示例:

thread1 = myThread("Thread-1")

# Start new Thread
thread1.start()

这会自动调用 run() 方法。

The run() Method

run() 方法表示该线程的活动。它可以在子类中重写。对象不会调用标准的 run() 方法,而是调用作为 target 参数传给其构造函数的函数。

Python - Joining the Threads

线程类中的 join() 方法会阻塞调用线程,直到调用其 join() 方法的线程中止。终止可以是正常的,也可以是由于未处理的异常而终止的,或者直到可选超时发生为止。可以多次调用它。如果尝试加入当前线程,join() 会引发 RuntimeError。在启动之前尝试加入线程也会引发相同的异常。

Syntax

thread.join(timeout)

Parameters

  1. timeout − 它应该是指定超时时间的浮点数,用于阻塞线程。

join() 方法始终返回 None。你必须在 join() 后调用 is_alive() 来判断是否发生超时 − 如果线程仍然处于活动状态,则 join() 调用超时。当没有超时参数或超时参数为 None 时,该操作将阻塞,直至线程终止。

线程可以多次被加入。

Example

thread1.start()
thread2.start()
thread1.join()
thread2.join()

is_alive() method

此方法返回线程是否处于活动状态。它在调用 run() 方法前和 run() 方法终止后返回 True。

Python - Naming the Threads

线程名称仅用于标识目的,在语义方面没有作用。多个线程可能具有相同名称。可以在thread()构造函数中将线程名指定为参数之一。

thread(name)

此处 name 是线程名。默认情况下,将构造一个唯一名称,例如“Thread-N”。

线程对象还具有一个属性对象,用于线程名称属性的 getter 和 setter 方法。

thread.name = "Thread-1"

The daemon Property

布尔值,指示此线程是守护线程(True)还是否(False)。必须在调用 start() 之前设置此值。

Example

要使用 threading 模块实现新线程,您需要执行以下操作:

  1. a. 定义 Thread 类的子类。

  2. b. 覆盖 init (self [,args]) 方法添加其他参数。

  3. c. 然后覆盖 run(self [,args]) 方法以实现线程启动后要做的事情。

创建新 Thread 子类后,您可以创建其实例,然后通过调用 start() 启动新线程,start() 依次调用 run() 方法。

import threading
import time
class myThread (threading.Thread):
   def __init__(self, name):
      threading.Thread.__init__(self)
      self.name = name

   def run(self):
      print ("Starting " + self.name)
      for count in range(1,6):
         time.sleep(5)
         print ("Thread name: {} Count: {}".format ( self.name, count ))
      print ("Exiting " + self.name)

# Create new threads
thread1 = myThread("Thread-1")
thread2 = myThread("Thread-2")

# Start new Threads
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("Exiting Main Thread")

它将生成以下 output

Starting Thread-1
Starting Thread-2
Thread name: Thread-1 Count: 1
Thread name: Thread-2 Count: 1
Thread name: Thread-1 Count: 2
Thread name: Thread-2 Count: 2
Thread name: Thread-1 Count: 3
Thread name: Thread-2 Count: 3
Thread name: Thread-1 Count: 4
Thread name: Thread-2 Count: 4
Thread name: Thread-1 Count: 5
Exiting Thread-1
Thread name: Thread-2 Count: 5
Exiting Thread-2
Exiting Main Thread

Python - Thread Scheduling

Python 在一个程序中支持多线程。一个多线程程序可以独立地执行多个子任务,这允许并行执行任务。

Python 解释器将 Python 线程请求映射到 POSIX/pthreads 或 Windows 线程。因此,与普通线程类似,Python 线程由主机操作系统处理。

但是,Python 解释器不支持线程调度。因此,使用 Python 解释器无法实现线程优先级、调度方案和线程抢占。Python 线程的调度和上下文切换由主机调度程序处置。

Python 确实具有一定程度的任务调度支持,形式为调度模块作为标准库。它可用于创建机器人程序和其他监视和自动化应用程序。 sched 模块实现了一个通用事件调度程序,用于在特定时间运行任务。它提供了类似于 Windows 或 Linux 中的任务计划程序的工具。

调度器类在 sched 内置模块中定义。

scheduler(timefunc=time.monotonic, delayfunc=time.sleep)

调度器类中定义的方法包括:

  1. scheduler.enter() - 可以安排在延迟或特定时间后运行事件。要安排延迟,可以使用 enter() 方法。

  2. scheduler.cancel() - 从队列中移除事件。如果事件不是当前队列中的事件,此方法将引发 ValueError。

  3. scheduler.run(blocking=True) - 运行所有已调度事件。

可以安排在延迟或特定时间后运行事件。要安排延迟,请使用 enter() 方法,它需要四个参数。

  1. 一个代表延迟的数字

  2. A priority value

  3. The function to call

  4. 一个针对函数的参数元组

Example 1

此示例调度两个不同的事件 −

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def schedule_event(name, start):
   now = time.time()
   elapsed = int(now - start)
   print('elapsed=',elapsed, 'name=', name)

start = time.time()
print('START:', time.ctime(start))
scheduler.enter(2, 1, schedule_event, ('EVENT_1', start))
scheduler.enter(5, 1, schedule_event, ('EVENT_2', start))

scheduler.run()

它将生成以下 output

START: Mon Jun 5 15:37:29 2023
elapsed= 2 name= EVENT_1
elapsed= 5 name= EVENT_2

Example 2

我们再举一个例子来更好地理解该概念 −

import sched
from datetime import datetime
import time

def addition(a,b):
   print("Performing Addition : ", datetime.now())
   print("Time : ", time.monotonic())
   print("Result : ", a+b)

s = sched.scheduler()

print("Start Time : ", datetime.now())

event1 = s.enter(10, 1, addition, argument = (5,6))
print("Event Created : ", event1)
s.run()
print("End Time : ", datetime.now())

它将生成以下 output

Start Time : 2023-06-05 15:49:49.508400
Event Created : Event(time=774087.453, priority=1, sequence=0, action=<function addition at 0x000001FFE71A1080>, argument=(5, 6), kwargs={})
Performing Addition : 2023-06-05 15:49:59.512213
Time : 774087.484
Result : 11
End Time : 2023-06-05 15:49:59.559659

Python - Thread Pools

What is a Thread Pool?

线程池是一种自动管理工作线程池的机制。池中的每个线程称为一个工作线程。任务完成后可以重新使用工作线程。一个线程一次只能执行一个任务。

一个线程池控制着何时创建线程,以及未使用的线程应该做什么。

使用线程池比手动启动、管理和关闭线程的效率要高很多,尤其是对于很多任务。

Python 中的多线程同时执行某个函数。通过 ThreadPoolExecutor 在 concurrent.futures 模块中定义的类可以实现多线程异步执行函数。

concurrent.futures 模块包含 Future 类和两个 Executor 类 − ThreadPoolExecutor 和 ProcessPoolExecutor。

The Future Class

concurrent.futures.Future 类负责处理任何可调用的异步执行,例如一个函数。要获取 Future 类的对象,你应该在任何 Executor 对象上调用 submit() 方法。它不应该直接通过其构造函数创建。

Future 类中的重要方法是:

result(timeout=None)

此方法返回由调用返回的值。如果调用尚未完成,此方法会等待最长 timeout 秒。如果调用未在 timeout 秒内完成,则会引发 TimeoutError。如果未指定超时,则等待时间不受限制。

cancel()

此方法会尝试取消调用。如果调用当前正在执行或完成运行并且无法取消,则该方法将返回 False,否则调用将被取消并且该方法将返回 True。

cancelled()

如果成功取消调用,此方法返回 True。

running()

如果调用当前正在执行且无法取消,此方法返回 True。

done()

如果成功取消调用或完成运行,此方法返回 True。

The ThreadPoolExecutor Class

此类代表一个指定数量的最大工作线程池,以异步执行调用。

concurrent.futures.ThreadPoolExecutor(max_threads)

Example

from concurrent.futures import ThreadPoolExecutor
from time import sleep
def square(numbers):
   for val in numbers:
      ret = val*val
      sleep(1)
      print("Number:{} Square:{}".format(val, ret))
def cube(numbers):
   for val in numbers:
      ret = val*val*val
      sleep(1)
      print("Number:{} Cube:{}".format(val, ret))
if __name__ == '__main__':
   numbers = [1,2,3,4,5]
   executor = ThreadPoolExecutor(4)
   thread1 = executor.submit(square, (numbers))
   thread2 = executor.submit(cube, (numbers))
   print("Thread 1 executed ? :",thread1.done())
   print("Thread 2 executed ? :",thread2.done())
   sleep(2)
   print("Thread 1 executed ? :",thread1.done())
   print("Thread 2 executed ? :",thread2.done())

它将生成以下 output

Thread 1 executed ? : False
Thread 2 executed ? : False
Number:1 Square:1
Number:1 Cube:1
Number:2 Square:4
Number:2 Cube:8
Thread 1 executed ? : False
Thread 2 executed ? : False
Number:3 Square:9
Number:3 Cube:27
Number:4 Square:16
Number:4 Cube:64
Number:5 Square:25
Number:5 Cube:125
Thread 1 executed ? : True
Thread 2 executed ? : True

Python - Main Thread

每个 Python 程序至少有一个执行线程称为 main thread 。默认情况下, main thread 是一个非守护线程。

有时,我们可能需要在程序中创建额外的线程,以同时执行代码。

以下是用于创建新线程的 syntax

object = threading.Thread(target, daemon)

Thread() 构造函数创建一个新对象。通过调用 start() 方法,新线程开始运行,它自动调用作为参数传递给 target 参数(默认为 run )的函数。第二个参数是 “daemon”,默认为 None。

Example

from time import sleep
from threading import current_thread
from threading import Thread

# function to be executed by a new thread
def run():
   # get the current thread
   thread = current_thread()
   # is it a daemon thread?
   print(f'Daemon thread: {thread.daemon}')

# create a new thread
thread = Thread(target=run)

# start the new thread
thread.start()

# block for a 0.5 sec
sleep(0.5)

它将生成以下 output

Daemon thread: False

因此,通过以下语句创建一个线程 −

t1=threading.Thread(target=run)

此语句会创建一个非守护程序线程。开始后,它会调用 run() 方法。

Python - Thread Priority

当必须在多个线程之间安全地交换信息时,Python 标准库中的 queue 模块在多线程编程中非常有用。此模块中的优先级队列类实现了所有必需的锁定语义。

对于优先级队列,条目是有序的(使用 heapq 模块),第一个检索到的条目是值最低的条目。

Queue 对象具备以下方法来控制队列−

  1. get() − get() 从队列中删除并返回一个项。

  2. put() − put 向队列中添加项。

  3. qsize() − qsize() 返回队列中当前的项数。

  4. empty() − empty( ) 如果队列为空,则返回 True;否则返回 False。

  5. full() −full() 如果队列已满则返回 True;否则,返回 False。

queue.PriorityQueue(maxsize=0)

这是用于优先级队列的构造函数。maxsize 为一个整数,用于设定可存入队列的条目数量上限。如果 maxsize 等于或小于零,则队列大小为无限。

首先检索到值最低的条目(值最低的条目是 min(entries) 将返回的条目)。条目的典型模式是一种元组,形式如下 −

(priority_number, data)

Example

from time import sleep
from random import random, randint
from threading import Thread
from queue import PriorityQueue

queue = PriorityQueue()

def producer(queue):
   print('Producer: Running')
   for i in range(5):

      # create item with priority
      value = random()
      priority = randint(0, 5)
      item = (priority, value)
      queue.put(item)
   # wait for all items to be processed
   queue.join()

   queue.put(None)
   print('Producer: Done')

def consumer(queue):
   print('Consumer: Running')

   while True:

      # get a unit of work
      item = queue.get()
      if item is None:
         break

      sleep(item[1])
      print(item)
      queue.task_done()
   print('Consumer: Done')

producer = Thread(target=producer, args=(queue,))
producer.start()

consumer = Thread(target=consumer, args=(queue,))
consumer.start()

producer.join()
consumer.join()

它将生成以下 output

Producer: Running
Consumer: Running
(0, 0.15332707626852804)
(2, 0.4730737391435892)
(2, 0.8679231358257962)
(3, 0.051924220435665025)
(4, 0.23945882716108446)
Producer: Done
Consumer: Done

Python - Daemon Threads

有时,有必要在后台执行任务。一种特殊类型的线程用于后台任务,称为 daemon thread 。换句话说,守护程序线程在后台执行任务。

需要注意的是,守护程序线程执行的非关键任务虽然可能对应用程序有用,但如果它们在操作过程中失败或被取消,也不会妨碍应用程序。

此外,守护线程不能控制何时终止。一旦所有非守护线程完成,程序将终止,即使那时仍有守护线程在运行。

这是守护程序线程和非守护程序线程之间的主要区别。如果只运行守护程序线程,则该进程将退出,而如果至少有一个非守护程序线程在运行,则该进程无法退出。

Creating a Daemon Thread

要创建一个守护程序线程,你需要设置 daemon 属性为 True。

t1=threading.Thread(daemon=True)

如果在不设置任何参数的情况下创建线程对象,则在调用 start() 方法之前,其守护程序属性也可以设置为 True。

t1=threading.Thread()
t1.daemon=True

Example

请看以下示例:

from time import sleep
from threading import current_thread
from threading import Thread

# function to be executed in a new thread
def run():

   # get the current thread
   thread = current_thread()
   # is it a daemon thread?
   print(f'Daemon thread: {thread.daemon}')

# create a new thread
thread = Thread(target=run, daemon=True)

# start the new thread
thread.start()

# block for a 0.5 sec for daemon thread to run
sleep(0.5)

它将生成以下 output

Daemon thread: True

守护程序线程可以执行在程序中为非守护程序线程提供支持的任务。例如: −

  1. 创建一个存储日志信息的后台文件。

  2. 在后台执行网络抓取。

  3. 自动将数据保存在后台数据库中。

Example

如果正在运行的线程被配置为守护程序,则会引发 RuntimeError。请看以下示例: −

from time import sleep
from threading import current_thread
from threading import Thread

# function to be executed in a new thread
def run():
   # get the current thread
   thread = current_thread()
   # is it a daemon thread?
   print(f'Daemon thread: {thread.daemon}')
   thread.daemon = True

# create a new thread
thread = Thread(target=run)

# start the new thread
thread.start()

# block for a 0.5 sec for daemon thread to run
sleep(0.5)

它将生成以下 output

Exception in thread Thread-1 (run):
Traceback (most recent call last):
. . . .
. . . .
   thread.daemon = True
   ^^^^^^^^^^^^^
 File "C:\Python311\Lib\threading.py", line 1219, in daemon
  raise RuntimeError("cannot set daemon status of active thread")
RuntimeError: cannot set daemon status of active thread

Python - Synchronizing Threads

Python 提供的线程模块包括一个易于实现的锁机制,允许同步线程。通过调用 Lock() 方法创建一个新锁,该方法返回新锁。

新锁对象的 acquire(blocking) 方法用于强制线程同步运行。可选的阻塞参数可让您控制线程是否等待获取锁。

如果将阻塞设置 0,则如果无法获取锁,则线程立即返回 0 值,如果获取锁,则返回 1。如果阻塞设置 1,则线程将阻塞并等待释放锁。

新锁对象的 release() 方法用于不再需要时释放锁。

Example

import threading
import time

class myThread (threading.Thread):
   def __init__(self, threadID, name, counter):
      threading.Thread.__init__(self)
      self.threadID = threadID
      self.name = name
      self.counter = counter
   def run(self):
      print ("Starting " + self.name)
      # Get lock to synchronize threads
      threadLock.acquire()
      print_time(self.name, self.counter, 3)
      # Free lock to release next thread
      threadLock.release()

def print_time(threadName, delay, counter):
   while counter:
      time.sleep(delay)
      print ("%s: %s" % (threadName, time.ctime(time.time())))
      counter -= 1

threadLock = threading.Lock()
threads = []

# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# Start new Threads
thread1.start()
thread2.start()

# Add threads to thread list
threads.append(thread1)
threads.append(thread2)

# Wait for all threads to complete
for t in threads:
   t.join()
print ("Exiting Main Thread")

Output

当执行以上代码时,它会生成以下输出 −

Starting Thread-1
Starting Thread-2
Thread-1: Thu Jul 13 21:10:11 2023
Thread-1: Thu Jul 13 21:10:12 2023
Thread-1: Thu Jul 13 21:10:13 2023
Thread-2: Thu Jul 13 21:10:15 2023
Thread-2: Thu Jul 13 21:10:17 2023
Thread-2: Thu Jul 13 21:10:19 2023
Exiting Main Thread

Python - Inter-Thread Communication

线程共享分配给进程的内存。因此,同一进程中的线程可以相互通信。为了促进线程间通信,threading 模块提供 Event 对象和 Condition 对象。

The Event Object

Event 对象管理内部标志的状态。该标志最初为 false,并通过 set() 方法变为 true,通过 clear() 方法重置为 false。wait() 方法阻塞,直至标志变为 true。

Event 对象的方法 −

is_set() method

当且仅当内部标志为 true 时,返回 True。

set() method

将内部标志设置为 true。所有等待它变为 true 的线程都会被唤醒。如果标志为 true,则调用 wait() 的线程将不会被阻塞。

clear() method

将内部标志重置为 false。随后,在 set() 被调用以将内部标志再次设置为 true 之前,调用 wait() 的线程将阻塞。

wait(timeout=None) method

阻塞,直至内部标志为 true。如果进入时内部标志为 true,则立即返回。否则,阻塞直至另一个线程调用 set() 以将标志设置为 true,或直至发生可选的超时。

当 timeout 参数存在且不为 None 时,它应为一个浮点数,指定操作的超时时间(以秒为单位)。

Example

以下代码尝试模拟由 GREEN 或 RED 交通信号状态控制的交通流量。

程序中有两个线程,分别针对两个不同的函数。 signal_state() 函数定期设置和重置事件,表示信号从绿色变为红色。

traffic_flow() 函数等待事件被设置,并运行一个循环,直到它保持设置状态。

from threading import *
import time

def signal_state():
   while True:
      time.sleep(5)
      print("Traffic Police Giving GREEN Signal")
      event.set()
      time.sleep(10)
      print("Traffic Police Giving RED Signal")
      event.clear()

def traffic_flow():
   num=0
   while num<10:
      print("Waiting for GREEN Signal")
      event.wait()
      print("GREEN Signal ... Traffic can move")
      while event.is_set():
         num=num+1
         print("Vehicle No:", num," Crossing the Signal")
         time.sleep(2)
      print("RED Signal ... Traffic has to wait")

event=Event()
t1=Thread(target=signal_state)
t2=Thread(target=traffic_flow)
t1.start()
t2.start()

Output

Waiting for GREEN Signal
Traffic Police Giving GREEN Signal
GREEN Signal ... Traffic can move
Vehicle No: 1 Crossing the Signal
Vehicle No: 2 Crossing the Signal
Vehicle No: 3 Crossing the Signal
Vehicle No: 4 Crossing the Signal
Vehicle No: 5 Crossing the Signal
Signal is RED
RED Signal ... Traffic has to wait
Waiting for GREEN Signal
Traffic Police Giving GREEN Signal
GREEN Signal ... Traffic can move
Vehicle No: 6 Crossing the Signal
Vehicle No: 7 Crossing the Signal
Vehicle No: 8 Crossing the Signal
Vehicle No: 9 Crossing the Signal
Vehicle No: 10 Crossing the Signal

The Condition Object

threading 模块中的 Condition 类实现了条件变量对象。Condition 对象强制一个或多个线程等待,直至另一个线程通知。Condition 与 Reentrant Lock 关联。Condition 对象具有 acquire() 和 release() 方法,分别调用关联锁的相应方法。

threading.Condition(lock=None)

以下是 Condition 对象的方法:

acquire(*args)

获取底层锁。此方法调用底层锁上的相应方法;返回值是该方法返回的任何值。

release()

释放底层锁。此方法调用底层锁上的相应方法;没有返回值。

wait(timeout=None)

此方法释放底层锁,然后阻塞,直到在另一个线程中针对同一条件变量调用 notify() 或 notify_all(),或者直到发生可选超时。唤醒或超时后,它重新获取锁并返回。

wait_for(predicate, timeout=None)

此实用方法可以重复调用 wait(),直至谓词得到满足,或者发生超时。返回值是谓词的最后一个返回值,如果方法超时,该值的评估结果为 False。

notify(n=1)

此方法最多唤醒 n 个等待条件变量的线程;如果没有任何线程在等待,则什么都不做。

notify_all()

唤醒正在等待此条件的所有线程。此方法类似于 notify(),但它唤醒所有等待的线程,而不是一个线程。如果调用线程在调用此方法时未获取锁,则会引发 RuntimeError。

Example

在以下代码中,线程 t2 运行 taskB() 函数,而 t1 运行 taskA() 函数。t1 线程获取条件并通知它。到那时,t2 线程处于等待状态。释放条件后,等待线程将继续使用通知函数生成的随机数。

from threading import *
import time
import random

numbers=[]
def taskA(c):
   while True:
      c.acquire()
      num=random.randint(1,10)
      print("Generated random number:", num)
      numbers.append(num)
      print("Notification issued")
      c.notify()
      c.release()
      time.sleep(5)

def taskB(c):
   while True:
      c.acquire()
      print("waiting for update")
      c.wait()
      print("Obtained random number", numbers.pop())
      c.release()
      time.sleep(5)

c=Condition()
t1=Thread(target=taskB, args=(c,))
t2=Thread(target=taskA, args=(c,))
t1.start()
t2.start()

执行此代码时,它将生成以下 output -

waiting for update
Generated random number: 4
Notification issued
Obtained random number 4
waiting for update
Generated random number: 6
Notification issued
Obtained random number 6
waiting for update
Generated random number: 10
Notification issued
Obtained random number 10
waiting for update

Python - Thread Deadlock

死锁可以描述为并发故障模式。它是程序中一个或多个线程等待永远不会发生的条件的情况。结果,该线程无法继续进行,程序将卡住或冻结,且必须手动终止。

在并发程序中,可能会以多种方式出现死锁情况。死锁永远不会有意地发展,相反,它们实际上是代码中的副作用或错误。

下面列出了线程死锁的常见原因 −

  1. 尝试两次获取同一互斥锁的线程。

  2. 相互等待的线程(例如,A 等待 B,B 等待 A)。

  3. 当线程未能释放诸如锁、信号量、条件、事件等资源时。

  4. 以不同顺序获取互斥锁的线程(例如,未执行锁定顺序)。

如果多线程应用程序中的多个线程尝试访问同一资源(例如对同一文件执行读/写操作),则可能导致数据不一致。因此,同步并发处理非常重要,以便当一个线程正在使用资源时,它对其他线程处于锁定状态。

Python 提供的线程模块包括一个易于实现的锁机制,允许同步线程。通过调用 Lock() 方法创建一个新锁,该方法返回新锁。

The Lock Object

Lock 类的对象有两种可能的状态:locked 或 unlocked,初始状态为 unlocked(首次创建时)。锁不属于任何特定线程。

锁定类定义了 acquire() 和 release() 方法。

The acquire() Method

当状态为 unlocked 时,此方法将状态更改为 locked 并立即返回。此方法采用可选的阻塞参数。

Syntax

Lock.acquire(blocking, timeout)

Parameters

  1. blocking − 如果设置为 False,意味着不锁定。如果带有锁定设置为 True 的调用将锁定,立即返回 False;否则,将锁定设置为锁定并返回 True。

这个方法的返回值如果成功获取锁定,则为 True;如果失败,则为 False。

The release() Method

当状态被锁定时,另一个线程中的这个方法会将其改为解锁。它可以被任何线程调用,不仅限于获取锁定的线程

Syntax

Lock.release()

release() 方法只能在锁定状态下调用。如果尝试释放一个未锁定的锁定,会引发 RuntimeError。

当锁定被锁定时,将它重置为解锁,并返回。如果有任何其他线程因为等待锁定被解锁而锁定,只允许其中一个继续。这个方法没有返回值。

Example

在以下程序中,有两个线程尝试调用 synchronized() 方法。其中一个线程获取锁定并获得访问权,而另一个线程则等待。当第一个线程的 run() 方法完成时,锁定被释放,并且 synchronized 方法对第二个线程可用。

当两个线程都加入时,程序结束。

from threading import Thread, Lock
import time

lock=Lock()
threads=[]

class myThread(Thread):
   def __init__(self,name):
      Thread.__init__(self)
      self.name=name
   def run(self):
      lock.acquire()
      synchronized(self.name)
      lock.release()

def synchronized(threadName):
   print ("{} has acquired lock and is running synchronized method".format(threadName))
   counter=5
   while counter:
      print ('**', end='')
      time.sleep(2)
      counter=counter-1
   print('\nlock released for', threadName)

t1=myThread('Thread1')
t2=myThread('Thread2')

t1.start()
threads.append(t1)

t2.start()
threads.append(t2)

for t in threads:
   t.join()
print ("end of main thread")

它将生成以下 output

Thread1 has acquired lock and is running synchronized method
**********
lock released for Thread1
Thread2 has acquired lock and is running synchronized method
**********
lock released for Thread2
end of main thread

The Semaphore Object

Python 通过另一种称为 semaphore 的机制支持线程同步。这是由著名计算机科学家艾兹格·W·迪杰斯特拉发明的最古老的同步技术之一。

信号量的基本概念是使用一个由每次 acquire() 调用递减,且每次 release() 调用递增的内部计数器。计数器永远不会低于零;当 acquire() 发现它是零时,它将锁定,一直等到其他线程调用 release() 为止。

线程模块中的信号量类定义了 acquire() 和 release() 方法。

The acquire() Method

如果输入时内部计数器大于零,将其减一并立即返回 True。

如果输入时内部计数器为零,则锁定,直到因调用 release() 而被唤醒。一旦唤醒(并且计数器大于 0),将计数器减 1 并返回 True。每次调用 release(),都将唤醒一个线程。唤醒线程的顺序是任意的。

如果阻塞参数被设置为 False,不要阻塞。如果未带参数的调用将阻塞,立即返回 False;否则,执行与未带参数调用时相同的操作,并返回 True。

The release() Method

释放一个信号量,将内部计数器加 1。当在进入时它为零,并且其他线程正在等待它再次变为大于零时,唤醒其中 n 个线程。

Example

from threading import *
import time

# creating thread instance where count = 3
lock = Semaphore(4)

# creating instance
def synchronized(name):

   # calling acquire method
   lock.acquire()

   for n in range(3):
      print('Hello! ', end = '')
      time.sleep(1)
      print( name)

      # calling release method
      lock.release()

# creating multiple thread
thread_1 = Thread(target = synchronized , args = ('Thread 1',))
thread_2 = Thread(target = synchronized , args = ('Thread 2',))
thread_3 = Thread(target = synchronized , args = ('Thread 3',))

# calling the threads
thread_1.start()
thread_2.start()
thread_3.start()

它将生成以下 output

Hello! Hello! Hello! Thread 1
Hello! Thread 2
Thread 3
Hello! Hello! Thread 1
Hello! Thread 3
Thread 2
Hello! Hello! Thread 1
Thread 3
Thread 2

Python - Interrupting a Thread

在多线程程序中,可能需要停止新线程中的任务。这可能是由于许多原因,例如:(a) 不再需要任务的结果或 (b) 任务的结果出错或 (c) 应用程序正在关闭。

可以使用 threading.Event 对象来停止线程。Event 对象管理内部标志的状态,该标志可以设置或不设置。

创建新的 Event 对象后,其标志将未设置(false)以启动。如果一个线程调用其 set() 方法,则可以检查其标志值在另一个线程中。如果发现为 true,则可以终止其活动。

Example

在此示例中,我们有一个类 MyThread。它的对象开始执行 run() 方法。主线程休眠一段时间,然后设置一个事件。直至检测到事件,run() 方法中的循环才会继续。只要检测到事件,循环就会终止。

from time import sleep
from threading import Thread
from threading import Event

class MyThread(Thread):
   def __init__(self, event):
      super(MyThread, self).__init__()
      self.event = event

   def run(self):
      i=0
      while True:
         i+=1
         print ('Child thread running...',i)
         sleep(0.5)
         if self.event.is_set():
            break
         print()
      print('Child Thread Interrupted')

event = Event()
thread1 = MyThread(event)
thread1.start()

sleep(3)
print('Main thread stopping child thread')
event.set()
thread1.join()

执行此代码时,它将生成以下 output -

Child thread running... 1
Child thread running... 2
Child thread running... 3
Child thread running... 4
Child thread running... 5
Child thread running... 6
Main thread stopping child thread
Child Thread Interrupted

Python - Network Programming

Python 标准库中的线程模块能够处理多线程及其在单进程中的交互。在同一台计算机上运行的两个进程之间的通信由 Unix 域套接字处理,而对于在不同计算机上运行并连接到 TCP(传输控制协议)的进程,则使用 Internet 域套接字。

network programming

Python 标准库包含各种内置模块,它们支持进程间通信和网络连接。Python 提供了两个级别的网络服务访问。在较低级别,你可以访问底层操作系统中的基本套接字支持,这使你能够为面向连接和无连接协议实现客户端和服务器。

Python 还具有库,提供对特定应用程序级网络协议的更高级访问,例如 FTP、HTTP 等。

Python - Socket Programming

标准库中的 socket 模块包含在硬件级别服务器和客户端之间通信所需的功能。

本模块提供了 BSD 套接字接口的访问权限。它可在所有操作系统上使用,例如 Linux、Windows、MacOS。

What are Sockets?

套接字是双向通信通道的端点。套接字可以在进程内进行通信,也可以在同一电脑上的进程之间或不同区域中的进程之间进行通信。

套接字通过 IP 地址和端口号组合识别。为了开始通信,它应该在两端均正确配置。

connection
ip address

套接字可以用许多不同信道类型执行:Unix 域套接字、TCP、UDP 等。套接字库为处理常见的传输提供了特定类,并为处理其余部分提供了一个通用接口。

套接字编程术语意味着以编程方式设置套接字,使其能够发送和接收数据。

有两种类型的通信协议 −

  1. connection-oriented protocol

  2. connection-less protocol

TCP 或传输控制协议是一种面向连接的协议。数据由服务器以数据包形式传输,并由接收器按照相同传输顺序进行组装。因为通信两端的套接字在开始之前需要设置,所以这种方法的可靠性更高。

UDP 或用户数据报协议是无连接的。该方法不可靠,因为套接字不需要建立任何用于传输数据连接和终止处理。

Python The socket Module

此模块包括套接字类型。套接字对象表示主机名和端口号的 psir。构造方法具有以下签名 −

Syntax

socket.socket (socket_family, socket_type, protocol=0)

Parameters

  1. family − 默认情况下为 AF_INET。其他值 - AF_INET6(八组四位十六进制数字)、AF_UNIX、AF_CAN(控制器局域网络)或 AF_RDS(可靠数据包套接字)。

  2. socket_type − 应该是 SOCK_STREAM(默认值)、SOCK_DGRAM、SOCK_RAW 或者可能是其他 SOCK_ 常量之一。

  3. protocol − 数字通常为零,可以省略。

Return Type

此方法返回一个套接字对象。

一旦有了套接字对象,你可以使用所需的方法创建客户端或服务器程序。

Server Socket Methods

在服务器上实例化的套接字称为服务器套接字。以下方法可在服务器上的套接字对象上使用 −

  1. bind() method − 此方法将套接字绑定到指定的 IP 地址和端口号。

  2. listen() method − 此方法启动服务器并进入侦听循环,寻找来自客户端的连接请求。

  3. accept() method − 当服务器截获连接请求时,此方法接受它并识别具有其地址的客户端套接字。

要在服务器上创建套接字,请使用以下片段 −

import socket
server = socket.socket()
server.bind(('localhost',12345))
server.listen()
client, addr = server.accept()
print ("connection request from: " + str(addr))

默认情况下,服务器绑定到本地计算机的 IP 地址“localhost”,监听在任意空闲的端口号。

Client Socket Methods

在客户端设置了类似的套接字。它主要向其 IP 地址和端口号处监听的服务器套接字发送连接请求。

connect() method

此方法以一个二元组对象作为参数。这两个成员是服务器的 IP 地址和端口号。

obj=socket.socket()
obj.connect((host,port))

一旦连接被服务器接受,两个套接字对象都可以发送和/或接收数据。

send() method

服务器使用它截获的地址向客户端发送数据。

client.send(bytes)

客户端套接字向与其建立连接的套接字发送数据。

sendall() method

与 send() 类似。但是与 send() 不同,此方法会持续发送数据字节,直到所有数据发送完毕或者出现错误。成功时不返回任何内容。

sendto() method

此方法仅在 UDP 协议的情况下使用。

recv() method

此方法用于检索发送到客户端的数据。对于服务器而言,它使用其请求已被接受的远程套接字。

client.recv(bytes)

recvfrom() method

此方法在 UDP 协议中使用。

Python - Socket Server

要编写 Internet 服务器,我们使用 socket 模块中可用的 socket 函数创建一个 socket 对象。此后使用该 socket 对象来调用其他函数以设置一个 socket 服务器。

现在调用 bind(hostname, port) 函数以指定您在给定主机上使用的服务端口。

接下来,调用返回对象的 accept 方法。此方法会一直等待直到某个客户端连接到您指定的端口,然后返回表示对该客户端连接的连接对象。

import socket
host = "127.0.0.1"
port = 5001
server = socket.socket()
server.bind((host,port))
server.listen()
conn, addr = server.accept()
print ("Connection from: " + str(addr))
while True:
   data = conn.recv(1024).decode()
   if not data:
      break
   data = str(data).upper()
   print (" from client: " + str(data))
   data = input("type message: ")
   conn.send(data.encode())
conn.close()

Python - Socket Client

接下来让我们编写一个非常简单的客户端程序,该程序打开一个对给定的本地主机和端口 5001 的连接。使用 Python 的 socket 模块函数创建 socket 客户端非常简单。

socket.connect(hosname, port) 在该端口处向 hostname 打开一个 TCP 连接。一旦您打开一个套接字,就可以像任何 IO 对象一样从中读取内容。完成后,别忘了关闭它,就像你会关闭一个文件一样。

下列代码是一个非常简单的客户端,它连接到给定的主机和端口,从套接字读取任何可用的数据,然后在输入“q”时退出。

import socket
host = '127.0.0.1'
port = 5001
obj = socket.socket()
obj.connect((host,port))
message = input("type message: ")
while message != 'q':
   obj.send(message.encode())
   data = obj.recv(1024).decode()
   print ('Received from server: ' + data)
   message = input("type message: ")
obj.close()
  1. 首先运行服务器代码。它开始侦听。

  2. 然后启动客户端代码。它发送请求。

  3. 请求已接受。已识别客户端地址

  4. 输入一些文本后按 Enter 键。

  5. 打印已接收的数据。将数据发送至客户端。

  6. 收到服务器的数据。

  7. 输入“q”时循环终止。

服务器-客户端交互如下所示:

server client interaction

我们已在本地计算机上使用 socket 模块实现了客户端-服务器通信。若要将服务器和客户端代码放置在网络中的两台不同计算机上,我们需要找到服务器的 IP 地址。

在 Windows 中,可以通过运行 ipconfig 命令来找到 IP 地址。ifconfig 命令是 Ubuntu 上的等效命令。

ipv4 address

使用 IPv4 地址值更改服务器和客户端代码中的 host 字符串,并像以前一样运行它们。

Python File Transfer with Socket Module

下面的程序演示了如何使用套接字通信来将某个文件从服务器传输至客户端。

Server Code

建立连接的代码与之前相同。连接请求被接受后,服务器上的一个文件会以二进制模式打开用于读取,且字节会顺序读取并发送至客户端流,直至到达文件结尾。

import socket
host = "127.0.0.1"
port = 5001
server = socket.socket()
server.bind((host, port))
server.listen()
conn, addr = server.accept()
data = conn.recv(1024).decode()
filename='test.txt'
f = open(filename,'rb')
while True:
   l = f.read(1024)
   if not l:
      break
   conn.send(l)
   print('Sent ',repr(l))
f.close()
print('File transferred')
conn.close()

Client Code

在客户端上,一个新文件会以 wb 模式打开。从服务器接收到的数据流被写入该文件。当流结束时,输出文件会关闭。客户端计算机上会创建一个新文件。

import socket

s = socket.socket()
host = "127.0.0.1"
port = 5001

s.connect((host, port))
s.send("Hello server!".encode())

with open('recv.txt', 'wb') as f:
   while True:
      print('receiving data...')
      data = s.recv(1024)
      if not data:
         break
      f.write(data)

f.close()
print('Successfully received')
s.close()
print('connection closed')

Python The socketserver Module

Python 标准库中的 socketserver 模块是一个用于简化编写网络服务器任务的框架。该模块中包含以下类,它们表示同步服务器:

socketserver module

这些类与相应的 RequestHandler 类结合使用,用于实现服务。BaseServer 是模块中所有 Server 对象的超类。

TCPServer 类使用互联网 TCP 协议,在客户端和服务器之间提供连续数据流。构造函数会自动尝试调用 server_bind() 和 server_activate()。其他参数会传递至 BaseServer 基类。

你必须创建 StreamRequestHandler 类的子类。它提供了 self.rfile 和 self.wfile 属性,用于读写以获取请求数据或将数据返回至客户端。

  1. UDPServerDatagramRequestHandler - 这些类用于 UDP 协议。

  2. DatagramRequestHandlerUnixDatagramServer - 这些类使用 Unix 域套接字;它们在非 Unix 平台上不可用。

Server Code

你必须编写一个 RequestHandler 类。每当连接到服务器时,该类都会被实例化一次,且必须重写 handle() 方法来实现与客户端的通信。

import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
   def handle(self):
      self.data = self.request.recv(1024).strip()
      host,port=self.client_address
      print("{}:{} wrote:".format(host,port))
      print(self.data.decode())
      msg=input("enter text .. ")
      self.request.sendall(msg.encode())

在服务器分配的端口号上,TCPServer 类的对象会调用 forever() 方法,以将服务器置于监听模式并接受来自客户端的传入请求。

if __name__ == "__main__":
   HOST, PORT = "localhost", 9999
   with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
      server.serve_forever()

Client Code

在使用 socketserver 时,客户端代码与 socket 客户端应用程序比较类似。

import socket
import sys

HOST, PORT = "localhost", 9999

while True:
   with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
      # Connect to server and send data
      sock.connect((HOST, PORT))
      data = input("enter text .. .")
      sock.sendall(bytes(data + "\n", "utf-8"))

      # Receive data from the server and shut down
      received = str(sock.recv(1024), "utf-8")
      print("Sent: {}".format(data))
      print("Received: {}".format(received))

在命令提示符终端运行服务器代码。为客户端实例打开多个终端。您可以模拟服务器与多个客户端之间的并发通信。

Python - URL Processing

在互联网的世界中,不同的资源通过 URL(统一资源定位符)来识别。随 Python 标准库绑定的 urllib 包提供了一些用于处理 URL 的实用程序。它包含以下模块−

  1. urllib.parse 模块用于将 URL 解析成其各部分。

  2. urllib.request 模块包含用于打开和读取 URL 的函数

  3. urllib.error 模块承载 urllib.request 引发的异常的定义

  4. urllib.robotparser 模块解析 robots.txt 文件

The urllib.parse M odule

此模块用作一个标准接口,以从 URL 字符串获取各个部分。该模块包含以下函数−

urlparse(urlstring)

将 URL 解析成六个组件,返回一个 6 项命名字段的元组。每个元组项是一个字符串,对应于以下属性−

Example

from urllib.parse import urlparse
url = "https://example.com/employees/name/?salary>=25000"
parsed_url = urlparse(url)
print (type(parsed_url))
print ("Scheme:",parsed_url.scheme)
print ("netloc:", parsed_url.netloc)
print ("path:", parsed_url.path)
print ("params:", parsed_url.params)
print ("Query string:", parsed_url.query)
print ("Frgment:", parsed_url.fragment)

它将生成以下 output

<class 'urllib.parse.ParseResult'>
Scheme: https
netloc: example.com
path: /employees/name/
params:
Query string: salary>=25000
Frgment:

parse_qs(qs))

此函数解析给定为字符串参数的查询字符串。数据作为字典返回。字典键是唯一的查询变量名,值是每个名称的值列表。

要进一步从查询字符串提取查询参数到字典中,请按如下方式使用 ParseResult 对象的 query 属性的 parse_qs() 函数 −

from urllib.parse import urlparse, parse_qs
url = "https://example.com/employees?name=Anand&salary=25000"
parsed_url = urlparse(url)
dct = parse_qs(parsed_url.query)
print ("Query parameters:", dct)

它将生成以下 output

Query parameters: {'name': ['Anand'], 'salary': ['25000']}

urlsplit(urlstring)

这类似于 urlparse(),但不会从 URL 中分离参数。如果想要较新的 URL 语法,允许将参数应用于 URL 的路径部分的每个部分,则通常应该使用它代替 urlparse()。

urlunparse(parts)

此函数与 urlparse() 函数相反。它根据 urlparse() 返回的元组构造一个 URL。parts 参数可以是任何六项可迭代对象。这会返回一个等效的 URL。

Example

from urllib.parse import urlunparse

lst = ['https', 'example.com', '/employees/name/', '', 'salary>=25000', '']
new_url = urlunparse(lst)
print ("URL:", new_url)

它将生成以下 output

URL: https://example.com/employees/name/?salary>=25000

urlunsplit(parts)

将通过 urlsplit() 返回的元组的元素组合成一个完整的 URL,作为字符串。parts 参数可以是任何五项可迭代对象。

The urllib.request Module

此模块定义了有助于打开 URL 的函数和类

urlopen() function

此函数打开给定的 URL,该 URL 可以是字符串或请求对象。可选的 timeout 参数指定一个超时时间(以秒为单位),用于阻塞操作。这实际上只适用于 HTTP、HTTPS 和 FTP 连接。

此函数始终返回一个可以充当上下文管理器,并且具有 url、headers 和 status 属性的对象。

对于 HTTP 和 HTTPS URL,此函数返回一个已修改的 http.client.HTTPResponse 对象。

Example

以下代码使用 urlopen() 函数从图像文件的二进制数据读取,并将其写入本地文件。您可以使用任何图像查看器在您的计算机打开图像文件。

from urllib.request import urlopen
obj = urlopen("https://www.tutorialspoint.com/static/images/simply-easy-learning.jpg")
data = obj.read()
img = open("img.jpg", "wb")
img.write(data)
img.close()

它将生成以下 output

urllib request

The Request Object

urllib.request 模块包括 Request 类。此类是 URL 请求的抽象类。构造函数需要一个有效的 URL 字符串参数。

Syntax

urllib.request.Request(url, data, headers, origin_req_host, method=None)

Parameters

  1. url − 一个有效 URL 的字符串

  2. data − 一个指定要发送到服务器的其他数据对象。此参数仅能与 HTTP 请求一并使用。数据可以是字节、类文件对象和类字节对象的迭代对象。

  3. headers − 应该是包含标头及其关联值的字典。

  4. origin_req_host − 应该是原始交易的请求主机

  5. method − 应该是指示 HTTP 请求方法的字符串。GET、POST、PUT、DELETE 和其他 HTTP 动词之一。默认值为 GET。

Example

from urllib.request import Request
obj = Request("https://www.tutorialspoint.com/")

此 Request 对象现在可用作 urlopen() 方法的参数。

from urllib.request import Request, urlopen
obj = Request("https://www.tutorialspoint.com/")
resp = urlopen(obj)

urlopen() 函数返回一个 HttpResponse 对象。调用其 read() 方法可抓取指定 URL 的资源。

from urllib.request import Request, urlopen
obj = Request("https://www.tutorialspoint.com/")
resp = urlopen(obj)
data = resp.read()
print (data)

Sending Data

如果为 Request 构造函数定义数据参数,将向服务器发送 POST 请求。数据应为任何以字节表示的对象。

Example

from urllib.request import Request, urlopen
from urllib.parse import urlencode

values = {'name': 'Madhu',
   'location': 'India',
   'language': 'Hindi' }
data = urlencode(values).encode('utf-8')
obj = Request("https://example.com", data)

Sending Headers

Request 构造函数还接受标头参数以将标头信息推入请求中。它应包含在一个字典对象中。

headers = {'User-Agent': user_agent}
obj = Request("https://example.com", data, headers)

The urllib.error Module

urllib.error 模块中定义了以下异常 −

URLError

由于网络未连接(找不到路由到指定服务器)或指定的服务器不存在,因此会引发 URLError。在此情况下,引发的异常将具有“原因”属性。

from urllib.request import Request, urlopen
import urllib.error as err

obj = Request("http://www.nosuchserver.com")
try:
   urlopen(obj)
except err.URLError as e:
   print(e)

它将生成以下 output

HTTP Error 403: Forbidden

HTTPError

服务器每次发送 HTTP 响应,都与一个数字“状态代码”关联。该代码指示服务器为何无法满足请求。默认处理程序将处理部分这些响应。对于无法处理的那些响应,urlopen() 函数会引发 HTTPError。HTTPErrors 典型的示例包括“404”(找不到页面)、“403”(禁止请求)和“401”(需要身份验证)。

from urllib.request import Request, urlopen
import urllib.error as err

obj = Request("http://www.python.org/fish.html")
try:
   urlopen(obj)
except err.HTTPError as e:
   print(e.code)

它将生成以下 output

404

Python - Generics

在 Python 中,泛型是一种机制,可以用来定义可以在多种类型上操作但同时保持类型安全的功能、类或方法。通过实现泛型,可以编写可与不同数据类型一起使用的可重用代码。它确保了提升代码的灵活性并保证类型的正确性。

Python 中的泛型使用类型提示实现。此功能在 Python 3.5 中引入。

正常情况下,无需声明变量类型。类型由分配给变量的值动态确定。Python 的解释器不执行类型检查,因此可能会引发运行时异常。

Python 的新型提示功能有助于提示用户期望传入的参数类型。

使用类型提示,可以指定变量、函数参数和返回值的预期类型。泛型通过引入类型变量扩展了此功能,该类型在使用泛型函数或类时可以用特定类型替换。

Example 1

我们来看看以下定义了一个泛型函数的示例 −

from typing import List, TypeVar, Generic
T = TypeVar('T')
def reverse(items: List[T]) -> List[T]:
   return items[::-1]

在此处,我们定义了一个称为“reverse”的泛型函数。该函数将一个列表(“List[T]”)作为参数,并返回相同类型的列表。类型变量“T”表示泛型类型,在使用该函数时,它将被替换为特定类型。

Example 2

reverse() 函数被调用,并使用了不同的数据类型 −

numbers = [1, 2, 3, 4, 5]
reversed_numbers = reverse(numbers)
print(reversed_numbers)

fruits = ['apple', 'banana', 'cherry']
reversed_fruits = reverse(fruits)
print(reversed_fruits)

它将生成以下 output

[5, 4, 3, 2, 1]
['cherry', 'banana', 'apple']

Example 3

以下示例对泛型类使用了泛型 −

from typing import List, TypeVar, Generic
T = TypeVar('T')
class Box(Generic[T]):
   def __init__(self, item: T):
      self.item = item
   def get_item(self) -> T:
      return self.item
Let us create objects of the above generic class with int and str type
box1 = Box(42)
print(box1.get_item())

box2 = Box('Hello')
print(box2.get_item())

它将生成以下 output

42
Hello

Python - Date and Time

Python 程序可以使用多种方法处理日期和时间。在日期格式之间转换是计算机的常见任务。Python 标准库中的以下模块处理日期和时间相关的处理 −

  1. DateTime module

  2. Time module

  3. Calendar module

What are Tick Intervals

时间间隔是秒为单位的浮点数字。特定时间点以 1970 年 1 月 1 日上午 12:00(历元)以来的秒数表示。

Python 中有一个流行的 time 模块,它提供用于处理时间和在不同表示之间转换的函数。函数 time.time() 返回自 1970 年 1 月 1 日上午 12:00(历元)以来的当前系统时间(按刻度)。

Example

import time # This is required to include time module.
ticks = time.time()
print ("Number of ticks since 12:00am, January 1, 1970:", ticks)

结果类似于以下内容:

Number of ticks since 12:00am, January 1, 1970: 1681928297.5316436

刻度可以轻松做日期计算。但是,无法以这种形式表示历元之前的日期。遥远未来的日期也不能以这种方式表示 - UNIX 和 Windows 的截止时间是 2038 年的某个时间。

What is TimeTuple?

Python 的许多时间函数将时间作为 9 个数字的元组进行处理,如下所示:

For example,

>>>import time
>>> print (time.localtime())

这将产生一个 output ,如下所示:

time.struct_time(tm_year=2023, tm_mon=4, tm_mday=19, tm_hour=23, tm_min=49, tm_sec=8, tm_wday=2, tm_yday=109, tm_isdst=0)

上述元组等效于 struct_time 结构。此结构具有以下属性:

Getting the Current Time

要将自历元起的 seconds 浮点值的时间点转换为时间元组,将浮点值传递给返回包含所有 9 个有效项的时间元组的函数(例如,localtime)。

import time
localtime = time.localtime(time.time())
print ("Local current time :", localtime)

这将产生以下结果,该结果可以用任何其他可表示形式进行格式化:

Local current time : time.struct_time(tm_year=2023, tm_mon=4, tm_mday=19, tm_hour=23, tm_min=42, tm_sec=41, tm_wday=2, tm_yday=109, tm_isdst=0)

Getting the Formatted Time

您可以根据需要对任何时间进行格式化,但以可读格式获取时间的简单方法是 asctime()

import time

localtime = time.asctime( time.localtime(time.time()) )
print ("Local current time :", localtime)

这将产生以下 output

Local current time : Wed Apr 19 23:45:27 2023

Getting the Calendar for a Month

日历模块提供了多种方法来使用年历和月历。这里,我们为给定的月份(2008 年 1 月)打印日历。

import calendar
cal = calendar.month(2023, 4)
print ("Here is the calendar:")
print (cal)

这将产生以下 output

Here is the calendar:
     April 2023
Mo Tu We Th Fr Sa Su
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

The time Module

Python 中有一个流行的 time 模块,它提供用于处理时间和在不同表示之间转换的函数。以下是所有可用方法的列表。

让我们简单浏览一下这些函数。

时间模块提供两个重要的属性。它们是:

The calendar Module

日历模块提供与日历相关的一些功能,包括打印给定月份或年份文字日历的功能。

默认情况下,日历将星期一作为一周的第一天,将星期日作为最后一天。要更改此设置,请调用 calendar.setfirstweekday() 函数。

以下列出了 calendar 模块提供的函数:

datetime module

Python 的 datetime 模块包含在标准库中。它包含用于帮助处理数据和时间数据以及执行日期时间运算的类。

datetime 类的对象要么是感知时间的,要么是幼稚的。如果对象包含时区信息,则它是感知时间的;否则,它被归类为幼稚的。date 类的对象是幼稚的,而 time 和 datetime 对象是感知时间的。

date

日期对象用年、月和日表示日期。当前的格里高利历在两个方向上无限延伸。

Syntax

datetime.date(year, month, day)

参数必须是整数,在以下范围内:

  1. year − MINYEAR ⇐ year ⇐ MAXYEAR

  2. month − 1 ⇐ month ⇐ 12

  3. day − 1 ⇐ day ⇐ 给定月份和年份中天数

如果给出了超出这些范围的任何参数的值,则会引发 ValueError。

Example

from datetime import date
date1 = date(2023, 4, 19)
print("Date:", date1)
date2 = date(2023, 4, 31)

它将生成以下 output

Date: 2023-04-19
Traceback (most recent call last):
 File "C:\Python311\hello.py", line 8, in <module>
  date2 = date(2023, 4, 31)
ValueError: day is out of range for month

date class attributes

  1. date.min − 最早的可以表示的日期,日期(MINYEAR、1、1)。

  2. date.max − 最迟的可以表示的日期,日期(MAXYEAR、12、31)。

  3. date.resolution − 非相等日期对象之间最小的可能差异。

  4. date.year − 包括在 MINYEAR 和 MAXYEAR 之间。

  5. date.month − 包括在 1 和 12 之间。

  6. date.day − 在给定年份的给定月份的 1 和天数之间。

Example

from datetime import date

# Getting min date
mindate = date.min
print("Minimum Date:", mindate)

# Getting max date
maxdate = date.max
print("Maximum Date:", maxdate)

Date1 = date(2023, 4, 20)
print("Year:", Date1.year)
print("Month:", Date1.month)
print("Day:", Date1.day)

它将生成以下 output

Minimum Date: 0001-01-01
Maximum Date: 9999-12-31
Year: 2023
Month: 4
Day: 20

Classmethods in date class

  1. today() − 返回当前的本地日期。

  2. fromtimestamp(timestamp) − 返回与 POSIX 时间戳(如 time.time() 返回的时间戳)相对应的本地日期。

  3. fromordinal(ordinal) − 返回与前格里高利历序数相对应的日期,其中 1 年的 1 月 1 日的序数为 1。

  4. fromisoformat(date_string) − 返回与 date_string 对应的日期,该字符串以任何有效的 ISO 8601 格式给出,但序数日期除外。

Example

from datetime import date

print (date.today())
d1=date.fromisoformat('2023-04-20')
print (d1)
d2=date.fromisoformat('20230420')
print (d2)
d3=date.fromisoformat('2023-W16-4')
print (d3)

它将生成以下 output

2023-04-20
2023-04-20
2023-04-20
2023-04-20

Instance methods in date class

  1. replace() − 通过使用关键字参数指定的新值替换指定属性,返回一个日期。

  2. timetuple() − 返回一个 time.struct_time,例如由 time.localtime() 返回的。

  3. toordinal() − 返回日期的前格里高利历序数,其中 1 年的 1 月 1 日的序数为 1。对于任何日期对象 d,date.fromordinal(d.toordinal()) == d。

  4. weekday() − 将星期几返回为一个整数,其中星期一为 0,星期日为 6。

  5. isoweekday() − 将星期几返回为一个整数,其中星期一为 1,星期日为 7。

  6. isocalendar() − 返回一个含三个分量的命名元组对象:年份、星期和工作日。

  7. isoformat() − 返回一个表示日期的字符串,采用 ISO 8601 格式,YYYY-MM-DD:

  8. str() − 对于日期 d,str(d) 等效于 d.isoformat()

  9. ctime() − 返回一个表示日期的字符串:

  10. strftime(format) − 返回一个表示日期的字符串,受显式格式字符串控制。

  11. format(format) − 与 date.strftime() 相同。

Example

from datetime import date
d = date.fromordinal(738630) # 738630th day after 1. 1. 0001
print (d)
print (d.timetuple())
# Methods related to formatting string output
print (d.isoformat())
print (d.strftime("%d/%m/%y"))
print (d.strftime("%A %d. %B %Y"))
print (d.ctime())

print ('The {1} is {0:%d}, the {2} is {0:%B}.'.format(d, "day", "month"))

# Methods for to extracting 'components' under different calendars
t = d.timetuple()
for i in t:
   print(i)

ic = d.isocalendar()
for i in ic:
   print(i)

# A date object is immutable; all operations produce a new object
print (d.replace(month=5))

它将生成以下 output

2023-04-20
time.struct_time(tm_year=2023, tm_mon=4, tm_mday=20, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=110, tm_isdst=-1)
2023-04-20
20/04/23
Thursday 20. April 2023
Thu Apr 20 00:00:00 2023
The day is 20, the month is April.
2023
4
20
0
0
0
3
110
-1
2023
16
4
2023-05-20

time

一个对象 time 类表示这个一天中的本地时间。它独立于任何特定的一天。如果对象包含 tzinfo 详情,它就是一个有意识的对象。如果它为 None,则时间对象是一个天真的对象。

Syntax

datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)

所有参数都是可选的。tzinfo 为 None,或为 tzinfo 子类的实例。剩余参数必须是在以下范围内的整数 −

  1. hour − 0 ⇐ 小时 < 24,

  2. minute − 0 ⇐ 分钟 < 60,

  3. second − 0 ⇐ 秒 < 60,

  4. microsecond − 0 ⇐ 微秒 < 1000000

如果任何参数超出这些范围,则引发 ValueError。

Example

from datetime import time

time1 = time(8, 14, 36)
print("Time:", time1)

time2 = time(minute = 12)
print("time", time2)

time3 = time()
print("time", time3)

time4 = time(hour = 26)

它将生成以下 output

Time: 08:14:36
time 00:12:00
time 00:00:00
Traceback (most recent call last):
  File "/home/cg/root/64b912f27faef/main.py", line 12, in
    time4 = time(hour = 26)
ValueError: hour must be in 0..23

Class attributes

  1. time.min − 最早可表示的时间,time(0, 0, 0, 0)。

  2. time.max − 最新可表示的时间,time(23, 59, 59, 999999)。

  3. time.resolution − 不相等的时间对象之间的最小可能差。

Example

from datetime import time
print(time.min)
print(time.max)
print (time.resolution)

它将生成以下 output

00:00:00
23:59:59.999999
0:00:00.000001

Instance attributes

  1. time.hour − In range(24)

  2. time.minute − In range(60)

  3. time.second − In range(60)

  4. time.microsecond − In range(1000000)

  5. time.tzinfo − time 构造函数中的 tzinfo 参数,或为 None。

Example

from datetime import time
t = time(8,23,45,5000)
print(t.hour)
print(t.minute)
print (t.second)
print (t.microsecond)

它将生成以下 output

8
23
455000

Instance methods

  1. replace() − 返回一个具有相同值的时间,除了对通过指定任何关键词参数设置的那些属性进行的新值。

  2. isoformat() − 返回表示 ISO 8601 格式时间的一个字符串

  3. str() − 对于时间 t,str(t) 等同于 t.isoformat()。

  4. strftime(format) − 返回表示通过一个明确格式字符串控制的时间的一个字符串。

  5. format(format) − 同于 time.strftime()。

  6. utcoffset() − 如果 tzinfo 为无,则返回无,否则返回 self.tzinfo.utcoffset(None),

  7. dst() − 如果 tzinfo 为无,则返回无,否则返回 self.tzinfo.dst(None),

  8. tzname() − 如果 tzinfo 为无,则返回无,否则返回 self.tzinfo.tzname(None),或引发一个异常

datetime

datetime 类的一个对象包含着日期和时间的全部信息。它假设当前的公历在两个方向上延伸,就像一个 time 对象,并且每天精确包含 3600*24 秒。

Syntax

datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)

year、month 和 day 参数是必需的。

  1. year − MINYEAR ⇐ year ⇐ MAXYEAR,

  2. month − 1 ⇐ month ⇐ 12,

  3. day − 1 ⇐ day ⇐ 给定月中和年中的天数,

  4. hour − 0 ⇐ 小时 < 24,

  5. minute − 0 ⇐ 分钟 < 60,

  6. second −0 ⇐ second < 60,

  7. microsecond − 0 ⇐ microsecond < 1000000,

  8. fold − 在 [0, 1] 中。

如果给出了任何超出范围的参数,则引发 ValueError。

Example

from datetime import datetime
dt = datetime(2023, 4, 20)
print(dt)

dt = datetime(2023, 4, 20, 11, 6, 32, 5000)
print(dt)

它将生成以下 output

2023-04-20 00:00:00
2023-04-20 11:06:32.005000

Class attributes

  1. datetime.min − 能够表示的最早 datetime:datetime(MINYEAR, 1, 1, tzinfo=None)。

  2. datetime.max − 能够表示的最晚 datetime:datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=None)。

  3. datetime.resolution − 非相等 datetime 对象之间最小的可能差, timedelta(microseconds=1)。

Example

from datetime import datetime
min = datetime.min
print("Min DateTime ", min)

max = datetime.max
print("Max DateTime ", max)

它将生成以下 output

Min DateTime 0001-01-01 00:00:00
Max DateTime 9999-12-31 23:59:59.999999

Instance Attributes

  1. datetime.year − 包括 MINYEAR 和 MAXYEAR。

  2. datetime.month − 1 到 12 包括 1 和 12。

  3. datetime.day − 1 到给定年份中给定月份的天数。

  4. datetime.hour − In range(24)

  5. datetime.minute − In range(60)

  6. datetime.second − In range(60)

  7. datetime.microsecond − In range(1000000).

  8. datetime.tzinfo − 传递给 datetime 构造函数的 tzinfo 参数作为对象,如果未传递参数,则为 None。

  9. datetime.fold − 在 [0, 1] 中。用于消除重复间隔期间不同本地时间的模糊性。

Example

from datetime import datetime
dt = datetime.now()

print("Day: ", dt.day)
print("Month: ", dt.month)
print("Year: ", dt.year)
print("Hour: ", dt.hour)
print("Minute: ", dt.minute)
print("Second: ", dt.second)

它将生成以下 output

Day: 20
Month: 4
Year: 2023
Hour: 15
Minute: 5
Second: 52

Class Methods

  1. today() − 返回当前本地 datetime tzinfo 为 None。

  2. now(tz=None) − 返回当前本地日期和时间。

  3. utcnow() − 返回当前 UTC 日期和时间,tzinfo 为 None。

  4. utcfromtimestamp(timestamp) − 返回与 POSIX 时间戳相对应的 UTC datetime,tzinfo 为 None。

  5. fromtimestamp(timestamp, timezone.utc) − 在 POSIX 合规平台上,它等于 datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=timestamp)

  6. fromordinal(ordinal) − 返回与前儒略历序号对应的 datetime,其中 1 年 1 月 1 日的序数为 1。

  7. fromisoformat(date_string) − 返回与任何有效 ISO 8601 格式中的 date_string 对应的 datetime。

Instance Methods

  1. date() − 返回与相同的年、月和日的日期对象。

  2. time() − 返回与相同小时、分钟、秒、微秒和折叠的日期对象。

  3. timetz() − 返回与相同小时、分钟、秒、微秒、折叠和 tzinfo 属性的日期对象。请参阅方法时间()。

  4. replace() − 返回一个 datetime,其属性相同,不同之处在于指定的所有关键字参数都赋予这些属性新的值。

  5. astimezone(tz=None) − 返回一个具有新 tzinfo 属性 tz 的 datetime 对象。

  6. utcoffset() − 如果 tzinfo 为 None,则返回 None,否则返回 self.tzinfo.utcoffset(self)

  7. dst() − 如果 tzinfo 为空,返回空;否则,返回 self.tzinfo.dst(self)

  8. tzname() − 如果 tzinfo 为空,返回空;否则,返回 self.tzinfo.tzname(self)

  9. timetuple() − 返回一个 time.struct_time,例如由 time.localtime() 返回的。

  10. atetime.toordinal() − 返回日期的前儒略历序数。

  11. timestamp() − 返回对应于 datetime 实例的 POSIX 时间戳。

  12. isoweekday() − 返回一周中的日期,作为一个整数,其中星期一为 1,星期天为 7。

  13. isocalendar() − 返回一个具有三个部分的已命名元组:年、周和星期几。

  14. isoformat(sep='T', timespec='auto') − 返回一个以 ISO 8601 格式表示日期和时间的字符串。

  15. str() − 对于 datetime 实例 d,str(d) 等同于 d.isoformat(' ')。

  16. ctime() − 返回一个字符串,用于表示日期和时间:

  17. strftime(format) − 返回一个字符串,用于表示日期和时间,由一个显式的格式字符串控制。

  18. format(format) − 与 strftime() 相同。

Example

from datetime import datetime, date, time, timezone

# Using datetime.combine()
d = date(2022, 4, 20)
t = time(12, 30)
datetime.combine(d, t)

# Using datetime.now()
d = datetime.now()
print (d)

# Using datetime.strptime()
dt = datetime.strptime("23/04/20 16:30", "%d/%m/%y %H:%M")

# Using datetime.timetuple() to get tuple of all attributes
tt = dt.timetuple()
for it in tt:
   print(it)

# Date in ISO format
ic = dt.isocalendar()
for it in ic:
   print(it)

它将生成以下 output

2023-04-20 15:12:49.816343
2020
4
23
16
30
0
3
114
-1
2020
17
4

timedelta

timedelta 对象表示两个日期或两个时间对象之间的持续时间。

Syntax

datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

在内部,属性存储在日、秒和微秒中。其他参数被转换为这些单位 −

  1. 毫秒转换为 1000 微秒。

  2. 分钟转换为 60 秒。

  3. 小时转换为 3600 秒。

  4. 周转换为 7 天。

然后将天、秒和微秒标准化,以便表示唯一。

Example

以下示例显示了 Python 在内部仅存储日、秒和微秒。

from datetime import timedelta
delta = timedelta(
   days=100,
   seconds=27,
   microseconds=10,
   milliseconds=29000,
   minutes=5,
   hours=12,
   weeks=2
)
# Only days, seconds, and microseconds remain
print (delta)

它将生成以下 output

114 days, 12:05:56.000010

Example

以下例子展示了如何将 timedelta 对象添加到日期时间对象。

from datetime import datetime, timedelta

date1 = datetime.now()

date2= date1+timedelta(days = 4)
print("Date after 4 days:", date2)

date3 = date1-timedelta(15)
print("Date before 15 days:", date3)

它将生成以下 output

Date after 4 days: 2023-04-24 18:05:39.509905
Date before 15 days: 2023-04-05 18:05:39.509905

Class Attributes

  1. timedelta.min - 最负的 timedelta 对象,timedelta(-999999999)。

  2. timedelta.max - 最正的 timedelta 对象 timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)。

  3. timedelta.resolution - 非相等 timedelta 对象之间可能存在的最小差值,timedelta(microseconds=1)

Example

from datetime import timedelta

# Getting minimum value
min = timedelta.min
print("Minimum value:", min)

max = timedelta.max
print("Maximum value", max)

它将生成以下 output

Minimum value: -999999999 days, 0:00:00
Maximum value 999999999 days, 23:59:59.999999

Instance Attributes

由于 timedelta 对象在内部只存储日、秒和微秒,因此它们是 timedelta 对象的唯一实例属性。

  1. days - 介于-999999999和999999999之间(包含)。

  2. seconds - 介于 0 和 86399之间(包含)。

  3. microseconds - 介于 0 和 999999之间(包含)。

Instance Methods

timedelta.total_seconds() - 返回持续时间中包含的总秒数。

Example

from datetime import timedelta
year = timedelta(days=365)
years = 5 * year
print (years)
print (years.days // 365)
646
year_1 = years // 5
print(year_1.days)

它将生成以下 output

1825 days, 0:00:00
5
365

Python - Maths

Python 标准库提供了 math 模块,该模块包含用于执行不同数学运算的许多预定义函数。这些函数不适用于复数。有一个 cmath 模块,它包含用于复数的数学函数。

Functions in Math Module

以下是 math 模块可用的函数列表:

这些函数可以分类为以下类别:

Python - Iterators

Python 中的迭代器是一个表示数据流的对象,它遵循要求其支持 iter () 和 next () 方法的迭代器协议。Python 的内置方法 iter() 实现 iter () 方法。它接收一个可迭代对象并返回一个迭代器对象。内置的 next() 函数在内部调用迭代器的 next () 方法来返回流中的连续项。当没有更多的数据可用时,将引发 StopIteration 异常。

Python 隐式使用迭代器来处理集合数据类型,例如列表、元组或字符串。这就是为什么这些数据类型被称为可迭代对象的原因。我们通常使用 for 循环来遍历可迭代对象,如下所示:

for element in sequence:
 print (element)

Python 的内置方法 iter() 实现 iter () 方法。它接收一个可迭代对象并返回一个迭代器对象。

Example

以下代码从序列类型列表、字符串和元组中获取迭代器对象。iter() 函数也从字典返回 keyiterator。然而,int 不是可迭代对象,因此会产生 TypeError。

print (iter("aa"))
print (iter([1,2,3]))
print (iter((1,2,3)))
print (iter({}))
print (iter(100))

它将生成以下 output

<str_ascii_iterator object at 0x000001BB03FFAB60>
<list_iterator object at 0x000001BB03FFAB60>
<tuple_iterator object at 0x000001BB03FFAB60>
<dict_keyiterator object at 0x000001BB04181670>
Traceback (most recent call last):
   File "C:\Users\user\example.py", line 5, in <module>
      print (iter(100))
            ^^^^^^^^^
TypeError: 'int' object is not iterable

迭代器对象有 next () 方法。每次调用它时,它都会返回迭代器流中的下一个元素。当流耗尽时,会引发 StopIteration 错误。调用 next() 函数等同于调用迭代器对象的 next () 方法。

Example

it = iter([1,2,3])
print (next(it))
print (it.__next__())
print (it.__next__())
print (next(it))

它将生成以下 output

1
2
3
Traceback (most recent call last):
   File "C:\Users\user\example.py", line 5, in <module>
      print (next(it))
            ^^^^^^^^
StopIteration

Example

您可以使用异常处理机制来捕获 StopIteration。

it = iter([1,2,3, 4, 5])
print (next(it))
while True:
   try:
      no = next(it)
      print (no)
   except StopIteration:
      break

它将生成以下 output

1
2
3
4
5

要在 Python 中定义一个自定义迭代器类,该类必须定义 iter () 和 next () 方法。

在下面的示例中,Oddnumbers 是一个实现了 iter () 和 next () 方法的类。在每次调用 next () 时,数值会递增 2,从而在 1 到 10 的范围内流式处理奇数。

Example

class Oddnumbers:

   def __init__(self, end_range):
      self.start = -1
      self.end = end_range

   def __iter__(self):
      return self

   def __next__(self):
      if self.start < self.end-1:
         self.start += 2
         return self.start
      else:
         raise StopIteration

countiter = Oddnumbers(10)
while True:
   try:
      no = next(countiter)
      print (no)
   except StopIteration:
      break

它将生成以下 output

1
3
5
7
9

Asynchronous Iterator

从 Python 3.10 版本开始,添加了两个内置函数 aiter() 和 anext()。aiter() 函数返回一个异步迭代器对象。它是经典迭代器的异步对应项。任何异步迭代器都必须支持 aiter () 和 anext () 方法。这两个内置函数在内部调用这些方法。

与经典迭代器类似,异步迭代器也提供了一个对象流。当流用尽时,会引发 StopAsyncIteration 异常。

在下面给出的示例中,声明了一个异步迭代器类 Oddnumbers。它实现了 aiter () 和 anext () 方法。在每次迭代中,都会返回下一个奇数,程序等待一秒钟,以便可以异步执行任何其他进程。

与常规函数不同,异步函数称为协程,并使用 asyncio.run() 方法执行。main() 协程包含一个 while 循环,它顺序获取奇数,如果该数超过 9 则会引发 StopAsyncIteration。

Example

import asyncio

class Oddnumbers():
   def __init__(self):
      self.start = -1

   def __aiter__(self):
      return self

   async def __anext__(self):
      if self.start >= 9:
         raise StopAsyncIteration
      self.start += 2
      await asyncio.sleep(1)
      return self.start

async def main():
   it = Oddnumbers()
   while True:
      try:
         awaitable = anext(it)
         result = await awaitable
         print(result)
      except StopAsyncIteration:
         break

asyncio.run(main())

它将生成以下 output

1
3
5
7
9

Python - Generators

Python 中的生成器是一种特殊类型的函数,它返回一个迭代器对象。它看起来类似于一个普通的 Python 函数,因为它的定义也以 def 关键字开头。但是,生成器不使用末尾的 return 语句,而是使用 yield 关键字。

Syntax

def generator():
 . . .
 . . .
 yield obj
it = generator()
next(it)
. . .

函数末尾的 return 语句表示函数主体的执行已结束,该函数中的所有局部变量都超出了范围。如果再次调用该函数,则会重新初始化局部变量。

生成器函数的行为不同。它第一次像普通函数一样被调用,但是当它的 yield 语句出现时,它的执行暂时暂停,控件被传回。生成的结果被调用者使用。对 next() 内置函数的调用从暂停的点重新启动生成器的执行,并为迭代器生成下一个对象。随着 yield 后续提供迭代器中的下一个项目,这个循环会重复进行,直到迭代器耗尽。

Example 1

在下面的代码中,函数是一个生成器,它连续生成 1 到 5 的整数。调用它时,它返回一个迭代器。每次调用 next() 都会将控件传回到生成器中并获取下一个整数。

def generator(num):
   for x in range(1, num+1):
      yield x
   return

it = generator(5)
while True:
   try:
      print (next(it))
   except StopIteration:
      break

它将生成以下 output

1
2
3
4
5

生成器函数返回一个动态迭代器。因此,它比从 Python 序列对象中获得的普通迭代器更省内存。例如,如果您想要获取斐波那契序列中的前 n 个数字。您可以编写一个普通函数并构建一个斐波那契数字列表,然后使用循环迭代该列表。

Example 2

下面是获取斐波那契数字列表的普通函数 −

def fibonacci(n):
   fibo = []
   a, b = 0, 1
   while True:
      c=a+b
      if c>=n:
         break
      fibo.append(c)
      a, b = b, c
   return fibo
f = fibonacci(10)
for i in f:
   print (i)

它将生成如下输出:

1
2
3
5
8

上面的代码收集了列表中的所有斐波那契数列数字,然后使用循环遍历列表。想象一下,我们想要一个生成很大数字的斐波那契数列。在这种情况下,必须收集列表中的所有数字,这需要大量的内存。生成器在这里很有用,因为它在列表中生成一个数字并将其交由使用者使用。

Example 3

以下代码是用于斐波那契数列的基于生成器的解决方案 −

def fibonacci(n):
   a, b = 0, 1
   while True:
      c=a+b
      if c>=n:
         break
      yield c
      a, b = b, c
   return

f = fibonacci(10)
while True:
   try:
      print (next(f))
   except StopIteration:
      break

Asynchronous Generator

异步生成器是一个返回异步迭代器的协程。协程是一个使用 async 关键字定义的 Python 函数,它可以调度其他协程和任务并等待这些协程和任务。与普通生成器一样,异步生成器在每次调用 anext() 函数时(而不是 next() 函数)在迭代器中生成增量项目。

Syntax

async def generator():
. . .
. . .
yield obj
it = generator()
anext(it)
. . .

Example 4

以下代码演示了一个协程生成器,该生成器在 async for 循环的每次迭代中生成递增的整数。

import asyncio

async def async_generator(x):
   for i in range(1, x+1):
      await asyncio.sleep(1)
      yield i

async def main():
   async for item in async_generator(5):
      print(item)

asyncio.run(main())

它将生成以下 output

1
2
3
4
5

Example 5

下面,我们编写一个用于斐波那契数列的异步生成器。为了模拟协程中的某些异步任务,程序在生成下一个数字之前调用 sleep() 方法持续 1 秒。因此,您将在屏幕上看到这些数字在延迟一秒钟后打印出来。

import asyncio

async def fibonacci(n):
   a, b = 0, 1
   while True:
      c=a+b
      if c>=n:
         break
      await asyncio.sleep(1)
      yield c
      a, b = b, c
   return

async def main():
   f = fibonacci(10)
   async for num in f:
      print (num)

asyncio.run(main())

它将生成以下 output

1
2
3
5
8

Python - Closures

在本章中,我们讨论了 Python 中闭包的概念。在 Python 中,函数被称为一阶对象。与基本数据类型一样,函数也可以用于分配给变量或作为参数传递。

Nested Functions

您还可以进行嵌套函数声明,其中一个函数定义在另一个函数的主体中。

Example

def functionA():
   print ("Outer function")
   def functionB():
      print ("Inner function")
   functionB()

functionA()

它将生成以下 output

Outer function
Inner function

在上面的示例中,functionB 是在 functionA 中定义的。然后从外部函数的作用域内调用内部函数。

如果外部函数接收到任何参数,则可以将该参数传递给内部函数。

def functionA(name):
   print ("Outer function")
   def functionB():
      print ("Inner function")
      print ("Hi {}".format(name))
   functionB()

functionA("Python")

它将生成如下输出:

Outer function
Inner function
Hi Python

What is a Closure?

闭包是一个嵌套函数,它可以访问来自已经完成执行的包含函数中的变量。此类变量未绑定在局部作用域中。要使用不可变变量(数字或字符串),必须使用非局部关键字。

Python 闭包的主要优点是,我们可以帮助避免使用全局值并提供某种形式的数据隐藏。它们用于 Python 装饰器。

Example

def functionA(name):
   name ="New name"
   def functionB():
      print (name)
   return functionB

myfunction = functionA("My name")
myfunction()

它将生成以下 output

New name

在上面的示例中,我们有一个函数A 函数,它创建并返回另一个函数函数B。嵌套函数B 函数是闭包。

外部函数A 函数返回一个函数B 函数并将其分配给 myfunction 变量。即使它已经完成执行。但是,打印机闭包仍可以访问 name 变量。

nonlocal Keyword

在 Python 中,nonlocal 关键字允许访问局部作用域外部的变量。这在闭包中用于修改存在于外部变量作用域中的不可变变量。

Example

def functionA():
   counter =0
   def functionB():
      nonlocal counter
      counter+=1
      return counter
   return functionB

myfunction = functionA()

retval = myfunction()
print ("Counter:", retval)

retval = myfunction()
print ("Counter:", retval)

retval = myfunction()
print ("Counter:", retval)

它将生成以下 output

Counter: 1
Counter: 2
Counter: 3

Python - Decorators

Python 中的装饰器是一个接收另一个函数作为参数的函数。装饰器要装饰的参数函数。装饰器扩展了参数函数的行为,而不会实际修改它。

在本章中,我们 whall 将学习如何使用 Python 装饰器。

Python 中的函数是一等对象。这意味着它可以作为参数传递给另一个函数,就像其他数据类型(例如数字、字符串或列表等)。还可以在另一个函数内定义一个函数。这样的函数称为嵌套函数。此外,函数也可以返回其他函数。

Syntax

装饰器函数的典型定义如下 −

def decorator(arg_function): #arg_function to be decorated
   def nested_function():
      #this wraps the arg_function and extends its behaviour
      #call arg_function
      arg_function()
   return nested_function

此处为一个普通的 Python 函数 −

def function():
   print ("hello")

你现在可以通过将该函数传递给装饰器来装饰它以扩展其行为 −

function=decorator(function)

如果现在执行此函数,它将显示装饰器扩展的输出。

Example 1

以下代码是装饰器的简单示例 −

def my_function(x):
   print("The number is=",x)

def my_decorator(some_function,num):
   def wrapper(num):
      print("Inside wrapper to check odd/even")
      if num%2 == 0:
         ret= "Even"
      else:
         ret= "Odd!"
      some_function(num)
      return ret
   print ("wrapper function is called")
   return wrapper

no=10
my_function = my_decorator(my_function, no)
print ("It is ",my_function(no))

my_function() 刚输出接收到的数字。但是,通过将它传递给 my_decorator 来修改其行为。内部函数接收数字并返回它是奇数/偶数。上面代码的输出为 −

wrapper function is called
Inside wrapper to check odd/even
The number is= 10
It is Even

Example 2

装饰函数的一种优雅方式是在其定义之前只提一下装饰器名前面加上 @ 符号。上面的例子使用这种符号重写了 −

def my_decorator(some_function):
   def wrapper(num):
      print("Inside wrapper to check odd/even")
      if num%2 == 0:
         ret= "Even"
      else:
         ret= "Odd!"
      some_function(num)
      return ret
   print ("wrapper function is called")
   return wrapper

@my_decorator
def my_function(x):
   print("The number is=",x)
no=10
print ("It is ",my_function(no))

Python 的标准库定义了以下内置装饰器 −

@classmethod Decorator

classmethod 是一个内置函数。它将方法转换为类方法。类方法不同于实例方法。在类中定义的实例方法由其对象调用。该方法接收由 self 引用的隐式对象。另一方面,类方法隐式地将类本身作为第一个参数接收。

Syntax

为了声明类方法,使用了以下装饰器符号 −

class Myclass:
   @classmethod
   def mymethod(cls):
   #....

@classmethod 表单是前面描述的函数装饰器的形式。mymethod 接收对类的引用。它可以由类及其对象调用。这意味着 Myclass.mymethod 和 Myclass().mymethod 都是有效的调用。

Example 3

让我们在以下示例的帮助下了解类方法的行为−

class counter:
   count=0
   def __init__(self):
      print ("init called by ", self)
      counter.count=counter.count+1
      print ("count=",counter.count)
   @classmethod
   def showcount(cls):
      print ("called by ",cls)
      print ("count=",cls.count)

c1=counter()
c2=counter()
print ("class method called by object")
c1.showcount()
print ("class method called by class")
counter.showcount()

在类定义中 count 是一个类属性。 init () 方法是构造器,显然是实例方法,因为它接收了 self 作为对象引用。声明的每个对象都会调用此方法,并将计数增加 1。

@classmethod 装饰器将 showcount() 方法转换为类方法,该方法接收对该类的引用作为参数,即使它是由其对象调用的。即使当 c1 对象调用 showcount 时,它也会显示 counter 类的引用。

它将显示以下内容 output

init called by <__main__.counter object at 0x000001D32DB4F0F0>
count= 1
init called by <__main__.counter object at 0x000001D32DAC8710>
count= 2
class method called by object
called by <class '__main__.counter'>
count= 2
class method called by class
called by <class '__main__.counter'>

@staticmethod Decorator

staticmethod 也是 Python 标准库中的一个内置函数。它会将一个方法转换为一个静态方法。即使是通过类或类的实例调用的,静态方法也不接受任何引用参数。以下是在类中声明静态方法的符号说明−

Syntax

class Myclass:
@staticmethod
def mymethod():
#....

即使 Myclass.mymethod 和 Myclass().mymethod 都是有效的调用,但静态方法都不会接收到对 two 的引用。

Example 4

counter 类进行修改如下−

class counter:
   count=0
   def __init__(self):
      print ("init called by ", self)
      counter.count=counter.count+1
      print ("count=",counter.count)
   @staticmethod
   def showcount():
      print ("count=",counter.count)

c1=counter()
c2=counter()
print ("class method called by object")
c1.showcount()
print ("class method called by class")
counter.showcount()

和以前一样,类属性 count 在 init () 方法中声明每个对象后增加。但是,由于 mymethod() 是一个静态方法,它既不接受 self 参数也不接受 cls 参数。因此,显示类属性 count 的值时,必须显式引用 counter。

以上代码的 output 如下−

init called by <__main__.counter object at 0x000002512EDCF0B8>
count= 1
init called by <__main__.counter object at 0x000002512ED48668>
count= 2
class method called by object
count= 2
class method called by class
count= 2

@property Decorator

Python 的 property() 内置函数是用于访问类的实例变量的一个接口。@property 装饰器将实例方法转换为同名只读属性的“getter”(获得器),并且它将此属性的文档字符串设置为“获取实例变量的当前值”。

您可以使用以下三个装饰器来定义属性−

  1. @property − 将方法声明为属性。

  2. @&lt;property-name&gt;.setter: − 指定用于将值设置为属性的属性的 setter(设定器)方法。

  3. @&lt;property-name&gt;.deleter − 指定用于删除属性的属性的 delete(删除器)方法。

property() 函数返回的属性对象具有 getter、setter 和 delete 方法。

property(fget=None, fset=None, fdel=None, doc=None)

fget 参数是 getter 方法,fset 是 setter 方法。它还可以选择性地使用 fdel 作为删除对象的方法,而 doc 是文档字符串。

还可以使用以下语法为 property() 对象的 setter 和 getter 赋值。

speed = property()
speed=speed.getter(speed, get_speed)
speed=speed.setter(speed, set_speed)

其中 get_speed() 和 set_speeds() 是在 Car 类中检索和设置实例变量 speed 的值的方法。

可以通过 @property 装饰器实现上述语句。使用装饰器后,重新编写的 car 类如下−

class car:
   def __init__(self, speed=40):
      self._speed=speed
      return
   @property
   def speed(self):
      return self._speed
   @speed.setter
   def speed(self, speed):
      if speed<0 or speed>100:
         print ("speed limit 0 to 100")
         return
      self._speed=speed
      return

c1=car()
print (c1.speed) #calls getter
c1.speed=60 #calls setter

属性装饰器是一种非常方便且推荐的实例属性处理方法。

Python - Recursion

自己调用自己的函数被称为递归函数。当某个问题以自我为定义时,就会使用该方式。虽然这涉及迭代,但使用迭代方法解决此类问题可能会很繁琐。递归方式为看起来很复杂的问题提供了非常简洁的解决方案。

递归最流行的例子是阶乘的计算。数学上阶乘定义为 -

n! = n × (n-1)!

可以看出,我们使用阶乘本身来定义阶乘。因此,这是一个编写递归函数的合适案例。让我们展开以上定义以计算 5 的阶乘值。

5! = 5 × 4!
   5 × 4 × 3!
   5 × 4 × 3 × 2!
   5 × 4 × 3 × 2 × 1!
   5 × 4 × 3 × 2 × 1
= 120

虽然我们可以使用循环执行此计算,但其递归函数涉及通过递减数字依次调用它,直到数字变为 1。

Example 1

以下示例显示了如何使用递归函数计算阶乘 -

def factorial(n):

   if n == 1:
      print (n)
      return 1
   else:
      print (n,'*', end=' ')
      return n * factorial(n-1)

print ('factorial of 5=', factorial(5))

它将生成以下 output

5 * 4 * 3 * 2 * 1
factorial of 5= 120

让我们看另一个理解递归工作原理的示例。眼前的问题是检查给定数字是否存在于列表中。

虽然我们可以使用 for 循环在列表中按顺序查找某个数字并比较每个数字,但如果列表太大,顺序查找效率不高。二分查找算法检查索引“high”是否大于索引“low”。根据“mid”变量中存在的 value,再次调用该函数来搜索元素。

我们有一个按升序排列的数字列表。然后我们找到列表的中间点,并根据所需的数字是否小于或大于中间点的数字来将检查限制在中间点的左右两侧。

下图显示了二分查找的工作原理 -

python recursion

Example 2

以下代码实现了递归二分查找技术 -

def bsearch(my_list, low, high, elem):
   if high >= low:
      mid = (high + low) // 2
      if my_list[mid] == elem:
         return mid
      elif my_list[mid] > elem:
         return bsearch(my_list, low, mid - 1, elem)
      else:
         return bsearch(my_list, mid + 1, high, elem)
   else:
      return -1

my_list = [5,12,23, 45, 49, 67, 71, 77, 82]
num = 67
print("The list is")
print(my_list)
print ("Check for number:", num)
my_result = bsearch(my_list,0,len(my_list)-1,num)

if my_result != -1:
   print("Element found at index ", str(my_result))
else:
   print("Element not found!")

它将生成以下 output

The list is
[5, 12, 23, 45, 49, 67, 71, 77, 82]
Check for number: 67
Element found at index 5

您可以检查列表中不同数字以及不在列表中的数字的输出。

Python - Regular Expressions

正则表达式是由一个特殊字符序列组成的,使用在模式中保存的特殊语法可以帮助匹配或查找字符或一组字符。正则表达式也称为正则表达式,是定义搜索模式的字符序列。它通常被称为正则表达式或正则表达式,它是指定文本中匹配模式的字符序列。通常,字符串搜索算法使用这种模式对字符串进行“查找”或“查找并替换”操作,或者用于输入验证。

数据科学项目中的大规模文本处理需要处理文本数据。正则表达式处理得到包括 Python 在内的多种编程语言的支持。Python 的标准库为此目的提供了“re”模块。

由于 re 模块中定义的大多数函数都使用原始字符串,因此让我们首先了解一下什么是原始字符串。

Raw Strings

正则表达式使用反斜杠字符 ('\') 来指示特殊形式或允许使用特殊字符而不调用它们的特殊含义。另一方面,Python 使用相同字符作为转义字符。因此,Python 使用原始字符串表示法。

如果在引号前加上 r 或 R,则字符串将成为原始字符串。因此,'Hello' 是一个普通字符串,而 r’Hello' 是一个原始字符串。

>>> normal="Hello"
>>> print (normal)
Hello
>>> raw=r"Hello"
>>> print (raw)
Hello

在正常情况下,两者之间没有区别。但是,当转义字符嵌入字符串中时,普通字符串实际上解释转义序列,而原始字符串不处理转义字符。

>>> normal="Hello\nWorld"
>>> print (normal)
Hello
World
>>> raw=r"Hello\nWorld"
>>> print (raw)
Hello\nWorld

在上述示例中,打印普通字符串时,转义字符 '\n' 会被处理为引入换行符。然而,由于原始字符串运算符“r”,转义字符的作用不会按其含义进行转换。

Metacharacters

大多数字母和字符只是匹配它们自己。但是,有些字符是特殊元字符,不匹配它们自己。元字符是具有特殊含义的字符,类似通配符中的 *。

以下是元字符的完整列表:

. ^ $ * + ? { } [ ] \ | ( )

方括号符号 [ 和 ] 指示一组您希望匹配的字符。字符可以逐个列出,或作为以 '-' 分隔的字符范围列出。

'\' 是一个转义元字符。后面跟着各种字符会形成各种特殊序列。如果您需要匹配 [ 或 \, 您可以使用反斜杠为它们加上前缀以消除其特殊含义:\[ 或 \\。

以 '\' 开头的此类特殊序列表示的预定义字符集如下所示:

Python 的 re 模块提供了用于查找匹配、搜索模式和用其他字符串替换匹配字符串等有用函数。

re.match() Function

此函数尝试使用可选标志匹配字符串开头的 RE 模式。

以下是此函数的 syntax -

re.match(pattern, string, flags=0)

以下是参数说明 −

re.match 函数在成功时返回一个 match 对象,在失败时返回 None 。一个匹配对象实例包含有关匹配的信息:从何处开始和结束,它所匹配的子字符串等。

匹配对象的 start() 方法返回模式在字符串中的起始位置,end() 返回结束点。

如果找不到模式,则匹配对象为 None。

我们使用 match 对象的 group(num) 或 groups() 函数来获取匹配的表达式。

Example

import re
line = "Cats are smarter than dogs"
matchObj = re.match( r'Cats', line)
print (matchObj.start(), matchObj.end())
print ("matchObj.group() : ", matchObj.group())

它将生成以下 output

0 4
matchObj.group() : Cats

re.search() Function

该函数在字符串中搜索第一个出现的 RE 模式,带有可选标记。

以下是此函数的 syntax -

re.search(pattern, string, flags=0)

以下是参数说明 −

re.search 函数在成功时返回 match 对象,在失败时返回 none 。我们使用 match 对象的 group(num) 或 groups() 函数获取匹配的表达式。

Example

import re
line = "Cats are smarter than dogs"
matchObj = re.search( r'than', line)
print (matchObj.start(), matchObj.end())
print ("matchObj.group() : ", matchObj.group())

它将生成以下 output

17 21
matchObj.group() : than

Matching Vs Searching

Python 提供基于正则表达式的两种不同的基本操作:match 只检查字符串开头的匹配,而 search 则检查字符串中任何位置的匹配(这是 Perl 的默认操作)。

Example

import re
line = "Cats are smarter than dogs";
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
   print ("match --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")
searchObj = re.search( r'dogs', line, re.M|re.I)
if searchObj:
   print ("search --> searchObj.group() : ", searchObj.group())
else:
   print ("Nothing found!!")

当执行以上代码时,它会产生以下 output -

No match!!
search --> matchObj.group() : dogs

re.findall() Function

findall() 函数将字符串中的模式所有不重叠的匹配项作为字符串或元组列表返回。从左到右扫描字符串,并按找到的顺序返回匹配项。结果中包含空匹配项。

Syntax

re.findall(pattern, string, flags=0)

Parameters

Example

import re
string="Simple is better than complex."
obj=re.findall(r"ple", string)
print (obj)

它将生成以下 output

['ple', 'ple']

以下代码借助 findall() 函数获取句子中的单词列表。

import re
string="Simple is better than complex."
obj=re.findall(r"\w*", string)
print (obj)

它将生成以下 output

['Simple', '', 'is', '', 'better', '', 'than', '', 'complex', '', '']

re.sub() Function

使用正则表达式的最重要的 re 方法之一是 sub

Syntax

re.sub(pattern, repl, string, max=0)

此方法使用 repl 替换字符串中 RE 模式的所有出现,除非提供了 max,否则将替换所有出现。此方法返回修改后的字符串。

Example

import re
phone = "2004-959-559 # This is Phone Number"

# Delete Python-style comments
num = re.sub(r'#.*$', "", phone)
print ("Phone Num : ", num)

# Remove anything other than digits
num = re.sub(r'\D', "", phone)
print ("Phone Num : ", num)

它将生成以下 output

Phone Num : 2004-959-559
Phone Num : 2004959559

Example

以下示例使用 sub() 函数将所有 is 替换为单词 was −

import re
string="Simple is better than complex. Complex is better than complicated."
obj=re.sub(r'is', r'was',string)
print (obj)

它将生成以下 output

Simple was better than complex. Complex was better than complicated.

re.compile() Function

compile() 函数将正则表达式模式编译成正则表达式对象,可以使用该对象与其 match()、search() 和其他方法进行匹配。

Syntax

re.compile(pattern, flags=0)

Flags

序列 −

prog = re.compile(pattern)
result = prog.match(string)

等效于 −

result = re.match(pattern, string)

但当在单个程序中多次使用表达式时,使用 re.compile() 并保存生成的正则表达式对象以便重用更为有效。

Example

import re
string="Simple is better than complex. Complex is better than complicated."
pattern=re.compile(r'is')
obj=pattern.match(string)
obj=pattern.search(string)
print (obj.start(), obj.end())

obj=pattern.findall(string)
print (obj)

obj=pattern.sub(r'was', string)
print (obj)

它将生成如下输出:

7 9
['is', 'is']
Simple was better than complex. Complex was better than complicated.

re.finditer() Function

此函数返回一个迭代器,为字符串中 RE 模式的所有非重叠匹配生成匹配对象。

Syntax

re.finditer(pattern, string, flags=0)

Example

import re
string="Simple is better than complex. Complex is better than
complicated."
pattern=re.compile(r'is')
iterator = pattern.finditer(string)
print (iterator )

for match in iterator:
   print(match.span())

它将生成以下 output

(7, 9)
(39, 41)

Use Cases of Python Regex

Finding all Adverbs

findall() 匹配模式的所有出现,而不仅仅是 search() 所匹配的第一个出现。例如,如果编写者想要查找某个文本中所有副词,他们可能会以以下方式使用 findall() −

import re
text = "He was carefully disguised but captured quickly by police."
obj = re.findall(r"\w+ly\b", text)
print (obj)

它将生成以下 output

['carefully', 'quickly']

Finding words starting with vowels

import re
text = 'Errors should never pass silently. Unless explicitly silenced.'
obj=re.findall(r'\b[aeiouAEIOU]\w+', text)
print (obj)

它将生成以下 output

['Errors', 'Unless', 'explicitly']

Python - PIP

Python 标准库是大量开箱即用的模块和软件包的集合。除了这些软件包之外,Python 程序员通常还需要使用某些第三方库。第三方 Python 包托管在名为 Python Package Index (https://pypi.org/) 的仓库中。

要从该仓库安装一个包,你需要一个包管理器工具。PIP 是最受欢迎的包管理器之一。

PIP 实用程序随 Python 的标准发行版自动安装,特别是从 3.4 版本开始。它存在于 Python 安装目录中的 scripts 文件夹中。例如,当 Python 3.11 安装在 Windows 计算机上时,你可以在 C:\Python311\Scripts 文件夹中找到 pip3.exe。

如果 pip 默认情况下没有安装,可以通过以下程序安装。

从以下 URL 下载 get-pip.py 脚本 -

https://bootstrap.pypa.io/get-pip.py

要安装,从命令提示符运行上述脚本 -

c:\Python311>python get-pip.py

在 scripts 文件夹中,pip 和 pip3 都存在。如果使用 pip 安装某个包,将安装其与 Python 2.x 兼容的版本。因此,要安装与 Python 3 兼容的版本,请使用 pip3。

Install a Package

要从 PyPi 安装某个包,请使用 PIP 的安装命令。以下命令在当前 Python 安装中安装 Flask 库。

pip3 install flask

该包及其依赖项(如果有)将从 PyPI 仓库安装。上述命令在终端中生成以下日志 -

Collecting flask
   Downloading Flask-2.2.3-py3-none-any.whl (101 kB)
      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
101.8/101.8 kB 3.0 MB/s eta 0:00:00
Collecting Werkzeug>=2.2.2
   Downloading Werkzeug-2.2.3-py3-none-any.whl (233 kB)
      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
233.6/233.6 kB 7.2 MB/s eta 0:00:00
Collecting Jinja2>=3.0
   Downloading Jinja2-3.1.2-py3-none-any.whl (133 kB)
      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
133.1/133.1 kB 8.2 MB/s eta 0:00:00
Collecting itsdangerous>=2.0
   Downloading itsdangerous-2.1.2-py3-none-any.whl (15 kB)
Collecting click>=8.0
   Downloading click-8.1.3-py3-none-any.whl (96 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
96.6/96.6 kB 5.4 MB/s eta 0:00:00
Requirement already satisfied: colorama in
c:\users\mlath\appdata\roaming\python\python311\site-packages (from
click>=8.0->flask) (0.4.6)
Collecting MarkupSafe>=2.0
   Downloading MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl (16 kB)
Installing collected packages: MarkupSafe, itsdangerous, click,
Werkzeug, Jinja2, flask
Successfully installed Jinja2-3.1.2 MarkupSafe-2.1.2 Werkzeug-2.2.3
click-8.1.3 flask-2.2.3 itsdangerous-2.1.2

默认情况下,将安装所需包的最新可用版本。要指定所需的版本,

pip3 install flask==2.0.0

要测试包安装是否完成,请打开 Python 解释器并尝试导入它并检查版本。如果包尚未成功安装,将收到 ModuleNotFoundError。

>>> import flask
>>> print (flask.__version__)
2.2.3
>>> import dummypackage
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'dummypackage'

PIP 实用程序与以下内容一起工作 -

  1. PyPI(和其他索引)使用需求规范。

  2. VCS project urls.

  3. Local project directories.

  4. 本地或远程源存档。

Use requirements.txt

你可以通过在名为 requirements.txt 的文本文件中提及所需包的列表来一次性执行包安装。

例如,以下 requirements.txt 文件包含要为 FastAPI 库安装的依赖项列表。

anyio==3.6.2
click==8.1.3
colorama==0.4.6
fastapi==0.88.0
gunicorn==20.1.0
h11==0.14.0
idna==3.4
pydantic==1.10.4
sniffio==1.3.0
starlette==0.22.0
typing_extensions==4.4.0
uvicorn==0.20.0

现在在 PIP 安装命令中使用 -r 开关。

pip3 install -r requirements.txt

PIP 实用程序与以下命令一起使用:

pip uninstall

此命令用于卸载一个或多个已安装的包。

Syntax

pip3 uninstall package, [package2, package3, . . ]

这将卸载包及其依赖项。

Example

pip3 uninstall flask

You will be asked confirmation for removal before proceeding.

pip3 uninstall flask
Found existing installation: Flask 2.2.3
Uninstalling Flask-2.2.3:
   Would remove:
   c:\python311\lib\site-packages\flask-2.2.3.dist-info\*
   c:\python311\lib\site-packages\flask\*
   c:\python311\scripts\flask.exe
Proceed (Y/n)?

pip list

此命令提供已安装包的列表,包括可编辑包。按不区分大小写的顺序列出包。

Syntax

pip3 list

pip list 命令可以使用以下开关:

-o, --outdated: List outdated packages

pip3 list --outdated
Package     Version    Latest     Type
--------    -------    -------    -----
debugpy     1.6.6      1.6.7      wheel
ipython     8.11.0     8.12.0     wheel
pip         22.3.1     23.0.1     wheel
Pygments    2.14.0     2.15.0     wheel
setuptools  65.5.0     67.6.1     wheel

-u, --uptodate : List uptodate packages

pip3 list --uptodate
Package           Version
--------          --------- -------
click             8.1.3
colorama          0.4.6
executing         1.2.0
Flask             2.2.3
jedi              0.18.2
Jinja2            3.1.2
python-dateutil   2.8.2
pyzmq             25.0.2
six               1.16.0
Werkzeug          2.2.3

pip show

此命令显示一个或多个已安装包的信息。输出采用符合 RFC 规范的邮件头格式。

Syntax

pip3 show package

Example

pip3 show flask
Name: Flask
Version: 2.2.3
Summary: A simple framework for building complex web applications.
Home-page: https://palletsprojects.com/p/flask
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
License: BSD-3-Clause
Location: C:\Python311\Lib\site-packages
Requires: click, itsdangerous, Jinja2, Werkzeug
Required-by:

pip freeze

此命令以需求格式输出已安装的包。按不区分大小写的顺序列出所有包。

Syntax

pip3 freeze

此命令的输出可以使用以下命令重定向到文本文件:

pip3 freeze > requirements.txt

pip download

此命令从以下位置下载包:

  1. PyPI(和其他索引)使用需求规范。

  2. VCS project urls.

  3. Local project directories.

  4. 本地或远程源存档。

事实上,pip download 完成与 pip install 相同的解析和下载,但它不会安装依赖项,而是将下载的发行版收集到提供的目录(默认为当前目录)中。此目录稍后可作为值传递给 pip install --find-links,以方便离线或锁定包的安装。

Syntax

pip3 download somepackage

此命令搜索包含给定查询的名称或摘要的 PyPI 包。

Syntax

pip3 search query

pip config

此命令用于管理本地和全局配置。

Subcommands

  1. list - 列出活动配置(或来自指定的文件)。

  2. edit - 使用编辑器编辑配置文件。

  3. get - 获取与 command.option 关联的值。

  4. set - 设置 command.option=value。

  5. unset - 取消设置与 command.option 关联的值。

  6. debug − 列出配置的文件和在它们下面定义的值。

配置键应该点隔开的命令和选项的名称,特殊的开头的“global”对于任何的命令都有作用。

Example

pip config set global.index-url https://example.org/

这将会为所有的命令配置索引 URL。

pip config set download.timeout 10

这将会仅为“pip download”命令配置一个 10 秒的超时。

Python - Database Access

数据输入和在程序执行期间生成的数据存储在 RAM 中。如果要持久存储,它需要存储在数据库表中。有各种的关系数据库管理系统 (RDBMS) 可用。

  1. GadFly

  2. MySQL

  3. PostgreSQL

  4. Microsoft SQL Server

  5. Informix

  6. Oracle

  7. Sybase

  8. SQLite

  9. and many more…​

在本节中,我们将学习如何使用 Python 访问数据库,如何将 Python 的对象的数据存储在 SQLite 数据库中,以及如何从 SQLite 数据库中检索数据,并使用 Python 程序对其进行处理。

关系数据库使用 SQL(结构化查询语言)对数据库表执行插入/删除/更新操作。但是,SQL 的实现因一种数据库类型而异。这会产生不兼容问题。一个数据库的 SQL 指令与另一个不匹配。

为了克服这个不兼容,在 PEP(Python 增强提案)249 中提出了一个通用的界面。这个提案称为 DB-API,并要求一个用于与 Python 交互的数据库驱动程序必须兼容 DB-API。

driver interfaces

Python 的标准库包括 sqlite3 模块,这是一个适用于 SQLite3 数据库的与 DB_API 兼容的驱动,它还是一个 DB-API 的参考实现。

由于所需要的 DB-API 接口是内置的,我们可以轻松地将 Python 应用程序同 SQLite 数据库一起使用。对于其他类型的数据库,你将必须安装相关的 Python 包。

一个类似于 sqlite3 的 DB-API 模块包含连接和游标类。通过提供必要的连接凭据(例如服务器名称、端口号以及用户名和密码,如果适用)使用 connect() 方法获得连接对象。连接对象处理数据库的打开和关闭,以及进行事务控制机制(提交或回滚一个事务)。

从连接对象中获得的游标对象在执行所有 CRUD 操作的时候担任数据库的句柄。

The sqlite3 Module

SQLite 是一个无服务器的基于文件的轻量级事务关系数据库。它不需要任何安装,而且无需任何用户名或密码等凭据即可访问数据库。

Python 的 sqlite3 模块包含了适用于 SQLite 数据库的 DB-API 实现。它由 Gerhard Häring 所撰写。我们将学习如何使用 sqlite3 模块来实现 Python 数据库访问。

我们先从导入 sqlite3 并检查其版本开始。

>>> import sqlite3
>>> sqlite3.sqlite_version
'3.39.4'

The Connection Object

连接对象由 sqlite3 模块中的 connect() 函数设置。此函数的第一个参数是一个字符串,用于表示 SQLite 数据库文件的路径(相对或绝对)。该函数返回一个引用数据库的连接对象。

>>> conn=sqlite3.connect('testdb.sqlite3')
>>> type(conn)
<class 'sqlite3.Connection'>

连接类中定义了不同的方法。其中一个方法是 cursor() 方法,该方法返回一个游标对象,我们将在下一部分中了解它。事务控制是由连接对象的 commit() 和 rollback() 方法实现的。连接类具有重要的方法,可定义要在 SQL 查询中使用的自定义功能和聚合。

The Cursor Object

接下来,我们需要从连接对象获取游标对象。它是您在数据库上执行任何 CRUD 操作时对数据库的控制。连接对象的 cursor() 方法返回游标对象。

>>> cur=conn.cursor()
>>> type(cur)
<class 'sqlite3.Cursor'>

现在,我们可以借助于 cursor 对象中可用的 execute() 方法执行所有 SQL 查询操作。该方法需要一个字符串参数,该字符串必须是有效的 SQL 语句。

Creating a Database Table

现在,我们将 Employee 表添加到新创建的“testdb.sqlite3”数据库中。在以下脚本中,我们调用 cursor 对象的 execute() 方法,并向其提供一个包含 CREATE TABLE 语句的字符串。

import sqlite3
conn=sqlite3.connect('testdb.sqlite3')
cur=conn.cursor()
qry='''
CREATE TABLE Employee (
EmpID INTEGER PRIMARY KEY AUTOINCREMENT,
FIRST_NAME TEXT (20),
LAST_NAME TEXT(20),
AGE INTEGER,
SEX TEXT(1),
INCOME FLOAT
);
'''
try:
   cur.execute(qry)
   print ('Table created successfully')
except:
   print ('error in creating table')
conn.close()

当以上程序运行时,在当前工作目录中会创建一个包含 Employee 表的数据库。

我们可以通过在 SQLite 控制台列出该数据库中的表来进行验证。

sqlite> .open mydb.sqlite
sqlite> .tables
Employee

INSERT Operation

当您想将记录创建到数据库表中时,需要使用 INSERT 操作。

Example

以下示例执行 SQL INSERT 语句以在 EMPLOYEE 表中创建记录:

import sqlite3
conn=sqlite3.connect('testdb.sqlite3')
cur=conn.cursor()
qry="""INSERT INTO EMPLOYEE(FIRST_NAME,
   LAST_NAME, AGE, SEX, INCOME)
   VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""
try:
   cur.execute(qry)
   conn.commit()
   print ('Record inserted successfully')
except:
   conn.rollback()
print ('error in INSERT operation')
conn.close()

您还可以使用参数替换技术执行 INSERT 查询,如下所示:

import sqlite3
conn=sqlite3.connect('testdb.sqlite3')
cur=conn.cursor()
qry="""INSERT INTO EMPLOYEE(FIRST_NAME,
   LAST_NAME, AGE, SEX, INCOME)
   VALUES (?, ?, ?, ?, ?)"""
try:
   cur.execute(qry, ('Makrand', 'Mohan', 21, 'M', 5000))
   conn.commit()
   print ('Record inserted successfully')
except Exception as e:
   conn.rollback()
   print ('error in INSERT operation')
conn.close()

READ Operation

在任何数据库上进行 READ 操作意味着从数据库中获取一些有用的信息。

建立数据库连接后,便可针对此数据库进行查询。你可以使用 fetchone() 方法来获取单一记录,或使用 fetchall() 方法来获取数据库表格中的多个值。

  1. fetchone() − 从查询结果集中获取下一列。当使用光标对象对表格进行查询时,会返回结果集对象。

  2. fetchall() − 从结果集中获取所有列。如果已从结果集中提取一些列,它会从结果集中检索剩余的列。

  3. rowcount − 这是只读属性,并返回受 execute() 方法影响的列数。

Example

在以下代码中,光标对象执行 SELECT * FROM EMPLOYEE 查询。通过 fetchall() 方法获取结果集。我们以 for 循环打印出结果集中的所有记录。

import sqlite3
conn=sqlite3.connect('testdb.sqlite3')
cur=conn.cursor()
qry="SELECT * FROM EMPLOYEE"

try:
   # Execute the SQL command
   cur.execute(qry)
   # Fetch all the rows in a list of lists.
   results = cur.fetchall()
   for row in results:
      fname = row[1]
      lname = row[2]
      age = row[3]
      sex = row[4]
      income = row[5]
      # Now print fetched result
      print ("fname={},lname={},age={},sex={},income={}".format(fname, lname, age, sex, income ))
except Exception as e:
   print (e)
   print ("Error: unable to fecth data")

conn.close()

它将生成以下 output

fname=Mac,lname=Mohan,age=20,sex=M,income=2000.0
fname=Makrand,lname=Mohan,age=21,sex=M,income=5000.0

Update Operation

对任何数据库进行 UPDATE 操作表示更新数据库中已有的一个或多个记录。

以下过程更新了 income=2000 的所有记录。此处,我们将 income 增加 1000。

import sqlite3
conn=sqlite3.connect('testdb.sqlite3')
cur=conn.cursor()
qry="UPDATE EMPLOYEE SET INCOME = INCOME+1000 WHERE INCOME=?"

try:
   # Execute the SQL command
   cur.execute(qry, (1000,))
   # Fetch all the rows in a list of lists.
   conn.commit()
   print ("Records updated")
except Exception as e:
   print ("Error: unable to update data")
conn.close()

DELETE Operation

当你想从数据库中删除一些记录时,需要 DELETE 操作。以下过程用于删除 EMPLOYEE 中 INCOME 小于 2000 的所有记录。

import sqlite3
conn=sqlite3.connect('testdb.sqlite3')
cur=conn.cursor()
qry="DELETE FROM EMPLOYEE WHERE INCOME<?"

try:
   # Execute the SQL command
   cur.execute(qry, (2000,))
   # Fetch all the rows in a list of lists.
   conn.commit()
   print ("Records deleted")
except Exception as e:
   print ("Error: unable to delete data")

conn.close()

Performing Transactions

事务是一种确保数据一致性的机制。事务具有以下四个属性−

  1. Atomicity − 事务要么完成,要么根本不会发生。

  2. Consistency − 事务必须从一致的状态开始,并以一致的状态离开系统。

  3. Isolation − 事务的中间结果在当前事务外不可见。

  4. Durability − 一旦提交事务,其效果将持久,即使在系统故障后也是如此。

performing transactions

Python DB API 2.0 提供了两种方法来提交或回滚事务。

Example

你已经知道如何实现事务了。此处是一个类似的示例−

# Prepare SQL query to DELETE required records
sql = "DELETE FROM EMPLOYEE WHERE AGE > ?"
try:
   # Execute the SQL command
   cursor.execute(sql, (20,))
   # Commit your changes in the database
   db.commit()
except:
   # Rollback in case there is any error
   db.rollback()

COMMIT Operation

提交是一种操作,它向数据库发出执行更改的绿灯信号,在此操作后,任何更改都不能再撤销。

此处是调用 commit 方法的一个简单示例。

db.commit()

ROLLBACK Operation

如果你不满意其中的一个或多个更改,并且想要完全撤消那些更改,请使用 rollback() 方法。

此处是调用 rollback() 方法的一个简单示例。

db.rollback()

The PyMySQL Module

PyMySQL 是一个接口,用于从 Python 连接到 MySQL 数据库服务器。它实现了 Python 数据库 API v2.0 并包含一个纯 Python MySQL 客户端库。PyMySQL 的目标是成为 MySQLdb 的直接替代品。

Installing PyMySQL

在继续进行之前,请确保已在您的机器上安装了 PyMySQL。只需在您的 Python 脚本中输入以下内容并执行它 −

import PyMySQL

如果它产生了以下结果,则表示 MySQLdb 模块未安装 −

Traceback (most recent call last):
   File "test.py", line 3, in <module>
      Import PyMySQL
ImportError: No module named PyMySQL

最近的稳定版本在 PyPI 上可用,并可以使用 pip 安装 −

pip install PyMySQL

Note − 确保您具有安装上述模块的根权限。

MySQL Database Connection

在连接到 MySQL 数据库之前,请确保以下几点 −

  1. 您已经创建了一个 TESTDB 数据库。

  2. 您已经在 TESTDB 中创建了一个 EMPLOYEE 表。

  3. 此表具有 FIRST_NAME、LAST_NAME、AGE、SEX 和 INCOME 字段。

  4. 设置了用户 ID“testuser”和密码“test123”来访问 TESTDB。

  5. Python 模块 PyMySQL 已正确安装在您的机器上。

  6. 您已经学习了 MySQL 教程以了解 MySQL 基础知识。

Example

要在早期示例中使用 MySQL 数据库而不是 SQLite 数据库,我们需要将 connect() 函数更改为以下内容 −

import PyMySQL
# Open database connection
db = PyMySQL.connect("localhost","testuser","test123","TESTDB" )

除了此更改之外,每个数据库操作都可以轻松执行。

Handling Errors

有许多错误源。一些示例是执行的 SQL 语句中的语法错误、连接失败或为已取消或已完成的语句句柄调用 fetch 方法。

DB API 定义了一些错误,这些错误必须存在于每个数据库模块中。下表列出了这些异常。

Python - Weak References

在实现垃圾收集策略的时候,Python 使用引用计数机制。当在内存中引用一个对象时,计数会增加 1。相反,当移除该引用时,计数会减少 1。如果在后台运行的垃圾收集器找到一个计数为 0 的对象,它将会被移除,且它占用的内存将会被回收。

弱引用是一个不保护对象不受垃圾回收影响的引用。当你需要实现大型对象的缓存时,它非常重要,并且在你希望减少循环引用的痛苦的情况下也是如此。

为了创建弱引用,Python 为我们提供了名为 weakref 的模块。

这个模块中的 ref 类管理到一个对象的弱引用。当被调用时,它检索原始对象。

创建弱引用的方法:

weakref.ref(class())

Example

import weakref
class Myclass:
   def __del__(self):
      print('(Deleting {})'.format(self))
obj = Myclass()
r = weakref.ref(obj)

print('object:', obj)
print('reference:', r)
print('call r():', r())

print('deleting obj')
del obj
print('r():', r())

在删除引用之后调用引用对象将返回 None。

它将生成以下 output

object: <__main__.Myclass object at 0x00000209D7173290>
reference: <weakref at 0x00000209D7175940; to 'Myclass' at
0x00000209D7173290>
call r(): <__main__.Myclass object at 0x00000209D7173290>
deleting obj
(Deleting <__main__.Myclass object at 0x00000209D7173290>)
r(): None

The callback Function

ref 类的构造函数有一个可选的参数称为回调函数,它在引用的对象被删除时被调用。

import weakref
class Myclass:
   def __del__(self):
      print('(Deleting {})'.format(self))
def mycallback(rfr):
   """called when referenced object is deleted"""
   print('calling ({})'.format(rfr))
obj = Myclass()
r = weakref.ref(obj, mycallback)

print('object:', obj)
print('reference:', r)
print('call r():', r())

print('deleting obj')
del obj
print('r():', r())

它将生成以下 output

object: <__main__.Myclass object at 0x000002A0499D3590>
reference: <weakref at 0x000002A0499D59E0; to 'Myclass' at
0x000002A0499D3590>
call r(): <__main__.Myclass object at 0x000002A0499D3590>
deleting obj
(Deleting <__main__.Myclass object at 0x000002A0499D3590>)
calling (<weakref at 0x000002A0499D59E0; dead>)
r(): None

Finalizing Objects

weakref 模块提供了 finalize 类。当垃圾收集器收集对象的时候,调用它的对象。对象在引用对象被调用之前存在。

import weakref
class Myclass:
   def __del__(self):
      print('(Deleting {})'.format(self))

def finalizer(*args):
   print('Finalizer{!r})'.format(args))

obj = Myclass()
r = weakref.finalize(obj, finalizer, "Call to finalizer")

print('object:', obj)
print('reference:', r)
print('call r():', r())

print('deleting obj')
del obj
print('r():', r())

它将生成以下 output

object: <__main__.Myclass object at 0x0000021015103590>
reference: <finalize object at 0x21014eabe80; for 'Myclass' at
0x21015103590>
Finalizer('Call to finalizer',))
call r(): None
deleting obj
(Deleting <__main__.Myclass object at 0x0000021015103590>)
r(): None

Weakref 模块提供 WeakKeyDictionary 和 WeakValueDictionary 类。它们不会让对象在映射对象中看似存活。它们更适用于创建多个对象的缓存。

WeakKeyDictionary

引用键的弱映射类。当键不再有强引用时,字典中的条目将被丢弃。

WeakKeyDictionary 类的实例使用现有字典创建,也可以不使用任何参数创建它的功能与普通字典相同,可以向其中添加和删除映射条目。

在下面给出的代码中,创建了三个 Person 实例。然后使用字典创建 WeakKeyDictionary 实例,其中键是 Person 实例,而值是 Person 的名称。

我们调用 keyrefs() 方法来检索弱引用。当对 Person1 的引用被删除时,字典键将再次被打印。将新 Person 实例添加到具有弱引用键的字典中。最后,我们再次打印字典的键。

Example

import weakref

class Person:
   def __init__(self, person_id, name, age):
      self.emp_id = person_id
      self.name = name
      self.age = age

   def __repr__(self):
      return "{} : {} : {}".format(self.person_id, self.name, self.age)
Person1 = Person(101, "Jeevan", 30)
Person2 = Person(102, "Ramanna", 35)
Person3 = Person(103, "Simran", 28)
weak_dict = weakref.WeakKeyDictionary({Person1: Person1.name, Person2: Person2.name, Person3: Person3.name})
print("Weak Key Dictionary : {}\n".format(weak_dict.data))
print("Dictionary Keys : {}\n".format([key().name for key in weak_dict.keyrefs()]))
del Person1
print("Dictionary Keys : {}\n".format([key().name for key in weak_dict.keyrefs()]))
Person4 = Person(104, "Partho", 32)
weak_dict.update({Person4: Person4.name})

print("Dictionary Keys : {}\n".format([key().name for key in weak_dict.keyrefs()]))

它将生成以下 output

Weak Key Dictionary : {<weakref at 0x7f542b6d4180; to 'Person' at 0x7f542b8bbfd0>: 'Jeevan', <weakref at 0x7f542b6d5530; to 'Person' at 0x7f542b8bbeb0>: 'Ramanna', <weakref at 0x7f542b6d55d0; to 'Person' at 0x7f542b8bb7c0>: 'Simran'}

Dictionary Keys : ['Jeevan', 'Ramanna', 'Simran']

Dictionary Keys : ['Ramanna', 'Simran']

Dictionary Keys : ['Ramanna', 'Simran', 'Partho']

WeakValueDictionary

引用值的弱映射类。当不再有对值的强引用时,字典中的条目将被丢弃。

我们将演示如何使用 WeakValueDictionary 创建具有弱引用值的字典。

代码与前一个示例类似,但这次我们使用 Person 名称作为键,使用 Person 实例作为值。我们使用 valuerefs() 方法来检索字典的弱引用值。

Example

import weakref

class Person:
   def __init__(self, person_id, name, age):
      self.emp_id = person_id
      self.name = name
      self.age = age

   def __repr__(self):
      return "{} : {} : {}".format(self.person_id, self.name, self.age)

Person1 = Person(101, "Jeevan", 30)
Person2 = Person(102, "Ramanna", 35)
Person3 = Person(103, "Simran", 28)

weak_dict = weakref.WeakValueDictionary({Person1.name:Person1, Person2.name:Person2, Person3.name:Person3})
print("Weak Value Dictionary : {}\n".format(weak_dict.data))
print("Dictionary Values : {}\n".format([value().name for value in weak_dict.valuerefs()]))
del Person1
print("Dictionary Values : {}\n".format([value().name for value in weak_dict.valuerefs()]))
Person4 = Person(104, "Partho", 32)
weak_dict.update({Person4.name: Person4})
print("Dictionary Values : {}\n".format([value().name for value in weak_dict.valuerefs()]))

它将生成以下 output

Weak Value Dictionary : {'Jeevan': <weakref at 0x7f3af9fe4180; to 'Person' at 0x7f3afa1c7fd0>, 'Ramanna': <weakref at 0x7f3af9fe5530; to 'Person' at 0x7f3afa1c7eb0>, 'Simran': <weakref at 0x7f3af9fe55d0; to 'Person' at 0x7f3afa1c77c0>}

Dictionary Values : ['Jeevan', 'Ramanna', 'Simran']

Dictionary Values : ['Ramanna', 'Simran']

Dictionary Values : ['Ramanna', 'Simran', 'Partho']

Python - Serialization

术语“对象序列化”是指将对象状态转换为字节流的过程。一旦创建,此字节流可以进一步存储在文件中或通过套接字等传输。另一方面,从字节流重建对象称为反序列化。

Python 的序列化和反序列化术语分别称为腌制和取消腌制。Python 标准库中提供的 pickle 模块提供了用于序列化(dump() 和 dumps())和反序列化(load() 和 loads())的函数。

pickle 模块使用非常特定于 Python 的数据格式。因此,不是用 Python 编写的程序可能无法正确反序列化编码(腌制)的数据。同样,从未经身份验证的来源取消腌制数据也不被认为是安全的。

Pickle Protocols

协议是在 Python 对象与二进制数据之间相互转换中使用的约定。目前 pickle 模块定义了以下 5 种不同的协议:

要了解 Python 安装的最高和默认协议版本,请使用 pickle 模块中定义的以下常量:

>>> import pickle
>>> pickle.HIGHEST_PROTOCOL
4
>>> pickle.DEFAULT_PROTOCOL
3

pickle 模块的 dump() 和 load() 函数执行 Python 数据的腌制和取消腌制。dump() 函数将腌制对象写入文件,load() 函数从文件将数据取消腌制到 Python 对象。

dump() and load()

以下程序将字典对象腌制到二进制文件中。

import pickle
f=open("data.txt","wb")
dct={"name":"Ravi", "age":23, "Gender":"M","marks":75}
pickle.dump(dct,f)
f.close()

执行以上代码时,字典对象的字节表示将存储在 data.txt 文件中。

要将二进制文件中的数据取消腌制或反序列化回字典,请运行以下程序。

import pickle
f=open("data.txt","rb")
d=pickle.load(f)
print (d)
f.close()

Python 控制台显示从文件中读取的字典对象。

{'age': 23, 'Gender': 'M', 'name': 'Ravi', 'marks': 75}

dumps() and loads()

pickle 模块还包含 dumps() 函数,该函数返回腌制数据的字符串表示。

>>> from pickle import dump
>>> dct={"name":"Ravi", "age":23, "Gender":"M","marks":75}
>>> dctstring=dumps(dct)
>>> dctstring
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00Raviq\x02X\x03\x00\x00\x00ageq\x03K\x17X\x06\x00\x00\x00Genderq\x04X\x01\x00\x00\x00Mq\x05X\x05\x00\x00\x00marksq\x06KKu.'

使用 loads() 函数解腌制字符串以获取原始字典对象。

from pickle import load
dct=loads(dctstring)
print (dct)

它将生成以下 output

{'name': 'Ravi', 'age': 23, 'Gender': 'M', 'marks': 75}

Pickler Class

pickle 模块还定义了 Pickler 类和 Unpickler 类。Pickler 类将腌制数据写入文件。Unpickler 类从文件读取二进制数据并构建 Python 对象。

要写入 Python 对象的腌制数据 -

from pickle import pickler
f=open("data.txt","wb")
dct={'name': 'Ravi', 'age': 23, 'Gender': 'M', 'marks': 75}
Pickler(f).dump(dct)
f.close()

Unpickler Class

通过解腌制二进制文件读取数据 -

from pickle import Unpickler
f=open("data.txt","rb")
dct=Unpickler(f).load()
print (dct)
f.close()

所有 Python 标准数据类型的对象都是可腌制的。此外,自定义类的对象也可以被腌制和解腌。

from pickle import *
class person:
   def __init__(self):
      self.name="XYZ"
      self.age=22
   def show(self):
      print ("name:", self.name, "age:", self.age)
p1=person()
f=open("data.txt","wb")
dump(p1,f)
f.close()
print ("unpickled")
f=open("data.txt","rb")
p1=load(f)
p1.show()

Python 库还具有 marshal 模块,用于内部序列化 Python 对象。

Python - Templating

Python 提供了不同的文本格式化功能。其中包括格式化运算符、Python 的 format() 函数和 f 字符串。此外,Python 的标准库包含带更多格式化选项的字符串模块。

字符串模块中的 Template 类通过 PEP 292 中描述的替换技术动态形成字符串对象。与 Python 中其他内置字符串格式化设施相比,其简单的语法和功能使其在内部翻译中更容易。

Template 字符串使用 $ 符号进行替换。该符号之后紧跟着一个标识符,该标识符遵循形成有效 Python 标识符的规则。

Syntax

from string import Template

tempStr = Template('Hello $name')

Template 类定义了以下方法 -

substitute()

此方法执行 Template 对象中标识符的值替换。使用关键字参数或字典对象可以用来映射模板中的标识符。该方法返回一个新的字符串。

Example 1

以下代码为 substitute() 方法使用关键字参数。

from string import Template

tempStr = Template('Hello. My name is $name and my age is $age')
newStr = tempStr.substitute(name = 'Pushpa', age = 26)
print (newStr)

它将生成以下 output

Hello. My name is Pushpa and my age is 26

Example 2

在以下示例中,我们使用字典对象来映射模板字符串中的替换标识符。

from string import Template

tempStr = Template('Hello. My name is $name and my age is $age')
dct = {'name' : 'Pushpalata', 'age' : 25}
newStr = tempStr.substitute(dct)
print (newStr)

它将生成以下 output

Hello. My name is Pushpalata and my age is 25

Example 3

如果 substitute() 方法没有提供足够的参数与模板字符串中的标识符匹配,Python 会引发 KeyError。

from string import

tempStr = Template('Hello. My name is $name and my age is $age')
dct = {'name' : 'Pushpalata'}
newStr = tempStr.substitute(dct)
print (newStr)

它将生成以下 output

Traceback (most recent call last):
File "C:\Users\user\example.py", line 5, in
newStr = tempStr.substitute(dct)
^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python311\Lib\string.py", line 121, in substitute
return self.pattern.sub(convert, self.template)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python311\Lib\string.py", line 114, in convert
return str(mapping[named])
~~~~~~~^^^^^^^
KeyError: 'age'

safe_substitute()

此方法的行为与 substitute() 方法类似,但它不会在键不足或不匹配时引发错误。相反,原始占位符将完整地显示在结果字符串中。

Example 4

from string import Template
tempStr = Template('Hello. My name is $name and my age is $age')
dct = {'name' : 'Pushpalata'}
newStr = tempStr.safe_substitute(dct)
print (newStr)

它将生成以下 output

Hello. My name is Pushpalata and my age is $age

is_valid()

如果模板具有会导致 substitute() 引发 ValueError 的无效占位符,则返回 false。

get_identifiers()

返回模板中有效标识符的列表,按它们首次出现的顺序,忽略任何无效标识符。

Example 5

from string import Template

tempStr = Template('Hello. My name is $name and my age is $23')
print (tempStr.is_valid())
tempStr = Template('Hello. My name is $name and my age is $age')
print (tempStr.get_identifiers())

它将生成以下 output

False

['name', 'age']

Example 6

“$”符号已被定义为替换字符。如果你需要 $ 实际出现在字符串中,则必须对其进行转义。换句话说,使用 $$ 在字符串中使用它。

from string import Template

tempStr = Template('The symbol for Dollar is $$')
print (tempStr.substitute())

它将生成以下 output

The symbol for Dollar is $

Example 7

如果你希望使用其他字符而不是 “$” 作为替换符号,请声明 Template 类的一个子类并分配 -

from string import Template

class myTemplate(Template):
   delimiter = '#'

tempStr = myTemplate('Hello. My name is #name and my age is #age')
print (tempStr.substitute(name='Harsha', age=30))

Python - Output Formatting

本章将讨论用于设置输出格式的不同技术。

String Formatting Operator

Python 最酷的一个特性是字符串格式运算符 %。该运算符对字符串而言是唯一的,弥补了缺少 C 语言 printf() 系列函数的问题。C 语言中使用的格式说明符号 (%d %c %f %s 等) 被用作字符串中的占位符。

以下是一个简单的示例:

print ("My name is %s and weight is %d kg!" % ('Zara', 21))

它将生成以下 output

My name is Zara and weight is 21 kg!

The format() Method

Python 3.0,为 str 类引入了 format() 方法,更加高效地处理复杂的字符串格式设置。此后,该方法已移植到 Python 2.6 和 Python 2.7。

此内置字符串类的方法提供了执行复杂变量替换和值格式设置的能力。此新的格式设置技术被视为更为优雅。

Syntax

format() 方法的一般语法如下:

str.format(var1, var2,...)

Return Value

该方法返回一个格式化字符串。

该字符串本身包含占位符 {},其中依次插入变量的值。

Example

name="Rajesh"
age=23
print ("my name is {} and my age is {} years".format(name, age))

它将生成以下 output

my name is Rajesh and my age is 23 years

可以将变量用作 format() 方法的关键字参数,并将变量名用作字符串中的占位符。

print ("my name is {name} and my age is {age}
years".format(name="Rajesh", age=23))

还可以指定 C 样式格式化符号。唯一的变化是用 : 代替 %。例如,使用 {:s} 代替 %s,使用 (:d} 代替 %d

name="Rajesh"
age=23
print ("my name is {:s} and my age is {:d} years".format(name, age))

f-strings

在 Python 中,f 字符串或文字字符串内插是另一种格式设置功能。使用此格式设置方法,可以在字符串常量中使用内嵌的 Python 表达式。Python f 字符串速度更快、可读性更强、更简洁且错误更少。

该字符串以前缀“f”开头,其中插入了一个或多个占位符,其值会动态填充。

name = 'Rajesh'
age = 23

fstring = f'My name is {name} and I am {age} years old'
print (fstring)

它将生成以下 output

My name is Rajesh and I am 23 years old

Template Strings

string 模块中的 Template 类提供了一种格式设置字符串的替代方法。Template 类的优势之一是能够自定义格式设置规则。

有效的模板字符串或占位符包含两部分:$ 符号,后跟有效的 Python 标识符。

需要创建一个 Template 类的对象,并将模板字符串作为参数传递给构造函数。

接下来,调用 Template 类的 substitute() 方法。它会将作为参数提供的放入模板字符串中。

Example

from string import Template

temp_str = "My name is $name and I am $age years old"
tempobj = Template(temp_str)
ret = tempobj.substitute(name='Rajesh', age=23)
print (ret)

它将生成以下 output

My name is Rajesh and I am 23 years old

The textwrap Module

Python 的 textwrap 模块中的 wrap 类包含通过调整输入段落中的换行来设置和包装纯文本的功能。它有助于使文本格式正确且美观。

textwrap 模块具有以下便捷功能:

textwrap.wrap(text, width=70)

将文本(字符串)中的单个段落包装起来,使得每一行的长度最多为 width 个字符。返回输出行列表,没有最终换行符。可选关键字参数对应于 TextWrapper 的实例属性。width 默认为 70。

textwrap.fill(text, width=70)

将文本包装成单个段落,并返回包含已包装段落的单个字符串。

这两种方法都在内部创建 TextWrapper 类的对象并对其调用单个方法。由于实例未被重用,因此你创建自己的 TextWrapper 对象将更有效率。

Example

import textwrap

text = '''
Python is a high-level, general-purpose programming language. Its design philosophy emphasizes code readability with the use of significant indentation via the off-side rule.

Python is dynamically typed and garbage-collected. It supports multiple programming paradigms, including structured (particularly procedural), object-oriented and functional programming. It is often described as a "batteries included" language due to its comprehensive standard library.
'''

wrapper = textwrap.TextWrapper(width=40)
wrapped = wrapper.wrap(text = text)

# Print output
for element in wrapped:
   print(element)

它将生成以下 output

Python is a high-level, general-purpose
programming language. Its design
philosophy emphasizes code readability
with the use of significant indentation
via the off-side rule. Python is
dynamically typed and garbage-collected.
It supports multiple programming
paradigms, including structured
(particularly procedural), objectoriented and functional programming. It
is often described as a "batteries
included" language due to its
comprehensive standard library.

下列属性针对 TextWrapper 对象进行定义 −

  1. width − (默认: 70) 已包装行的最大长度。

  2. expand_tabs − (默认: True) 如果为 true,则文本中的所有制表符都将使用文本的 expandtabs() 方法展开为空格。

  3. tabsize − (默认: 8) 如果 expand_tabs 为 true,则文本中的所有制表符都将根据当前列和给定的制表符大小展开为零个或多个空格。

  4. replace_whitespace − (默认: True) 如果为 true,则在制表符展开后但在包装前,wrap() 方法将用一个空格替换每个空白字符。

  5. drop_whitespace − (默认: True) 如果为 true,则每行开始和结束处的空白字符(包装后但在缩进前)都会被去掉。然而,如果段落开始处后的字符不是空白,则段落开始处的空白字符不会被去掉。如果被去掉的空白字符占据了整行,则整行将被去掉。

  6. initial_indent − (默认: '') 将被添加至已包装输出的第一行的开头处的字符串。

  7. subsequent_indent − (默认: '') 将被添加至已包装输出的所有行(第一行除外)的开头处的字符串。

  8. fix_sentence_endings − (默认: False) 如果为 true,则 TextWrapper 尝试检测句子结尾并确保句子始终用正好两个空格分隔。对于使用等宽字体显示的文本,此属性通常是必需的。

  9. break_long_words − (默认: True) 如果为 true,则长于 width 的单词将被折行以确保任何行都不长于 width。如果为 false,则不会折行长单词,而且一些行可能长于 width。

  10. break_on_hyphens − (默认: True) 如果为 true,则包装将优选在复合词中的空格和连字符后进行,这符合英语的习惯。如果为 false,则仅空格将被视为潜在的良好的换行位置。

The shorten() Function

折起并截断给定的文本以满足给定的 width。首先折起文本的空白字符。如果文本此时满足 width ,则按原样返回文本。否则,尽可能多地加入单词,然后添加占位符 −

Example

import textwrap

python_desc = """Python is a general-purpose interpreted, interactive, object-oriented, and high-level programming language. It was created by Guido van Rossum during 1985- 1990. Like Perl, Python source code is also available under the GNU General Public License (GPL). This tutorial gives enough understanding on Python programming language."""

my_wrap = textwrap.TextWrapper(width = 40)

short_text = textwrap.shorten(text = python_desc, width=150)
print('\n\n' + my_wrap.fill(text = short_text))

它将生成以下 output

Python is a general-purpose interpreted,
interactive, object-oriented,and high
level programming language. It was
created by Guido van Rossum [...]

The pprint Module

Python 标准库中的 pprint 模块具有美观地展现 Python 数据结构的功能。pprint 的名称代表漂亮的打印机。可以被 Python 解释器正确解析的任何数据结构都将被优雅地格式化。

已格式化的表达式将尽可能地保存在一行中,但如果长度超出了格式化的 width 参数,则会拆分为多行。pprint 输出的一个独特功能是,在格式化显示表示形式之前,会自动对字典进行排序。

PrettyPrinter Class

pprint 模块包含 PrettyPrinter 类的定义。其构造函数采用以下格式 −

Syntax

pprint.PrettyPrinter(indent, width, depth, stream, compact)

Parameters

  1. indent − 为每个递归级别添加的缩进。默认值为 1。

  2. width − 默认值为 80。所需的输出受到此值限制。如果长度大于 width,则会拆分为多行。

  3. depth − 控制要打印级别的数量。

  4. stream − 默认为 std.out − 默认输出设备。它可以采用任何流对象,如文件。

  5. compact − id 默认为 False。如果为 true,则只显示可在宽度内调整的数据。

PrettyPrinter 类定义了以下方法−

pprint() method

打印 PrettyPrinter 对象的格式化表示。

pformat() method

根据构造函数的参数,返回对象的格式化表示。

Example

以下示例演示了 PrettyPrinter 类的一个简单用法 −

import pprint
students={"Dilip":["English", "Maths", "Science"],"Raju":{"English":50,"Maths":60, "Science":70},"Kalpana":(50,60,70)}
pp=pprint.PrettyPrinter()
print ("normal print output")
print (students)
print ("----")
print ("pprint output")
pp.pprint(students)

输出显示了正常打印和美观打印显示 −

normal print output
{'Dilip': ['English', 'Maths', 'Science'], 'Raju': {'English': 50, 'Maths': 60, 'Science': 70}, 'Kalpana': (50, 60, 70)}

pprint 输出{'Dilip': ['英语', '数学', '科学'], 'Kalpana': (50, 60, 70), 'Raju': {'英语': 50, '数学': 60, '科学': 70}}

The *pprint* module also defines convenience functions pprint() and pformat() corresponding to PrettyPrinter methods. The example below uses pprint() function.

[source, python]

from pprint import pprintstudents={"Dilip":["英语", "数学", "科学"], "Raju":{"英语":50,"数学":60, "科学":70}, "Kalpana":(50,60,70)}print ("普通打印输出")print (students)print ("----")print ("pprint 输出")pprint (students)

==== Example

The next example uses pformat() method as well as pformat() function. To use pformat() method, PrettyPrinter object is first set up. In both cases, the formatted representation is displayed using normal print() function.

[source, python]

import pprintstudents={"Dilip":["英语", "数学", "科学"], "Raju":{"英语":50,"数学":60, "科学":70}, "Kalpana":(50,60,70)}print ("使用 pformat 方法")pp=pprint.PrettyPrinter()string=pp.pformat(students)print (string)print ('------')print ("使用 pformat 函数")string=pprint.pformat(students)print (string)

Here is the output of the above code −

[source, python]

使用 pformat 方法{'Dilip': ['英语', '数学', '科学'], 'Kalpana': (50, 60, 70), 'Raju': {'英语': 50, '数学': 60, '科学': 70}}

using pformat function
{'Dilip': ['English', 'Maths', 'Science'],
 'Kalpana': (50, 60, 70),
 'Raju': {'English': 50, 'Maths': 60, 'Science': 70}}

Pretty printer can also be used with custom classes. Inside the class repr() method is overridden. The repr() method is called when repr() function is used. It is the official string representation of Python object. When we use object as parameter to print() function it prints return value of repr() function.

Example

In this example, the repr() method returns the string representation of player object −

import pprint
class player:
   def __init__(self, name, formats=[], runs=[]):
      self.name=name
      self.formats=formats
      self.runs=runs
   def __repr__(self):
      dct={}
      dct[self.name]=dict(zip(self.formats,self.runs))
      return (repr(dct))

l1=['Tests','ODI','T20']
l2=[[140, 45, 39],[15,122,36,67, 100, 49],[78,44, 12, 0, 23, 75]]
p1=player("virat",l1,l2)
pp=pprint.PrettyPrinter()
pp.pprint(p1)

The output of above code is −

{'virat': {'Tests': [140, 45, 39], 'ODI': [15, 122, 36, 67, 100, 49],
'T20': [78, 44, 12, 0, 23, 75]}}

Python - Performance Measurement

A given problem may be solved by more than one alternative algorithms. Hence, we need to optimize the performance of the solution. Python’s timeit module is a useful tool to measure the performance of a Python application.

The timit() function in this module measures execution time of your Python code.

Syntax

timeit.timeit(stmt, setup, timer, number)

Parameters

  1. stmt − code snippet for measurement of performance.

  2. setup − setup details arguments to be passed or variables.

  3. timer − uses default timer, so, it may be skipped.

  4. number − the code will be executed this number of times. The default is 1000000.

Example

The following statement uses list comprehension to return a list of multiple of 2 for each number in the range upto 100.

>>> [n*2 for n in range(100)]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34,
36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68,
70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100,
102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152,
154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178,
180, 182, 184, 186, 188, 190, 192, 194, 196, 198]

To measure the execution time of the above statement, we use the timeit() function as follows −

>>> from timeit import timeit
>>> timeit('[n*2 for n in range(100)]', number=10000)
0.0862189000035869

Compare the execution time with the process of appending the numbers using a for loop.

>>> string = '''
... numbers=[]
... for n in range(100):
... numbers.append(n*2)
... '''
>>> timeit(string, number=10000)
0.1010853999905521

The result shows that list comprehension is more efficient.

The statement string can contain a Python function to which one or more arguments My be passed as setup code.

We shall find and compare the execution time of a factorial function using a loop with that of its recursive version.

The normal function using for loop is −

def fact(x):
   fact = 1
   for i in range(1, x+1):
      fact*=i
   return fact

Definition of recursive factorial.

def rfact(x):
   if x==1:
      return 1
   else:
      return x*fact(x-1)

Test these functions to calculate factorial of 10.

print ("Using loop:",fact(10))
print ("Using Recursion",rfact(10))
Result
Using loop: 3628800
Using Recursion 3628800

Now we shall find their respective execution time with timeit() function.

import timeit

setup1="""
from __main__ import fact
x = 10
"""

setup2="""
from __main__ import rfact
x = 10
"""

print ("Performance of factorial function with loop")
print(timeit.timeit(stmt = "fact(x)", setup=setup1, number=10000))

print ("Performance of factorial function with Recursion")
print(timeit.timeit(stmt = "rfact(x)", setup=setup2, number=10000))

Output

Performance of factorial function with loop
0.00330029999895487
Performance of factorial function with Recursion
0.006506800003990065

The recursive function is slower than the function with loop.

In this way, we can perform performance measurement of Python code.

Python - Data Compression

Python’s standard library has a rich collection of modules for data compression and archiving. One can select whichever is suitable for his job.

There are following modules related to data compression −

Python - CGI Programming

The Common Gateway Interface, or CGI, is a set of standards that define how information is exchanged between the web server and a custom script. The CGI specs are currently maintained by the NCSA.

What is CGI?

  1. The Common Gateway Interface, or CGI, is a standard for external gateway programs to interface with information servers such as HTTP servers.

  2. The current version is CGI/1.1 and CGI/1.2 is under progress.

Web Browsing

To understand the concept of CGI, let us see what happens when we click a hyper link to browse a particular web page or URL.

  1. Your browser contacts the HTTP web server and demands for the URL, i.e., filename.

  2. Web Server parses the URL and looks for the filename. If it finds that file then sends it back to the browser, otherwise sends an error message indicating that you requested a wrong file.

  3. Web browser takes response from web server and displays either the received file or error message.

However, it is possible to set up the HTTP server so that whenever a file in a certain directory is requested that file is not sent back; instead it is executed as a program, and whatever that program outputs is sent back for your browser to display. This function is called the Common Gateway Interface or CGI and the programs are called CGI scripts. These CGI programs can be a Python Script, PERL Script, Shell Script, C or C++ program, etc.

CGI Architecture Diagram

Cgi Architecture Diagram

Web Server Support and Configuration

Before you proceed with CGI Programming, make sure that your Web Server supports CGI and it is configured to handle CGI Programs. All the CGI Programs to be executed by the HTTP server are kept in a pre-configured directory. This directory is called CGI Directory and by convention it is named as /var/www/cgi-bin. By convention, CGI files have extension as. cgi, but you can keep your files with python extension .py as well.

By default, the Linux server is configured to run only the scripts in the cgi-bin directory in /var/www. If you want to specify any other directory to run your CGI scripts, comment the following lines in the httpd.conf file −

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options ExecCGI
   Order allow,deny
   Allow from all
</Directory>

<Directory "/var/www/cgi-bin">
Options All
</Directory>

The following line should also be added for apache server to treat .py file as cgi script.

AddHandler cgi-script .py

Here, we assume that you have Web Server up and running successfully and you are able to run any other CGI program like Perl or Shell, etc.

First CGI Program

Here is a simple link, which is linked to a CGI script called hello.py. This file is kept in /var/www/cgi-bin directory and it has following content. Before running your CGI program, make sure you have change mode of file using chmod 755 hello.py UNIX command to make file executable.

print ("Content-type:text/html\r\n\r\n")
print ('<html>')
print ('<head>')
print ('<title>Hello Word - First CGI Program</title>')
print ('</head>')
print ('<body>')
print ('<h2>Hello Word! This is my first CGI program</h2>')
print ('</body>')
print ('</html>')

Note − First line in the script must be the path to Python executable. It appears as a comment in Python program, but it is called shebang line.

In Linux, it should be #!/usr/bin/python3.

In Windows, it should be #!c:/python311/python.exd.

Enter the following URL in your browser −

http://localhost/cgi-bin/hello.py
Hello Word! This is my first CGI program

This hello.py script is a simple Python script, which writes its output on STDOUT file, i.e., screen. There is one important and extra feature available which is first line to be printed Content-type:text/html\r\n\r\n. This line is sent back to the browser and it specifies the content type to be displayed on the browser screen.

By now you must have understood basic concept of CGI and you can write many complicated CGI programs using Python. This script can interact with any other external system also to exchange information such as RDBMS.

HTTP Header

The line Content-type:text/html\r\n\r\n is part of HTTP header which is sent to the browser to understand the content. All the HTTP header will be in the following form −

HTTP Field Name: Field Content

For Example
Content-type: text/html\r\n\r\n

There are few other important HTTP headers, which you will use frequently in your CGI Programming.

CGI Environment Variables

All the CGI programs have access to the following environment variables. These variables play an important role while writing any CGI program.

Here is small CGI program to list out all the CGI variables. Click this link to see the result Get Environment

import os

print ("Content-type: text/html\r\n\r\n");
print ("<font size=+1>Environment</font><\br>");
for param in os.environ.keys():
   print ("<b>%20s</b>: %s<\br>" % (param, os.environ[param]))

GET and POST Methods

You must have come across many situations when you need to pass some information from your browser to web server and ultimately to your CGI Program. Most frequently, browser uses two methods two pass this information to web server. These methods are GET Method and POST Method.

Passing Information using GET method

The GET method sends the encoded user information appended to the page request. The page and the encoded information are separated by the ? character as follows −

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
  1. The GET method is the default method to pass information from the browser to the web server and it produces a long string that appears in your browser’s Location:box.

  2. Never use GET method if you have password or other sensitive information to pass to the server.

  3. The GET method has size limtation: only 1024 characters can be sent in a request string.

  4. The GET method sends information using QUERY_STRING header and will be accessible in your CGI Program through QUERY_STRING environment variable.

You can pass information by simply concatenating key and value pairs along with any URL or you can use HTML <FORM> tags to pass information using GET method.

Simple URL Example:Get Method

Here is a simple URL, which passes two values to hello_get.py program using GET method.

/cgi-bin/hello_get.py?first_name=Malhar&last_name=Lathkar

Given below is the hello_get.py script to handle the input given by web browser. We are going to use the cgi module, which makes it very easy to access the passed information −

# Import modules for CGI handling
import cgi, cgitb

# Create instance of FieldStorage
form = cgi.FieldStorage()

# Get data from fields
first_name = form.getvalue('first_name')
last_name = form.getvalue('last_name')

print ("Content-type:text/html")
print()
print ("<html>")
print ('<head>')
print ("<title>Hello - Second CGI Program</title>")
print ('</head>')
print ('<body>')
print ("<h2>Hello %s %s</h2>" % (first_name, last_name))
print ('</body>')
print ('</html>')

This would generate the following result −

Hello Malhar Lathkar

Simple FORM Example:GET Method

This example passes two values using HTML FORM and submit button. We use same CGI script hello_get.py to handle this input.

<form action = "/cgi-bin/hello_get.py" method = "get">
   First Name: <input type = "text" name = "first_name">  <br />

   Last Name: <input type = "text" name = "last_name" />
   <input type = "submit" value = "Submit" />
</form>

Here is the actual output of the above form, you enter First and Last Name and then click submit button to see the result.

Passing Information Using POST Method

A generally more reliable method of passing information to a CGI program is the POST method. This packages the information in exactly the same way as GET methods, but instead of sending it as a text string after a ? in the URL it sends it as a separate message. This message comes into the CGI script in the form of the standard input.

Below is same hello_get.py script which handles GET as well as POST method.

# Import modules for CGI handling
import cgi, cgitb

# Create instance of FieldStorage
form = cgi.FieldStorage()

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Hello - Second CGI Program</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"

Let us take again same example as above which passes two values using HTML FORM and submit button. We use same CGI script hello_get.py to handle this input.

<form action = "/cgi-bin/hello_get.py" method = "post">
First Name: <input type = "text" name = "first_name"><br />
Last Name: <input type = "text" name = "last_name" />

<input type = "submit" value = "Submit" />
</form>

Here is the actual output of the above form. You enter First and Last Name and then click submit button to see the result.

Passing Checkbox Data to CGI Program

Checkboxes are used when more than one option is required to be selected.

Here is example HTML code for a form with two checkboxes −

<form action = "/cgi-bin/checkbox.cgi" method = "POST" target = "_blank">
   <input type = "checkbox" name = "maths" value = "on" /> Maths
   <input type = "checkbox" name = "physics" value = "on" /> Physics
   <input type = "submit" value = "Select Subject" />
</form>

The result of this code is the following form −

Below is checkbox.cgi script to handle input given by web browser for checkbox button.

# Import modules for CGI handling
import cgi, cgitb

# Create instance of FieldStorage
form = cgi.FieldStorage()

# Get data from fields
if form.getvalue('maths'):
   math_flag = "ON"
else:
   math_flag = "OFF"

if form.getvalue('physics'):
   physics_flag = "ON"
else:
   physics_flag = "OFF"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Checkbox - Third CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> CheckBox Maths is : %s</h2>" % math_flag
print "<h2> CheckBox Physics is : %s</h2>" % physics_flag
print "</body>"
print "</html>"

Passing Radio Button Data to CGI Program

Radio Buttons are used when only one option is required to be selected.

Here is example HTML code for a form with two radio buttons −

<form action = "/cgi-bin/radiobutton.py" method = "post" target = "_blank">
   <input type = "radio" name = "subject" value = "maths" /> Maths
   <input type = "radio" name = "subject" value = "physics" /> Physics
   <input type = "submit" value = "Select Subject" />
</form>

The result of this code is the following form −

Below is radiobutton.py script to handle input given by web browser for radio button −

# Import modules for CGI handling
import cgi, cgitb

# Create instance of FieldStorage
form = cgi.FieldStorage()

# Get data from fields
if form.getvalue('subject'):
   subject = form.getvalue('subject')
else:
   subject = "Not set"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Radio - Fourth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

Passing Text Area Data to CGI Program

TEXTAREA element is used when multiline text has to be passed to the CGI Program.

Here is example HTML code for a form with a TEXTAREA box −

<form action = "/cgi-bin/textarea.py" method = "post" target = "_blank">
   <textarea name = "textcontent" cols = "40" rows = "4">
      Type your text here...
   </textarea>
   <input type = "submit" value = "Submit" />
</form>

The result of this code is the following form −

Below is textarea.cgi script to handle input given by web browser −

# Import modules for CGI handling
import cgi, cgitb

# Create instance of FieldStorage
form = cgi.FieldStorage()

# Get data from fields
if form.getvalue('textcontent'):
   text_content = form.getvalue('textcontent')
else:
   text_content = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>";
print "<title>Text Area - Fifth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Entered Text Content is %s</h2>" % text_content
print "</body>"

Passing Drop Down Box Data to CGI Program

Drop Down Box is used when we have many options available but only one or two will be selected.

Here is example HTML code for a form with one drop down box −

<form action = "/cgi-bin/dropdown.py" method = "post" target = "_blank">
   <select name = "dropdown">
      <option value = "Maths" selected>Maths</option>
      <option value = "Physics">Physics</option>
   </select>
   <input type = "submit" value = "Submit"/>
</form>

The result of this code is the following form −

Below is dropdown.py script to handle input given by web browser.

# Import modules for CGI handling
import cgi, cgitb

# Create instance of FieldStorage
form = cgi.FieldStorage()

# Get data from fields
if form.getvalue('dropdown'):
   subject = form.getvalue('dropdown')
else:
   subject = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Dropdown Box - Sixth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

Using Cookies in CGI

HTTP protocol is a stateless protocol. For a commercial website, it is required to maintain session information among different pages. For example, one user registration ends after completing many pages. How to maintain user’s session information across all the web pages?

In many situations, using cookies is the most efficient method of remembering and tracking preferences, purchases, commissions, and other information required for better visitor experience or site statistics.

How It Works?

Your server sends some data to the visitor’s browser in the form of a cookie. The browser may accept the cookie. If it does, it is stored as a plain text record on the visitor’s hard drive. Now, when the visitor arrives at another page on your site, the cookie is available for retrieval. Once retrieved, your server knows/remembers what was stored.

Cookies are a plain text data record of 5 variable-length fields −

  1. Expires − The date the cookie will expire. If this is blank, the cookie will expire when the visitor quits the browser.

  2. Domain − The domain name of your site.

  3. Path − The path to the directory or web page that sets the cookie. This may be blank if you want to retrieve the cookie from any directory or page.

  4. Secure − If this field contains the word "secure", then the cookie may only be retrieved with a secure server. If this field is blank, no such restriction exists.

  5. Name = Value − Cookies are set and retrieved in the form of key and value pairs.

Setting up Cookies

It is very easy to send cookies to browser. These cookies are sent along with HTTP Header before to Content-type field. Assuming you want to set UserID and Password as cookies. Setting the cookies is done as follows −

print "Set-Cookie:UserID = XYZ;\r\n"
print "Set-Cookie:Password = XYZ123;\r\n"
print "Set-Cookie:Expires = Tuesday, 31-Dec-2007 23:12:40 GMT;\r\n"
print "Set-Cookie:Domain = www.tutorialspoint.com;\r\n"
print "Set-Cookie:Path = /perl;\n"
print "Content-type:text/html\r\n\r\n"
...........Rest of the HTML Content....

From this example, you must have understood how to set cookies. We use Set-Cookie HTTP header to set cookies.

It is optional to set cookies attributes like Expires, Domain, and Path. It is notable that cookies are set before sending magic line "Content-type:text/html\r\n\r\n.

Retrieving Cookies

It is very easy to retrieve all the set cookies. Cookies are stored in CGI environment variable HTTP_COOKIE and they will have following form −

key1 = value1;key2 = value2;key3 = value3....

Here is an example of how to retrieve cookies.

# Import modules for CGI handling
from os import environ
import cgi, cgitb

if environ.has_key('HTTP_COOKIE'):
   for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):
      (key, value ) = split(cookie, '=');
      if key == "UserID":
         user_id = value

      if key == "Password":
         password = value

print "User ID  = %s" % user_id
print "Password = %s" % password

This produces the following result for the cookies set by above script −

User ID = XYZ
Password = XYZ123

File Upload Example

To upload a file, the HTML form must have the enctype attribute set to multipart/form-data. The input tag with the file type creates a "Browse" button.

<html>
   <body>
      <form enctype = "multipart/form-data" action = "save_file.py" method = "post">
      <p>File: <input type = "file" name = "filename" /></p>
      <p><input type = "submit" value = "Upload" /></p>
      </form>
   </body>
</html>

The result of this code is the following form −

Above example has been disabled intentionally to save people uploading file on our server, but you can try above code with your server.

Here is the script save_file.py to handle file upload −

import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# Get filename here.
fileitem = form['filename']

# Test if the file was uploaded
if fileitem.filename:
   # strip leading path from file name to avoid
   # directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())

   message = 'The file "' + fn + '" was uploaded successfully'

else:
   message = 'No file was uploaded'

print """\
Content-Type: text/html\n
<html>
   <body>
      <p>%s</p>
   </body>
</html>
""" % (message,)

If you run the above script on Unix/Linux, then you need to take care of replacing file separator as follows, otherwise on your windows machine above open() statement should work fine.

fn = os.path.basename(fileitem.filename.replace("\\", "/" ))

How To Raise a "File Download" Dialog Box?

Sometimes, it is desired that you want to give option where a user can click a link and it will pop up a "File Download" dialogue box to the user instead of displaying actual content. This is very easy and can be achieved through HTTP header. This HTTP header is be different from the header mentioned in previous section.

For example, if you want make a FileName file downloadable from a given link, then its syntax is as follows −

# HTTP Header
print "Content-Type:application/octet-stream; name = \"FileName\"\r\n";
print "Content-Disposition: attachment; filename = \"FileName\"\r\n\n";

# Actual File Content will go here.
fo = open("foo.txt", "rb")

str = fo.read();
print str

# Close opend file
fo.close()

Python - XML Processing

XML is a portable, open-source language that allows programmers to develop applications that can be read by other applications, regardless of operating system and/or developmental language.

What is XML?

The Extensible Markup Language (XML) is a markup language much like HTML or SGML. This is recommended by the World Wide Web Consortium and available as an open standard.

XML is extremely useful for keeping track of small to medium amounts of data without requiring an SQL- based backbone.

XML Parser Architectures and APIs.

The Python standard library provides a minimal but useful set of interfaces to work with XML. All the submodules for XML processing are available in the xml package.

  1. xml.etree.ElementTree − the ElementTree API, a simple and lightweight XML processor

  2. xml.dom − the DOM API definition.

  3. xml.dom.minidom − a minimal DOM implementation.

  4. xml.dom.pulldom − support for building partial DOM trees.

  5. xml.sax − SAX2 base classes and convenience functions.

  6. xml.parsers.expat − the Expat parser binding.

The two most basic and broadly used APIs to XML data are the SAX and DOM interfaces.

  1. Simple API for XML (SAX) − Here, you register callbacks for events of interest and then let the parser proceed through the document. This is useful when your documents are large or you have memory limitations, it parses the file as it reads it from the disk and the entire file is never stored in the memory.

  2. Document Object Model (DOM) − This is a World Wide Web Consortium recommendation wherein the entire file is read into the memory and stored in a hierarchical (tree-based) form to represent all the features of an XML document.

SAX obviously cannot process information as fast as DOM, when working with large files. On the other hand, using DOM exclusively can really kill your resources, especially if used on many small files.

SAX is read-only, while DOM allows changes to the XML file. Since these two different APIs literally complement each other, there is no reason why you cannot use them both for large projects.

For all our XML code examples, let us use a simple XML file movies.xml as an input −

<collection shelf="New Arrivals">
<movie title="Enemy Behind">
   <type>War, Thriller</type>
   <format>DVD</format>
   <year>2003</year>
   <rating>PG</rating>
   <stars>10</stars>
   <description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
   <type>Anime, Science Fiction</type>
   <format>DVD</format>
   <year>1989</year>
   <rating>R</rating>
   <stars>8</stars>
   <description>A schientific fiction</description>
</movie>
   <movie title="Trigun">
   <type>Anime, Action</type>
   <format>DVD</format>
   <episodes>4</episodes>
   <rating>PG</rating>
   <stars>10</stars>
   <description>Vash the Stampede!</description>
</movie>
   <movie title="Ishtar">
   <type>Comedy</type>
   <format>VHS</format>
   <rating>PG</rating>
   <stars>2</stars>
   <description>Viewable boredom</description>
</movie>
</collection>

Parsing XML with SAX APIs

SAX is a standard interface for event-driven XML parsing. Parsing XML with SAX generally requires you to create your own ContentHandler by subclassing xml.sax.ContentHandler.

Your ContentHandler handles the particular tags and attributes of your flavor(s) of XML. A ContentHandler object provides methods to handle various parsing events. Its owning parser calls ContentHandler methods as it parses the XML file.

The methods startDocument and endDocument are called at the start and the end of the XML file. The method characters(text) is passed the character data of the XML file via the parameter text.

The ContentHandler is called at the start and end of each element. If the parser is not in namespace mode, the methods startElement(tag, attributes) andendElement(tag) are called; otherwise, the corresponding methodsstartElementNS and endElementNS are called. Here, tag is the element tag, and attributes is an Attributes object.

Here are other important methods to understand before proceeding −

The make_parser Method

The following method creates a new parser object and returns it. The parser object created will be of the first parser type, the system finds.

xml.sax.make_parser( [parser_list] )

Here is the detail of the parameters −

  1. parser_list − The optional argument consisting of a list of parsers to use, which must all implement the make_parser method.

The parse Method

The following method creates a SAX parser and uses it to parse a document.

xml.sax.parse( xmlfile, contenthandler[, errorhandler])

Here are the details of the parameters −

  1. xmlfile − This is the name of the XML file to read from.

  2. contenthandler − This must be a ContentHandler object.

  3. errorhandler − If specified, errorhandler must be a SAX ErrorHandler object.

The parseString Method

There is one more method to create a SAX parser and to parse the specifiedXML string.

xml.sax.parseString(xmlstring, contenthandler[, errorhandler])

Here are the details of the parameters −

  1. xmlstring − This is the name of the XML string to read from.

  2. contenthandler − This must be a ContentHandler object.

  3. errorhandler − If specified, errorhandler must be a SAX ErrorHandler object.

Example

import xml.sax
class MovieHandler( xml.sax.ContentHandler ):
   def __init__(self):
      self.CurrentData = ""
      self.type = ""
      self.format = ""
      self.year = ""
      self.rating = ""
      self.stars = ""
      self.description = ""

   # Call when an element starts
   def startElement(self, tag, attributes):
      self.CurrentData = tag
      if tag == "movie":
         print ("*****Movie*****")
         title = attributes["title"]
         print ("Title:", title)

   # Call when an elements ends
   def endElement(self, tag):
      if self.CurrentData == "type":
         print ("Type:", self.type)
      elif self.CurrentData == "format":
         print ("Format:", self.format)
      elif self.CurrentData == "year":
         print ("Year:", self.year)
      elif self.CurrentData == "rating":
         print ("Rating:", self.rating)
      elif self.CurrentData == "stars":
         print ("Stars:", self.stars)
      elif self.CurrentData == "description":
         print ("Description:", self.description)
      self.CurrentData = ""

   # Call when a character is read
   def characters(self, content):
      if self.CurrentData == "type":
         self.type = content
      elif self.CurrentData == "format":
         self.format = content
      elif self.CurrentData == "year":
         self.year = content
      elif self.CurrentData == "rating":
         self.rating = content
      elif self.CurrentData == "stars":
         self.stars = content
      elif self.CurrentData == "description":
         self.description = content

if ( __name__ == "__main__"):

   # create an XMLReader
   parser = xml.sax.make_parser()

   # turn off namepsaces
   parser.setFeature(xml.sax.handler.feature_namespaces, 0)

   # override the default ContextHandler
   Handler = MovieHandler()
   parser.setContentHandler( Handler )

   parser.parse("movies.xml")

This would produce the following result −

*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Year: 2003
Rating: PG
Stars: 10
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Year: 1989
Rating: R
Stars: 8
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Stars: 10
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Stars: 2
Description: Viewable boredom

For a complete detail on SAX API documentation, please refer to standard Python SAX APIs.

Parsing XML with DOM APIs

The Document Object Model ("DOM") is a cross-language API from the World Wide Web Consortium (W3C) for accessing and modifying the XML documents.

The DOM is extremely useful for random-access applications. SAX only allows you a view of one bit of the document at a time. If you are looking at one SAX element, you have no access to another.

Here is the easiest way to load an XML document quickly and to create a minidom object using the xml.dom module. The minidom object provides a simple parser method that quickly creates a DOM tree from the XML file.

The sample phrase calls the parse( file [,parser] ) function of the minidom object to parse the XML file, designated by file into a DOM tree object.

from xml.dom.minidom import parse
import xml.dom.minidom

# Open XML document using minidom parser
DOMTree = xml.dom.minidom.parse("movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
   print ("Root element : %s" % collection.getAttribute("shelf"))

# Get all the movies in the collection
movies = collection.getElementsByTagName("movie")

# Print detail of each movie.
for movie in movies:
   print ("*****Movie*****")
   if movie.hasAttribute("title"):
      print ("Title: %s" % movie.getAttribute("title"))

   type = movie.getElementsByTagName('type')[0]
   print ("Type: %s" % type.childNodes[0].data)
   format = movie.getElementsByTagName('format')[0]
   print ("Format: %s" % format.childNodes[0].data)
   rating = movie.getElementsByTagName('rating')[0]
   print ("Rating: %s" % rating.childNodes[0].data)
   description = movie.getElementsByTagName('description')[0]
   print ("Description: %s" % description.childNodes[0].data)

This would produce the following output

Root element : New Arrivals
*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Rating: PG
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Rating: R
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Description: Viewable boredom

For a complete detail on DOM API documentation, please refer to standard Python DOM APIs.

ElementTree XML API

The xml package has an ElementTree module. This is a simple and lightweight XML processor API.

XML is a tree-like hierarchical data format. The 'ElementTree' in this module treats the whole XML document as a tree. The 'Element' class represents a single node in this tree. Reading and writing operations on XML files are done on the ElementTree level. Interactions with a single XML element and its sub-elements are done on the Element level.

Create an XML File

The tree is a hierarchical structure of elements starting with root followed by other elements. Each element is created by using the Element() function of this module.

import xml.etree.ElementTree as et
e=et.Element('name')

Each element is characterized by a tag and attrib attribute which is a dict object. For tree’s starting element, attrib is an empty dictionary.

>>> root=xml.Element('employees')
>>> root.tag
'employees'
>>> root.attrib
{}

You may now set up one or more child elements to be added under the root element. Each child may have one or more sub elements. Add them using the SubElement() function and define its text attribute.

child=xml.Element("employee")
nm = xml.SubElement(child, "name")
nm.text = student.get('name')
age = xml.SubElement(child, "salary")
age.text = str(student.get('salary'))

Each child is added to root by append() function as −

root.append(child)

After adding required number of child elements, construct a tree object by elementTree() function −

tree = et.ElementTree(root)

The entire tree structure is written to a binary file by tree object’s write() function −

f=open('employees.xml', "wb")
tree.write(f)

Example

In this example, a tree is constructed out of a list of dictionary items. Each dictionary item holds key-value pairs describing a student data structure. The tree so constructed is written to 'myfile.xml'

import xml.etree.ElementTree as et
employees=[{'name':'aaa','age':21,'sal':5000},{'name':xyz,'age':22,'sal':6000}]
root = et.Element("employees")
for employee in employees:
   child=xml.Element("employee")
   root.append(child)
   nm = xml.SubElement(child, "name")
   nm.text = student.get('name')
   age = xml.SubElement(child, "age")
   age.text = str(student.get('age'))
   sal=xml.SubElement(child, "sal")
   sal.text=str(student.get('sal'))
tree = et.ElementTree(root)
with open('employees.xml', "wb") as fh:
   tree.write(fh)

The 'myfile.xml' is stored in current working directory.

<employees><employee><name>aaa</name><age>21</age><sal>5000</sal></employee><employee><name>xyz</name><age>22</age><sal>60</sal></employee></employee>

Parse an XML File

Let us now read back the 'myfile.xml' created in above example. For this purpose, following functions in ElementTree module will be used −

ElementTree() − This function is overloaded to read the hierarchical structure of elements to a tree objects.

tree = et.ElementTree(file='students.xml')

getroot() − This function returns root element of the tree.

root = tree.getroot()

You can obtain the list of sub-elements one level below of an element.

children = list(root)

In the following example, elements and sub-elements of the 'myfile.xml' are parsed into a list of dictionary items.

Example

import xml.etree.ElementTree as et
tree = et.ElementTree(file='employees.xml')
root = tree.getroot()
employees=[]
   children = list(root)
for child in children:
   employee={}
   pairs = list(child)
   for pair in pairs:
      employee[pair.tag]=pair.text
   employees.append(employee)
print (employees)

It will produce the following output

[{'name': 'aaa', 'age': '21', 'sal': '5000'}, {'name': 'xyz', 'age':'22', 'sal': '6000'}]

Modify an XML file

We shall use iter() function of Element. It creates a tree iterator for given tag with the current element as the root. The iterator iterates over this element and all elements below it, in document (depth first) order.

Let us build iterator for all 'marks' subelements and increment text of each sal tag by 100.

import xml.etree.ElementTree as et
tree = et.ElementTree(file='students.xml')
root = tree.getroot()
for x in root.iter('sal'):
   s=int (x.text)
   s=s+100
   x.text=str(s)
with open("employees.xml", "wb") as fh:
   tree.write(fh)

Our 'employees.xml' will now be modified accordingly. We can also use set() to update value of a certain key.

x.set(marks, str(mark))

Python - GUI Programming

Python provides various options for developing graphical user interfaces (GUIs). The most important features are listed below.

  1. Tkinter − Tkinter is the Python interface to the Tk GUI toolkit shipped with Python. We would look at this option in this chapter.

  2. wxPython − This is an open-source Python interface for wxWidgets GUI toolkit. You can find a complete tutorial on WxPython here.

  3. PyQt − This is also a Python interface for a popular cross-platform Qt GUI library. TutorialsPoint has a very good tutorial on PyQt5 here.

  4. PyGTK − PyGTK is a set of wrappers written in Python and C for GTK + GUI library. The complete PyGTK tutorial is available here.

  5. PySimpleGUI − PySimpleGui is an open source, cross-platform GUI library for Python. It aims to provide a uniform API for creating desktop GUIs based on Python’s Tkinter, PySide and WxPython toolkits. For a detaile PySimpleGUI tutorial, click here.

  6. Pygame − Pygame is a popular Python library used for developing video games. It is free, open source and cross-platform wrapper around Simple DirectMedia Library (SDL). For a comprehensive tutorial on Pygame, visit this link.

  7. Jython − Jython is a Python port for Java, which gives Python scripts seamless access to the Java class libraries on the local machinehttp: //www.jython.org.

There are many other interfaces available, which you can find them on the net.

Tkinter Programming

Tkinter is the standard GUI library for Python. Python when combined with Tkinter provides a fast and easy way to create GUI applications. Tkinter provides a powerful object-oriented interface to the Tk GUI toolkit.

The tkinter package includes following modules −

  1. Tkinter − Main Tkinter module.

  2. tkinter.colorchooser − Dialog to let the user choose a color.

  3. tkinter.commondialog − Base class for the dialogs defined in the other modules listed here.

  4. tkinter.filedialog − Common dialogs to allow the user to specify a file to open or save.

  5. tkinter.font − Utilities to help work with fonts.

  6. tkinter.messagebox − Access to standard Tk dialog boxes.

  7. tkinter.scrolledtext − Text widget with a vertical scroll bar built in.

  8. tkinter.simpledialog − Basic dialogs and convenience functions.

  9. tkinter.ttk − Themed widget set introduced in Tk 8.5, providing modern alternatives for many of the classic widgets in the main tkinter module.

Creating a GUI application using Tkinter is an easy task. All you need to do is perform the following steps.

  1. Import the Tkinter module.

  2. Create the GUI application main window.

  3. Add one or more of the above-mentioned widgets to the GUI application.

  4. Enter the main event loop to take action against each event triggered by the user.

Example

# note that module name has changed from Tkinter in Python 2
# to tkinter in Python 3

import tkinter
top = tkinter.Tk()

# Code to add widgets will go here...
top.mainloop()

This would create a following window −

Tkinter Programming

When the program becomes more complex, using an object-oriented programming approach makes the code more organized.

import tkinter as tk
class App(tk.Tk):
   def __init__(self):
      super().__init__()

app = App()
app.mainloop()

Tkinter Widgets

Tkinter provides various controls, such as buttons, labels and text boxes used in a GUI application. These controls are commonly called widgets.

There are currently 15 types of widgets in Tkinter. We present these widgets as well as a brief description in the following table −

Let us study these widgets in detail.

Standard Attributes

Let us look at how some of the common attributes, such as sizes, colors and fonts are specified.

Let us study them briefly −

Geometry Management

All Tkinter widgets have access to the specific geometry management methods, which have the purpose of organizing widgets throughout the parent widget area. Tkinter exposes the following geometry manager classes: pack, grid, and place.

  1. The pack() Method − This geometry manager organizes widgets in blocks before placing them in the parent widget.

  2. The grid() Method − This geometry manager organizes widgets in a table-like structure in the parent widget.

  3. The place() Method − This geometry manager organizes widgets by placing them in a specific position in the parent widget.

Let us study the geometry management methods briefly −

SimpleDialog

The simpledialog module in tkinter package includes a dialog class and convenience functions for accepting user input through a modal dialog. It consists of a label, an entry widget and two buttons Ok and Cancel. These functions are −

  1. askfloat(title, prompt, **kw) − Accepts a floating point number.

  2. askinteger(title, prompt, **kw) − Accepts an integer input.

  3. askstring(title, prompt, **kw) − Accepts a text input from the user.

The above three functions provide dialogs that prompt the user to enter a value of the desired type. If Ok is pressed, the input is returned, if Cancel is pressed, None is returned.

askinteger

from tkinter.simpledialog import askinteger
from tkinter import *
from tkinter import messagebox
top = Tk()

top.geometry("100x100")
def show():
   num = askinteger("Input", "Input an Integer")
   print(num)

B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)

top.mainloop()

It will produce the following output

SimpleDialog

askfloat

from tkinter.simpledialog import askfloat
from tkinter import *
top = Tk()

top.geometry("100x100")
def show():
   num = askfloat("Input", "Input a floating point number")
   print(num)

B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)

top.mainloop()

It will produce the following output

askfloat

askstring

from tkinter.simpledialog import askstring
from tkinter import *

top = Tk()

top.geometry("100x100")
def show():
   name = askstring("Input", "Enter you name")
   print(name)

B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)

top.mainloop()

It will produce the following output

askstring

The FileDialog Module

The filedialog module in Tkinter package includes a FileDialog class. It also defines convenience functions that enable the user to perform open file, save file, and open directory activities.

  1. filedialog.asksaveasfilename()

  2. filedialog.asksaveasfile()

  3. filedialog.askopenfilename()

  4. filedialog.askopenfile()

  5. filedialog.askdirectory()

  6. filedialog.askopenfilenames()

  7. filedialog.askopenfiles()

askopenfile

This function lets the user choose a desired file from the filesystem. The file dialog window has Open and Cancel buttons. The file name along with its path is returned when Ok is pressed, None if Cancel is pressed.

from tkinter.filedialog import askopenfile
from tkinter import *

top = Tk()

top.geometry("100x100")
def show():
   filename = askopenfile()
   print(filename)

B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)

top.mainloop()

It will produce the following output

askopenfile

ColorChooser

The colorchooser module included in tkinter package has the feature of letting the user choose a desired color object through the color dialog. The askcolor() function presents with the color dialog with predefined color swatches and facility to choose custome color by setting RGB values. The dialog returns a tuple of RGB values of chosen color as well as its hex value.

from tkinter.colorchooser import askcolor
from tkinter import *

top = Tk()

top.geometry("100x100")
def show():
   color = askcolor()
   print(color)

B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)

top.mainloop()

It will produce the following output

ColorChooser
((0, 255, 0), '#00ff00')

ttk module

The term ttk stands from Tk Themed widgets. The ttk module was introduced with Tk 8.5 onwards. It provides additional benefits including anti-aliased font rendering under X11 and window transparency. It provides theming and styling support for Tkinter.

The ttk module comes bundled with 18 widgets, out of which 12 are already present in Tkinter. Importing ttk over-writes these widgets with new ones which are designed to have a better and more modern look across all platforms.

The 6 new widgets in ttk are, the Combobox, Separator, Sizegrip, Treeview, Notebook and ProgressBar.

To override the basic Tk widgets, the import should follow the Tk import −

from tkinter import *
from tkinter.ttk import *

The original Tk widgets are automatically replaced by tkinter.ttk widgets. They are Button, Checkbutton, Entry, Frame, Label, LabelFrame, Menubutton, PanedWindow, Radiobutton, Scale and Scrollbar.

New widgets which gives a better look and feel across platforms; however, the replacement widgets are not completely compatible. The main difference is that widget options such as "fg", "bg" and others related to widget styling are no longer present in Ttk widgets. Instead, use the ttk.Style class for improved styling effects.

The new widgets in ttk module are −

  1. Notebook − This widget manages a collection of "tabs" between which you can swap, changing the currently displayed window.

  2. ProgressBar − This widget is used to show progress or the loading process through the use of animations.

  3. Separator − Used to separate different widgets using a separator line.

  4. Treeview − This widget is used to group together items in a tree-like hierarchy. Each item has a textual label, an optional image, and an optional list of data values.

  5. ComboBox − Used to create a dropdown list of options from which the user can select one.

  6. Sizegrip − Creates a little handle near the bottom-right of the screen, which can be used to resize the window.

Combobox Widget

The Python ttk Combobox presents a drop down list of options and displays them one at a time. It is a sub class of the widget Entry. Hence it inherits many options and methods from the Entry class.

Syntax

from tkinter import ttk

Combo = ttk.Combobox(master, values.......)

The get() function to retrieve the current value of the Combobox.

Example

from tkinter import *
from tkinter import ttk

top = Tk()
top.geometry("200x150")

frame = Frame(top)
frame.pack()

langs = ["C", "C++", "Java",
   "Python", "PHP"]

Combo = ttk.Combobox(frame, values = langs)
Combo.set("Pick an Option")
Combo.pack(padx = 5, pady = 5)
top.mainloop()

It will produce the following output

Combobox Widget

Progressbar

The ttk ProgressBar widget, and how it can be used to create loading screens or show the progress of a current task.

Syntax

ttk.Progressbar(parent, orient, length, mode)

Parameters

  1. Parent − The container in which the ProgressBar is to be placed, such as root or a Tkinter frame.

  2. Orient − Defines the orientation of the ProgressBar, which can be either vertical of horizontal.

  3. Length − Defines the width of the ProgressBar by taking in an integer value.

  4. Mode − There are two options for this parameter, determinate and indeterminate.

Example

The code given below creates a progressbar with three buttons which are linked to three different functions.

The first function increments the "value" or "progress" in the progressbar by 20. This is done with the step() function which takes an integer value to change progress amount. (Default is 1.0)

The second function decrements the "value" or "progress" in the progressbar by 20.

The third function prints out the current progress level in the progressbar.

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
frame= ttk.Frame(root)
def increment():
   progressBar.step(20)

def decrement():
   progressBar.step(-20)

def display():
   print(progressBar["value"])

progressBar= ttk.Progressbar(frame, mode='determinate')
progressBar.pack(padx = 10, pady = 10)

button= ttk.Button(frame, text= "Increase", command= increment)
button.pack(padx = 10, pady = 10, side = tk.LEFT)

button= ttk.Button(frame, text= "Decrease", command= decrement)
button.pack(padx = 10, pady = 10, side = tk.LEFT)
button= ttk.Button(frame, text= "Display", command= display)
button.pack(padx = 10, pady = 10, side = tk.LEFT)

frame.pack(padx = 5, pady = 5)
root.mainloop()

It will produce the following output

Progressbar

Notebook

Tkinter ttk module has a new useful widget called Notebook. It is a of collection of of containers (e.g frames) which have many widgets as children inside.

Each "tab" or "window" has a tab ID associated with it, which is used to determine which tab to swap to.

You can swap between these containers like you would on a regular text editor.

Syntax

notebook = ttk.Notebook(master, *options)

Example

In this example, add 3 windows to our Notebook widget in two different ways. The first method involves the add() function, which simply appends a new tab to the end. The other method is the insert() function which can be used to add a tab to a specific position.

The add() function takes one mandatory parameter which is the container widget to be added, and the rest are optional parameters such as text (text to be displayed as tab title), image and compound.

The insert() function requires a tab_id, which defines the location where it should be inserted. The tab_id can be either an index value or it can be string literal like "end", which will append it to the end.

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
nb = ttk.Notebook(root)

# Frame 1 and 2
frame1 = ttk.Frame(nb)
frame2 = ttk.Frame(nb)

label1 = ttk.Label(frame1, text = "This is Window One")
label1.pack(pady = 50, padx = 20)
label2 = ttk.Label(frame2, text = "This is Window Two")
label2.pack(pady = 50, padx = 20)

frame1.pack(fill= tk.BOTH, expand=True)
frame2.pack(fill= tk.BOTH, expand=True)
nb.add(frame1, text = "Window 1")
nb.add(frame2, text = "Window 2")

frame3 = ttk.Frame(nb)
label3 = ttk.Label(frame3, text = "This is Window Three")
label3.pack(pady = 50, padx = 20)
frame3.pack(fill= tk.BOTH, expand=True)
nb.insert("end", frame3, text = "Window 3")
nb.pack(padx = 5, pady = 5, expand = True)

root.mainloop()

It will produce the following output

Notebook

Treeview

The Treeview widget is used to display items in a tabular or hierarchical manner. It has support for features like creating rows and columns for items, as well as allowing items to have children as well, leading to a hierarchical format.

Syntax

tree = ttk.Treeview(container, **options)

Options

Example

In this example we will create a simple Treeview ttk Widget and fill in some data into it. We have some data already stored in a list which will be reading and adding to the Treeview widget in our read_data() function.

We first need to define a list/tuple of column names. We have left out the column "Name" because there already exists a (default) column with a blank name.

We then assign that list/tuple to the columns option in Treeview, followed by defining the "headings", where the column is the actual column, whereas the heading is just the title of the column that appears when the widget is displayed. We give each a column a name. "#0" is the name of the default column.

The tree.insert() function has the following parameters −

  1. Parent − which is left as an empty string if there is none.

  2. Position − where we want to add the new item. To append, use tk.END

  3. Iid − which is the item ID used to later track the item in question.

  4. Text − to which we will assign the first value in the list (the name).

Value we will pass the the other 2 values we obtained from the list.

The Complete Code

import tkinter as tk
import tkinter.ttk as ttk
from tkinter import simpledialog

root = tk.Tk()
data = [
   ["Bobby",26,20000],
   ["Harrish",31,23000],
   ["Jaya",18,19000],
   ["Mark",22, 20500],
]
index=0
def read_data():
   for index, line in enumerate(data):
      tree.insert('', tk.END, iid = index,
         text = line[0], values = line[1:])
columns = ("age", "salary")

tree= ttk.Treeview(root, columns=columns ,height = 20)
tree.pack(padx = 5, pady = 5)

tree.heading('#0', text='Name')
tree.heading('age', text='Age')
tree.heading('salary', text='Salary')

read_data()
root.mainloop()

It will produce the following output

Treeview

Sizegrip

The Sizegrip widget is basically a small arrow-like grip that is typically placed at the bottom-right corner of the screen. Dragging the Sizegrip across the screen also resizes the container to which it is attached to.

Syntax

sizegrip = ttk.Sizegrip(parent, **options)

Example

import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
root.geometry("100x100")

frame = ttk.Frame(root)
label = ttk.Label(root, text = "Hello World")
label.pack(padx = 5, pady = 5)
sizegrip = ttk.Sizegrip(frame)
sizegrip.pack(expand = True, fill = tk.BOTH, anchor = tk.SE)
frame.pack(padx = 10, pady = 10, expand = True, fill = tk.BOTH)

root.mainloop()

It will produce the following output

Sizegrip

Separator

The ttk Separator widget is a very simple widget, that has just one purpose and that is to help "separate" widgets into groups/partitions by drawing a line between them. We can change the orientation of this line (separator) to either horizontal or vertical, and change its length/height.

Syntax

separator = ttk.Separator(parent, **options)

The "orient", which can either be tk.VERTICAL or tk.HORIZTONAL, for a vertical and horizontal separator respectively.

Example

Here we have created two Label widgets, and then created a Horizontal Separator between them.

import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
root.geometry("200x150")

frame = ttk.Frame(root)

label = ttk.Label(frame, text = "Hello World")
label.pack(padx = 5)

separator = ttk.Separator(frame,orient= tk.HORIZONTAL)
separator.pack(expand = True, fill = tk.X)

label = ttk.Label(frame, text = "Welcome To TutorialsPoint")
label.pack(padx = 5)

frame.pack(padx = 10, pady = 50, expand = True, fill = tk.BOTH)

root.mainloop()

It will produce the following output

Separator

Python - Command-Line Arguments

To run a Python program, we execute the following command in the command prompt terminal of the operaing system. For example, in windows, the following command is entered in Windows command prompt terminal.

command line

The line in front of the command prompt C:\> ( or $ in case of Linux operating system) is called as command-line.

If the program needs to accept input from the user, Python’s input() function is used. When the program is executed from command line, user input is accepted from the command terminal.

Example

name = input("Enter your name: ")
print ("Hello {}. How are you?".format(name))

The program is run from the command prompt terminal as follows −

command prompt

Very often, you may need to put the data to be used by the program in the command line itself and use it inside the program. An example of giving the data in the command line could be any DOS commands in Windows or Linux.

In Windows, you use the following DOS command to rename a file hello.py to hi.py.

C:\Python311>ren hello.py hi.py

In Linux you may use the mv command −

$ mv hello.py hi.py

Here ren or mv are the commands which need the old and new file names. Since they are put in line with the command, they are called command-line arguments.

You can pass values to a Python program from command line. Python collects the arguments in a list object. Python’s sys module provides access to any command-line arguments via the sys.argv variable. sys.argv is the list of command-line arguments and sys.argv[0] is the program i.e. the script name.

The hello.py script used input() function to accept user input after the script is run. Let us change it to accept input from command line.

import sys
print ('argument list', sys.argv)
name = sys.argv[1]
print ("Hello {}. How are you?".format(name))

Run the program from command-line as shown in the following figure −

command-line

The output is shown below −

C:\Python311>python hello.py Rajan
argument list ['hello.py', 'Rajan']
Hello Rajan. How are you?

The command-line arguments are always stored in string variables. To use them as numerics, you can them suitably with type conversion functions.

In the following example, two numbers are entered as command-line arguments. Inside the program, we use int() function to parse them as integer variables.

import sys
print ('argument list', sys.argv)
first = int(sys.argv[1])
second = int(sys.argv[2])
print ("sum = {}".format(first+second))

It will produce the following output

C:\Python311>python hello.py 10 20
argument list ['hello.py', '10', '20']
sum = 30

Python’s standard library includes a couple of useful modules to parse command line arguments and options −

  1. getopt − C-style parser for command line options.

  2. argparse − Parser for command-line options, arguments and sub-commands.

The getopt Module

Python provides a getopt module that helps you parse command-line options and arguments. This module provides two functions and an exception to enable command line argument parsing.

getopt.getopt method

This method parses the command line options and parameter list. Following is a simple syntax for this method −

getopt.getopt(args, options, [long_options])

Here is the detail of the parameters −

  1. args − This is the argument list to be parsed.

  2. options − This is the string of option letters that the script wants to recognize, with options that require an argument should be followed by a colon (:).

  3. long_options − This is an optional parameter and if specified, must be a list of strings with the names of the long options, which should be supported. Long options, which require an argument should be followed by an equal sign ('='). To accept only long options, options should be an empty string.

This method returns a value consisting of two elements- the first is a list of (option, value) pairs, the second is a list of program arguments left after the option list was stripped.

Each option-and-value pair returned has the option as its first element, prefixed with a hyphen for short options (e.g., '-x') or two hyphens for long options (e.g., '--long-option').

Exception getopt.GetoptError

This is raised when an unrecognized option is found in the argument list or when an option requiring an argument is given none.

The argument to the exception is a string indicating the cause of the error. The attributes msg and opt give the error message and related option.

Example

Suppose we want to pass two file names through command line and we also want to give an option to check the usage of the script. Usage of the script is as follows −

usage: test.py -i <inputfile> -o <outputfile>

Here is the following script to test.py −

import sys, getopt
def main(argv):
   inputfile = ''
   outputfile = ''
   try:
      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
   except getopt.GetoptError:
      print ('test.py -i <inputfile> -o <outputfile>')
      sys.exit(2)
   for opt, arg in opts:
      if opt == '-h':
         print ('test.py -i <inputfile> -o <outputfile>')
         sys.exit()
      elif opt in ("-i", "--ifile"):
         inputfile = arg
      elif opt in ("-o", "--ofile"):
         outputfile = arg
   print ('Input file is "', inputfile)
   print ('Output file is "', outputfile)
if __name__ == "__main__":
   main(sys.argv[1:])

Now, run the above script as follows −

$ test.py -h
usage: test.py -i <inputfile> -o <outputfile>
$ test.py -i BMP -o
usage: test.py -i <inputfile> -o <outputfile>
$ test.py -i inputfile -o outputfile
Input file is " inputfile
Output file is " outputfile

The argparse Module

The argparse module provides tools for writing very easy to use command line interfaces. It handles how to parse the arguments collected in sys.argv list, automatically generate help and issues error message when invalid options are given.

First step to design the command line interface is to set up parser object. This is done by ArgumentParser() function in argparse module. The function can be given an explanatory string as description parameter.

To start with our script will be executed from command line without any arguments. Still use parse_args() method of parser object, which does nothing because there aren’t any arguments given.

import argparse
parser=argparse.ArgumentParser(description="sample argument parser")
args=parser.parse_args()

When the above script is run −

C:\Python311>python parser1.py
C:\Python311>python parser1.py -h
usage: parser1.py [-h]
sample argument parser
options:
   -h, --help show this help message and exit

The second command line usage gives −help option which produces a help message as shown. The −help parameter is available by default.

Now let us define an argument which is mandatory for the script to run and if not given script should throw error. Here we define argument 'user' by add_argument() method.

import argparse
parser=argparse.ArgumentParser(description="sample argument parser")
parser.add_argument("user")
args=parser.parse_args()
if args.user=="Admin":
   print ("Hello Admin")
else:
   print ("Hello Guest")

This script’s help now shows one positional argument in the form of 'user'. The program checks if it’s value is 'Admin' or not and prints corresponding message.

C:\Python311>python parser2.py --help
usage: parser2.py [-h] user
sample argument parser
positional arguments:
   user
options:
   -h, --help show this help message and exit

Use the following command −

C:\Python311>python parser2.py Admin
Hello Admin

But the following usage displays Hello Guest message.

C:\Python311>python parser2.py Rajan
Hello Guest

add_argument() method

We can assign default value to an argument in add_argument() method.

import argparse
parser=argparse.ArgumentParser(description="sample argument parser")
parser.add_argument("user", nargs='?',default="Admin")
args=parser.parse_args()
if args.user=="Admin":
   print ("Hello Admin")
else:
   print ("Hello Guest")

Here nargs is the number of command-line arguments that should be consumed. '?'. One argument will be consumed from the command line if possible, and produced as a single item. If no command-line argument is present, the value from default will be produced.

By default, all arguments are treated as strings. To explicitly mention type of argument, use type parameter in the add_argument() method. All Python data types are valid values of type.

import argparse
parser=argparse.ArgumentParser(description="add numbers")
parser.add_argument("first", type=int)
parser.add_argument("second", type=int)
args=parser.parse_args()
x=args.first
y=args.second
z=x+y
print ('addition of {} and {} = {}'.format(x,y,z))

It will produce the following output

C:\Python311>python parser3.py 10 20
addition of 10 and 20 = 30

In the above examples, the arguments are mandatory. To add optional argument, prefix its name by double dash --. In following case surname argument is optional because it is prefixed by double dash (--surname).

import argparse
parser=argparse.ArgumentParser()
parser.add_argument("name")
parser.add_argument("--surname")
args=parser.parse_args()
print ("My name is ", args.name, end=' ')
if args.surname:
   print (args.surname)

A one letter name of argument prefixed by single dash acts as a short name option.

C:\Python311>python parser3.py Anup
My name is Anup
C:\Python311>python parser3.py Anup --surname Gupta
My name is Anup Gupta

If it is desired that an argument should value only from a defined list, it is defined as choices parameter.

import argparse
parser=argparse.ArgumentParser()
parser.add_argument("sub", choices=['Physics', 'Maths', 'Biology'])
args=parser.parse_args()
print ("My subject is ", args.sub)

Note that if value of parameter is not from the list, invalid choice error is displayed.

C:\Python311>python parser3.py Physics
My subject is Physics
C:\Python311>python parser3.py History
usage: parser3.py [-h] {Physics,Maths,Biology}
parser3.py: error: argument sub: invalid choice: 'History' (choose from
'Physics', 'Maths', 'Biology')

Python - Docstrings

In Python, a docstring is a string literal that serves as the documentation of different Python objects such as functions, modules, class as well as its methods and packages. It is the first line in the definition of all these constructs and becomes the value of doc attribute.

DocString of a Function

def addition(x, y):
   '''This function returns the sum of two numeric arguments'''
   return x+y
print ("Docstring of addition function:", addition.__doc__)

It will produce the following output

Docstring of addition function: This function returns the sum of two numeric arguments

The docstring can be written with single, double or triple quotation marks. However, most of the times you may want a descriptive text as the documentation, so using triple quotes is desirable.

All the built-in modules and functions have the doc property that returns their docstring.

Docstring of math module

import math

print ("Docstring of math module:", math.__doc__)

It will produce the following output

Docstring of math module: This module provides access to the mathematical functions
 defined by the C standard.

Docstring of Built-in functions

Following code displays the docstring of abs() function and randint() function in random module.

print ("Docstring of built-in abs() function:", abs.__doc__)
import random

print ("Docstring of random.randint() function:",
random.randint.__doc__)

It will produce the following output −

Docstring of built-in abs() function: Return the absolute value of the
argument.

Docstring of random.randint() function: Return random integer in range
[a, b], including both end points.

Docstring of built-in class

Docstrings of built-in classes are usually more explanatory, hence the text is over multiple lines. Below, we check the docstring of built-in dict class

print ("Docstring of built-in dict class:", dict.__doc__)

It will produce the following output

Docstring of built-in dict class: dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
   (key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
   d = {}
   for k, v in iterable:
      d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

Docstring of Template class

Template class is defined in string module of Python’s standard library. Its docstring is as follows −

from string import Template

print ("Docstring of Template class:", Template.__doc__)

It will produce the following output

Docstring of Template class: A string class for supporting $- substitutions.

Docstring in help system

The docstring is also used by Python’s built-in help service. For example check its help of abs() function in Python interpreter −

>>> help (abs)
Help on built-in function abs in module builtins:
abs(x, /)
   Return the absolute value of the argument.

Similarly, define a function in the interpreter terminal and run help command.

>>> def addition(x,y):
... '''addtion(x,y)
... Returns the sum of x and y
... '''
... return x+y
...
>>> help (addition)
Help on function addition in module __main__:
addition(x, y)
   addtion(x,y)
   Returns the sum of x and y

Docstring also is used by IDEs to provide useful type ahead information while editing the code.

docstring

Docstring as Comment

A string literal appearing anywhere other than these objects (function, method, class, module or package) is ignored by the interpreter, hence they are similar to comments (which start with # symbol).

# This is a comment
print ("Hello World")
'''This is also a comment'''
print ("How are you?")

Python - JSON

JSON stands for JavaScript Object Notation. It is a lightweight data interchange format. It is similar to pickle. However, pickle serialization is Python specific whereas JSON format is implemented by many languages. The json module in Python’s standard library implements object serialization functionality that is similar to pickle and marshal modules.

Just as in pickle module, the json module also provides dumps() and loads() function for serialization of Python object into JSON encoded string, and dump() and load() functions write and read serialized Python objects to/from file.

  1. dumps() − This function converts the object into JSON format.

  2. loads() − This function converts a JSON string back to Python object.

The following example the demonstrates basic usage of these functions −

Example 1

import json

data=['Rakesh',{'marks':(50,60,70)}]
s=json.dumps(data)
print (s, type(s))

data = json.loads(s)
print (data, type(data))

It will produce the following output

["Rakesh", {"marks": [50, 60, 70]}] <class 'str'>
['Rakesh', {'marks': [50, 60, 70]}] <class 'list'>

The dumps() function can take optional sort_keys argument. By default it is False. If set to True, the dictionary keys appear in sorted order in the JSON string.

data=['Rakesh',{'marks':(50,60,70)}]
s=json.dumps(data, sort_keys=True)

Example 2

The dumps() function has another optional parameter called indent which takes a number as value. It decides length of each segment of formatted representation of json string, similar to pprint output.

import json
data=['Rakesh',{'marks':(50,60,70)}]
s=json.dumps(data, indent = 2)
print (s)

It will produce the following output −

[
  "Rakesh",
  {
    "marks": [
      50,
      60,
      70
    ]
  }
]

The json module also has object-oriented API corresponding to above functions. There are two classes defined in the module − JSONEncoder and JSONDecoder.

JSONEncoder Class

Object of this class is encoder for Python data structures. Each Python data type is converted in corresponding JSON type as shown in following table −

The JSONEncoder class is instantiated by JSONEncoder() constructor. Following important methods are defined in encoder class −

  1. encode() − serializes Python object into JSON format.

  2. iterencode() − Encodes the object and returns an iterator yielding encoded form of each item in the object.

  3. indent − Determines indent level of encoded string.

  4. sort_keys − is either true or false to make keys appear in sorted order or not.

  5. check_circular − if True, check for circular reference in container type object.

The following example encodes Python list object.

Example

import json

data=['Rakesh',{'marks':(50,60,70)}]
e=json.JSONEncoder()

Using iterencode() method, each part of the encoded string is displayed as below −

import json
data=['Rakesh',{'marks':(50,60,70)}]
e=json.JSONEncoder()
for obj in e.iterencode(data):
   print (obj)

It will produce the following output −

["Rakesh"
,
{
"marks"
:
[50
, 60
, 70
]
}
]

JSONDEcoder class

Object of this class helps in decoded in json string back to Python data structure. Main method in this class is decode(). Following example code retrieves Python list object from encoded string in earlier step.

Example

import json
data=['Rakesh',{'marks':(50,60,70)}]
e=json.JSONEncoder()
s = e.encode(data)
d=json.JSONDecoder()
obj = d.decode(s)
print (obj, type(obj))

It will produce the following output

['Rakesh', {'marks': [50, 60, 70]}] <class 'list'>

JSON with Files/Streams

The json module defines load() and dump() functions to write JSON data to a file like object − which may be a disk file or a byte stream and read data back from them.

dump() Function

This function encodes Python object data in JSON format and writes it to a file. The file must be having write permission.

Example

import json
data=['Rakesh', {'marks': (50, 60, 70)}]
fp=open('json.txt','w')
json.dump(data,fp)
fp.close()

This code will create 'json.txt' in current directory. It shows the contents as follows −

["Rakesh", {"marks": [50, 60, 70]}]

load() Function

This function loads JSON data from the file and constructs Python object from it. The file must be opened with read permission.

Example

import json
fp=open('json.txt','r')
ret=json.load(fp)
print (ret)

Python - Sending Email

An application that handles and delivers e-mail over the Internet is called a "mail server". Simple Mail Transfer Protocol (SMTP) is a protocol, which handles sending an e-mail and routing e-mail between mail servers. It is an Internet standard for email transmission.

Python provides smtplib module, which defines an SMTP client session object that can be used to send mails to any Internet machine with an SMTP or ESMTP listener daemon.

smptlib.SMTP() Function

To send an email, you need to obtain the object of SMTP class with the following function −

import smtplib

smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )

Here is the detail of the parameters −

  1. host − This is the host running your SMTP server. You can specifiy IP address of the host or a domain name like tutorialspoint.com. This is an optional argument.

  2. port − If you are providing host argument, then you need to specify a port, where SMTP server is listening. Usually this port would be 25.

  3. local_hostname − If your SMTP server is running on your local machine, then you can specify just localhost as the option.

The SMTP object has following methods −

  1. connect(host, port, source_address) − This method establishes connection to a host on a given port.

  2. login(user, password) − Log in on an SMTP server that requires authentication.

  3. quit() − terminate the SMTP session.

  4. data(msg) − sends message data to server.

  5. docmd(cmd, args) − send a command, and return its response code.

  6. ehlo(name) − Hostname to identify itself.

  7. starttls() − puts the connection to the SMTP server into TLS mode.

  8. getreply() −get a reply from the server consisting of server response code.

  9. putcmd(cmd, args) − sends a command to the server.

  10. send_message(msg, from_addr, to_addrs) − converts message to a bytestring and passes it to sendmail.

The smtpd Module

The smtpd module that comes pre-installed with Python has a local SMTP debugging server. You can test email functionality by starting it. It doesn’t actually send emails to the specified address, it discards them and prints their content to the console. Running a local debugging server means it’s not necessary to deal with encryption of messages or use credentials to log in to an email server.

You can start a local SMTP debugging server by typing the following in Command Prompt −

python -m smtpd -c DebuggingServer -n localhost:1025

Example

The following program sends a dummy email with the help of smtplib functionality.

import smtplib

def prompt(prompt):
   return input(prompt).strip()

fromaddr = prompt("From: ")
toaddrs = prompt("To: ").split()
print("Enter message, end with ^D (Unix) or ^Z (Windows):")

# Add the From: and To: headers at the start!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
   % (fromaddr, ", ".join(toaddrs)))
while True:
   try:
      line = input()
   except EOFError:
      break
   if not line:
      break
   msg = msg + line

print("Message length is", len(msg))
server = smtplib.SMTP('localhost', 1025)
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()

Basically we use the sendmail() method, specifying three parameters −

  1. The sender − A string with the address of the sender.

  2. TheThe receivers − A list of strings, one for each recipient.

  3. TheThe message − A message as a string formatted as specified in the various RFCs.

We have already started the SMTP debugging server. Run this program. User is asked to input the sender’s ID, recipients and the message.

python example.py
From: abc@xyz.com
To: xyz@abc.com
Enter message, end with ^D (Unix) or ^Z (Windows):
Hello World
^Z

The console reflects the following log −

From: abc@xyz.com
reply: retcode (250); Msg: b'OK'
send: 'rcpt TO:<xyz@abc.com>\r\n'
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
send: 'data\r\n'
reply: b'354 End data with <CR><LF>.<CR><LF>\r\n'
reply: retcode (354); Msg: b'End data with <CR><LF>.<CR><LF>'
data: (354, b'End data with <CR><LF>.<CR><LF>')
send: b'From: abc@xyz.com\r\nTo: xyz@abc.com\r\n\r\nHello
World\r\n.\r\n'
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
data: (250, b'OK')
send: 'quit\r\n'
reply: b'221 Bye\r\n'
reply: retcode (221); Msg: b'Bye'

The terminal in which the SMTPD server is running shows this output

---------- MESSAGE FOLLOWS ----------
b'From: abc@xyz.com'
b'To: xyz@abc.com'
b'X-Peer: ::1'
b''
b'Hello World'
------------ END MESSAGE ------------

Using gmail SMTP

Let us look at the script below which uses Google’s smtp mail server to send an email message.

First of all SMTP object is set up using gmail’s smtp server and port 527. The SMTP object then identifies itself by invoking ehlo() command. We also activate Transport Layer Security to the outgoing mail message.

Next the login() command is invoked by passing credentials as arguments to it. Finally the mail message is assembled by attaching it a header in prescribed format and it is sent using sendmail() method. The SMTP object is closed afterwards.

import smtplib
content="Hello World"
mail=smtplib.SMTP('smtp.gmail.com', 587)
mail.ehlo()
mail.starttls()
sender='mvl@gmail.com'
recipient='tester@gmail.com'
mail.login('mvl@gmail.com','******')
header='To:'+receipient+'\n'+'From:' \
+sender+'\n'+'subject:testmail\n'
content=header+content
mail.sendmail(sender, recipient, content)
mail.close()

Before running above script, sender’s gmail account must be configured to allow 'less secure apps'. Visit following link.

https://myaccount.google.com/lesssecureapps Set the shown toggle button to ON.

toggle button

If everything goes well, execute the above script. The message should be delivered to the recipient’s inbox.

Python - Further Extensions

Any code that you write using any compiled language like C, C++, or Java can be integrated or imported into another Python script. This code is considered as an "extension."

A Python extension module is nothing more than a normal C library. On Unix machines, these libraries usually end in .so (for shared object). On Windows machines, you typically see .dll (for dynamically linked library).

Pre-Requisites for Writing Extensions

To start writing your extension, you are going to need the Python header files.

  1. On Unix machines, this usually requires installing a developer-specific package.

  2. Windows users get these headers as part of the package when they use the binary Python installer.

Additionally, it is assumed that you have a good knowledge of C or C++ to write any Python Extension using C programming.

First look at a Python Extension

For your first look at a Python extension module, you need to group your code into four parts −

  1. The header file Python.h.

  2. The C functions you want to expose as the interface from your module..

  3. A table mapping the names of your functions as Python developers see them as C functions inside the extension module..

  4. An initialization function.

The Header File Python.h

You need to include Python.h header file in your C source file, which gives you the access to the internal Python API used to hook your module into the interpreter.

Make sure to include Python.h before any other headers you might need. You need to follow the includes with the functions you want to call from Python.

The C Functions

The signatures of the C implementation of your functions always takes one of the following three forms −

static PyObject *MyFunction(PyObject *self, PyObject *args);
static PyObject *MyFunctionWithKeywords(PyObject *self,
   PyObject *args,
   PyObject *kw);
static PyObject *MyFunctionWithNoArgs(PyObject *self);

Each one of the preceding declarations returns a Python object. There is no such thing as a void function in Python as there is in C. If you do not want your functions to return a value, return the C equivalent of Python’s None value. The Python headers define a macro, Py_RETURN_NONE, that does this for us.

The names of your C functions can be whatever you like as they are never seen outside of the extension module. They are defined as static function.

Your C functions usually are named by combining the Python module and function names together, as shown here −

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}

This is a Python function called func inside the module module. You will be putting pointers to your C functions into the method table for the module that usually comes next in your source code.

The Method Mapping Table

This method table is a simple array of PyMethodDef structures. That structure looks something like this −

struct PyMethodDef {
   char *ml_name;
   PyCFunction ml_meth;
   int ml_flags;
   char *ml_doc;
};

Here is the description of the members of this structure −

  1. ml_name − This is the name of the function as the Python interpreter presents when it is used in Python programs.

  2. ml_meth − This is the address of a function that has any one of the signatures, described in the previous section.

  3. ml_flags − This tells the interpreter which of the three signatures ml_meth is using. This flag usually has a value of METH_VARARGS. This flag can be bitwise OR’ed with METH_KEYWORDS if you want to allow keyword arguments into your function. This can also have a value of METH_NOARGS that indicates you do not want to accept any arguments.

  4. mml_doc − This is the docstring for the function, which could be NULL if you do not feel like writing one.

This table needs to be terminated with a sentinel that consists of NULL and 0 values for the appropriate members.

Example

For the above-defined function, we have the following method mapping table −

static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { NULL, NULL, 0, NULL }
};

The Initialization Function

The last part of your extension module is the initialization function. This function is called by the Python interpreter when the module is loaded. It is required that the function be named initModule, where Module is the name of the module.

The initialization function needs to be exported from the library you will be building. The Python headers define PyMODINIT_FUNC to include the appropriate incantations for that to happen for the particular environment in which we are compiling. All you have to do is use it when defining the function.

Your C initialization function generally has the following overall structure −

PyMODINIT_FUNC initModule() {
   Py_InitModule3(func, module_methods, "docstring...");
}

Here is the description of Py_InitModule3 function −

  1. func − This is the function to be exported.

  2. module_methods − This is the mapping table name defined above.

  3. docstring − This is the comment you want to give in your extension.

Putting all this together, it looks like the following −

#include <Python.h>
static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}
static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { NULL, NULL, 0, NULL }
};
PyMODINIT_FUNC initModule() {
   Py_InitModule3(func, module_methods, "docstring...");
}

Example

A simple example that makes use of all the above concepts −

#include <Python.h>
static PyObject* helloworld(PyObject* self)
{
   return Py_BuildValue("s", "Hello, Python extensions!!");
}
static char helloworld_docs[] =
   "helloworld( ): Any message you want to put here!!\n";
static PyMethodDef helloworld_funcs[] = {
   {"helloworld", (PyCFunction)helloworld,
   METH_NOARGS, helloworld_docs},
   {NULL}
};
void inithelloworld(void)
{
   Py_InitModule3("helloworld", helloworld_funcs,
      "Extension module example!");
}

Here the Py_BuildValue function is used to build a Python value. Save above code in hello.c file. We would see how to compile and install this module to be called from Python script.

Building and Installing Extensions

The distutils package makes it very easy to distribute Python modules, both pure Python and extension modules, in a standard way. Modules are distributed in the source form, built and installed via a setup script usually called setup.pyas.

For the above module, you need to prepare the following setup.py script −

from distutils.core import setup, Extension
setup(name='helloworld', version='1.0', \
   ext_modules=[Extension('helloworld', ['hello.c'])])

Now, use the following command, which would perform all needed compilation and linking steps, with the right compiler and linker commands and flags, and copies the resulting dynamic library into an appropriate directory −

$ python setup.py install

On Unix-based systems, you will most likely need to run this command as root in order to have permissions to write to the site-packages directory. This usually is not a problem on Windows.

Importing Extensions

Once you install your extensions, you would be able to import and call that extension in your Python script as follows −

import helloworld
print helloworld.helloworld()

This would produce the following output

Hello, Python extensions!!

Passing Function Parameters

As you will most likely want to define functions that accept arguments, you can use one of the other signatures for your C functions. For example, the following function, that accepts some number of parameters, would be defined like this −

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Parse args and do something interesting here. */
   Py_RETURN_NONE;
}

The method table containing an entry for the new function would look like this −

static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { "func", module_func, METH_VARARGS, NULL },
   { NULL, NULL, 0, NULL }
};

You can use the API PyArg_ParseTuple function to extract the arguments from the one PyObject pointer passed into your C function.

The first argument to PyArg_ParseTuple is the args argument. This is the object you will be parsing. The second argument is a format string describing the arguments as you expect them to appear. Each argument is represented by one or more characters in the format string as follows.

static PyObject *module_func(PyObject *self, PyObject *args) {
   int i;
   double d;
   char *s;
   if (!PyArg_ParseTuple(args, "ids", &i, &d, &s)) {
      return NULL;
   }

   /* Do something interesting here. */
   Py_RETURN_NONE;
}

Compiling the new version of your module and importing it enables you to invoke the new function with any number of arguments of any type −

module.func(1, s="three", d=2.0)
module.func(i=1, d=2.0, s="three")
module.func(s="three", d=2.0, i=1)

You can probably come up with even more variations.

The PyArg_ParseTuple Function

re is the standard signature for the PyArg_ParseTuple function −

int PyArg_ParseTuple(PyObject* tuple,char* format,...)

This function returns 0 for errors, and a value not equal to 0 for success. Tuple is the PyObject* that was the C function’s second argument. Here format is a C string that describes mandatory and optional arguments.

Here is a list of format codes for the PyArg_ParseTuple function −

Returning Values

Py_BuildValue takes in a format string much like PyArg_ParseTuple does. Instead of passing in the addresses of the values you are building, you pass in the actual values. Here is an example showing how to implement an add function.

static PyObject *foo_add(PyObject *self, PyObject *args) {
   int a;
   int b;
   if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
      return NULL;
   }
   return Py_BuildValue("i", a + b);
}

This is what it would look like if implemented in Python −

def add(a, b):
   return (a + b)

You can return two values from your function as follows. This would be captured using a list in Python.

static PyObject *foo_add_subtract(PyObject *self, PyObject *args) {
   int a;
   int b;
   if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
      return NULL;
   }
   return Py_BuildValue("ii", a + b, a - b);
}

This is what it would look like if implemented in Python −

def add_subtract(a, b):
   return (a + b, a - b)

The Py_BuildValue Function

Here is the standard signature for Py_BuildValue function −

PyObject* Py_BuildValue(char* format,...)

Here format is a C string that describes the Python object to build. The following arguments of Py_BuildValue are C values from which the result is built. ThePyObject* result is a new reference.

The following table lists the commonly used code strings, of which zero or more are joined into a string format.

Code {…​} builds dictionaries from an even number of C values, alternately keys and values. For example, Py_BuildValue("{issi}",23,"zig","zag",42) returns a dictionary like Python’s {23:'zig','zag':42}

Python - Tools/Utilities

The standard library comes with a number of modules that can be used both as modules and as command-line utilities.

The dis Module

The dis module is the Python disassembler. It converts byte codes to a format that is slightly more appropriate for human consumption.

Example

import dis
def sum():
   vara = 10
   varb = 20

   sum = vara + varb
   print ("vara + varb = %d" % sum)

# Call dis function for the function.
dis.dis(sum)

This would produce the following result −

  3           0 LOAD_CONST               1 (10)
              2 STORE_FAST               0 (vara)

  4           4 LOAD_CONST               2 (20)
              6 STORE_FAST               1 (varb)

  6           8 LOAD_FAST                0 (vara)
             10 LOAD_FAST                1 (varb)
             12 BINARY_ADD
             14 STORE_FAST               2 (sum)

  7          16 LOAD_GLOBAL              0 (print)
             18 LOAD_CONST               3 ('vara + varb = %d')
             20 LOAD_FAST                2 (sum)
             22 BINARY_MODULO
             24 CALL_FUNCTION            1
             26 POP_TOP
             28 LOAD_CONST               0 (None)
             30 RETURN_VALUE

The pdb Module

The pdb module is the standard Python debugger. It is based on the bdb debugger framework.

You can run the debugger from the command line (type n [or next] to go to the next line and help to get a list of available commands) −

Example

Before you try to run pdb.py, set your path properly to Python lib directory. So let us try with above example sum.py −

$pdb.py sum.py
> /test/sum.py(3)<module>()
-> import dis
(Pdb) n
> /test/sum.py(5)<module>()
-> def sum():
(Pdb) n
>/test/sum.py(14)<module>()
-> dis.dis(sum)
(Pdb) n
  6           0 LOAD_CONST               1 (10)
              3 STORE_FAST               0 (vara)

  7           6 LOAD_CONST               2 (20)
              9 STORE_FAST               1 (varb)

  9          12 LOAD_FAST                0 (vara)
             15 LOAD_FAST                1 (varb)
             18 BINARY_ADD
             19 STORE_FAST               2 (sum)

  10         22 LOAD_CONST               3 ('vara + varb = %d')
             25 LOAD_FAST                2 (sum)
             28 BINARY_MODULO
             29 PRINT_ITEM
             30 PRINT_NEWLINE
             31 LOAD_CONST               0 (None)
             34 RETURN_VALUE
--Return--
> /test/sum.py(14)<module>()->None
-v dis.dis(sum)
(Pdb) n
--Return--
> <string>(1)<module>()->None
(Pdb)

The profile Module

The profile module is the standard Python profiler. You can run the profiler from the command line −

Example

Let us try to profile the following program −

vara = 10
varb = 20
sum = vara + varb
print "vara + varb = %d" % sum

Now, try running cProfile.py over this file sum.py as follow −

$cProfile.py sum.py
vara + varb = 30
   4 function calls in 0.000 CPU seconds
   Ordered by: standard name
ncalls   tottime  percall  cumtime  percall filename:lineno
 1       0.000    0.000    0.000    0.000 <string>:1(<module>)
 1       0.000    0.000    0.000    0.000 sum.py:3(<module>)
 1       0.000    0.000    0.000    0.000 {execfile}
 1       0.000    0.000    0.000    0.000 {method ......}

The tabnanny Module

The tabnanny module checks Python source files for ambiguous indentation. If a file mixes tabs and spaces in a way that throws off indentation, no matter what tab size you’re using, the nanny complains.

Example

Let us try to profile the following program −

vara = 10
varb = 20

sum = vara + varb
print "vara + varb = %d" % sum

If you would try a correct file with tabnanny.py, then it won’t complain as follows −

$tabnanny.py -v sum.py
'sum.py': Clean bill of health.

Python - GUIs

In this chapter, you will learn about some popular Python IDEs (Integrated Development Environment), and how to use IDE for program development.

To use the scripted mode of Python, you need to save the sequence of Python instructions in a text file and save it with .py extension. You can use any text editor available on the operating system. Whenever the interpreter encounters errors, the source code needs to be edited and run again and again. To avoid this tedious method, IDE is used. An IDE is a one stop solution for typing, editing the source code, detecting the errors and executing the program.

IDLE

Python’s standard library contains the IDLE module. IDLE stands for Integrated Development and Learning Environment. As the name suggests, it is useful when one is in the learning stage. It includes a Python interactive shell and a code editor, customized to the needs of Python language structure. Some of its important features include syntax highlighting, auto-completion, customizable interface etc.

To write a Python script, open a new text editor window from the File menu.

idle_module

A new editor window opens in which you can enter the Python code. Save it and run it with Run menu.

new_window

Jupyter Notebook

Initially developed as a web interface for IPython, Jupyter Notebook supports multiple languages. The name itself derives from the alphabets from the names of the supported languages − Ju*lia, *PYT*hon and *R. Jupyter notebook is a client server application. The server is launched at the localhost, and the browser acts as its client.

Install Jupyter notebook with PIP −

pip3 install jupyter

Invoke from the command line.

C:\Users\Acer>jupyter notebook

The server is launched at localhost’s 8888 port number.

server_launched

The default browser of your system opens a link http://localhost:8888/tree to display the dashboard.

jupyter

Open a new Python notebook. It shows IPython style input cell. Enter Python instructions and run the cell.

python_notebook

Jupyter notebook is a versatile tool, used very extensively by data scientists to display inline data visualizations. The notebook can be conveniently converted and distributed in PDF, HTML or Markdown format.

VS Code

Microsoft has developed a source code editor called VS Code (Visual Studio Code) that supports multiple languages including C++, Java, Python and others. It provides features such as syntax highlighting, autocomplete, debugger and version control.

VS Code is a freeware. It is available for download and install from https://code.visualstudio.com/.

Launch VS Code from the start menu (in Windows).

vs_code_window

You can also launch VS Code from command line −

C:\test>code .

VS Code cannot be used unless respective language extension is not installed. VS Code Extensions marketplace has a number of extensions for language compilers and other utilities. Search for Python extension from the Extension tab (Ctrl+Shift+X) and install it.

VS_Code_Extensions

After activating Python extension, you need to set the Python interpreter. Press Ctrl+Shift+P and select Python interpreter.

select_interpreter

Open a new text file, enter Python code and save the file.

python_code_file

Open a command prompt terminal and run the program.

command_prompt_terminal

PyCharm

PyCharm is another popular Python IDE. It has been developed by JetBrains, a Czech software company. Its features include code analysis, a graphical debugger, integration with version control systems etc. PyCharm supports web development with Django.

The community as well as professional editions can be downloaded from https://www.jetbrains.com/pycharm/download.

Download, install the latest Version: 2022.3.2 and open PyCharm. The Welcome screen appears as below −

welcome_to_pycharm

When you start a new project, PyCharm creates a virtual environment for it based on the choice of folder location and the version of Python interpreter chosen.

new_project

You can now add one or more Python scripts required for the project. Here we add a sample Python code in main.py file.

python_project

To execute the program, choose from Run menu or use Shift+F10 shortcut.

run_the_program

Output will be displayed in the console window as shown below −

output_displayed