文章目录
- 第1章 Python简介
- 1.1 Python简介
- 1.2 Python历史
- 1.3 Python特点
- 1.4 Python的应用场景
- 1.5 Python的版本
- 第2章 Python环境搭建
- 2.1 Python软件安装
- 2.2 编辑器安装
- 第3章 Python基础语法
- 3.1 第一个Python程序
- 3.1.1 使用 Python 命令行
- 3.1.2 使用 IPython
- 3.1.3 使用 PyCharm
- 3.2 注释
- 3.2.1 单行注释
- 3.2.2 多行注释
- 3.3 变量
- 3.3.1 变量的赋值
- 3.3.2 变量的命名
- 3.4 关键字
- 3.4.1 Python3.x关键字
- 3.5 基本数据类型
- 3.6 数据类型转换
- 3.6.1 强制类型转换
- 3.6.2 自动类型转换
- 3.7 运算符
- 3.7.1 算术运算符
- 3.7.2 比较运算符
- 3.7.3 赋值运算符
- 3.7.4 逻辑运算符
- 3.7.5 成员运算符
- 3.7.6 身份运算符
- 3.7.7 位运算符
- 3.8 type() 和 input()函数
- 3.8.1 type() 函数
- 3.8.2 input() 函数
- 3.9 字符串运算
- 3.9.1 拼接字符串
- 3.9.2 重复字符串
- 3.10 格式化输出
- 3.10.1 使用 `%` 运算符
- 3.10.2 使用 `str.format()`
- 3.10.3 使用 f-string (f-strings)
- 3.10.4 使用 `str()` 和字符串拼接
- 3.10.5 格式符号
- 第4章 基本控制结构
- 4.1 顺序结构
- 4.2 选择结构
- 4.2.1 if 语句
- 4.2.2 if-else 语句
- 4.2.3 if-elif-else 语句
- 4.2.4 选择结构的嵌套
- 4.3 循环结构
- 4.3.1 for循环
- 4.3.2 while循环
- 4.3.3 break关键字
- 4.3.4 continue关键字
- 第5章 函数
- 5.1 定义与调用
- 5.2 函数名
- 5.3 函数参数
- 5.3.1 位置参数
- 5.3.2 关键字参数
- 5.3.3 默认值参数
- 5.3.4 不定长参数
- 5.3.5 参数组合
- 5.4 函数返回值
- 5.5 作用域
- 5.6 函数的嵌套
- 5.7 匿名函数
- 5.8 文档字符串
- 5.9 内置函数
- 5.9.1 获取内置函数帮助信息
- 5.9.2 常见内置函数示例
- 第6章 面向对象
- 6.1 面向过程和面向对象
- 6.1.1 面向过程编程
- 6.1.2 面向对象编程
- 6.2 类和对象
- 6.2.1 类 (Class)
- 6.2.2 类的定义
- 6.2.3 对象 (Object)
- 6.2.4 创建对象
- 6.2.5 访问属性和方法
- 6.2.6 构造方法
- 6.3 魔术方法
- 6.3.1 `__init__(self,...)`方法
- 6.3.2 `__str__(self)`方法
- 6.3.3 `__del__(self)`方法
- 6.4 面向对象三大特征
- 6.4.1 封装
- 6.4.2 继承
- 6.4.3 多态
- 6.5 属性
- 6.5.1 类属性
- 6.5.2 实例属性
- 6.6 方法
- 6.6.1 实例方法
- 6.6.2 类方法
- 6.6.3 类静态方法
- 第7章 模块与包
- 7.1 模块
- 7.2 包
- 7.3 包管理工具
- 第8章 异常处理
- 8.1 异常的概念
- 8.2 捕获异常
- 8.3 异常的传递
- 8.4 抛出(raise)异常
第1章 Python简介
1.1 Python简介
-
Python是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。
-
Python的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。
-
Python是一种解释型语言: 意味着开发过程中没有编译这个环节。类似于PHP语言。
-
Python是交互式语言: 意味着可以在一个 Python 提示符 >>> 后直接执行代码。
-
Python是面向对象语言: 意味着Python支持面向对象的风格或代码封装在对象的编程技术。
-
Python是初学者的语言:Python对初级程序员而言,是一种伟大的语言,它支持广泛的应用程序开发,从简单的文字处理到WWW浏览器再到游戏。
1.2 Python历史
- 创立与发展
- 1989年:Guido van Rossum 在圣诞节期间开始设计 Python,目的是创造一种更易于阅读和编写的编程语言。
- 1991年:发布了第一个公开版本 Python 0.9.0。
- 1994年:发布了 Python 1.0 版本,引入了函数式编程的概念,如 lambda、map、filter 和 reduce。
- Python 2.x
- 2000年:Python 2.0 发布,引入了垃圾回收机制,并支持 Unicode。
- 2008年:Python 2.6 发布,增加了对多线程的支持,并改进了异常处理。
- Python 3.x
- 2008年:Python 3.0 发布,这是 Python 的一次重大更新,引入了许多改进,包括更好的 Unicode 支持、简化语法和改进的库。
- 2010年:Python 3.2 发布,带来了更好的安全性、性能改进和新特性。
- 2014年:Python 3.4 发布,引入了 asyncio 模块,支持异步 I/O。
- 2015年:Python 3.5 发布,进一步增强了 asyncio,并引入了新的类型提示功能。
- 2018年:Python 3.7 发布,带来了新的数据类(data classes)、异步上下文管理器和其他改进。
- 2019年:Python 3.8 发布,引入了新的赋值表达式(walrus operator
:=
)和其他新特性。 - 2020年:Python 3.9 发布,改进了类型提示,增加了新的字符串替换方法,并增强了字典解包等功能。
- 2021年:Python 3.10 发布,引入了模式匹配(Pattern Matching)和其他新特性。
- 2022年:Python 3.11 发布,带来了性能提升、改进的错误处理和新的类型检查工具等。
- Python 2.x 的退役
- 2020年1月1日:Python 2.7 正式停止支持,不再提供安全更新和改进。Python 社区鼓励用户迁移到 Python 3.x。
- 当前状态
- 截至2024年,Python 3.x 是当前的活跃版本,Python 3.11 和 3.12 已经发布,带来了新的特性和改进。
- 未来展望
- Python 社区持续推动语言的发展,计划中的版本将继续带来性能改进、新特性和对现代编程趋势的支持。
- 社区与生态系统
- Python 拥有一个庞大的社区和丰富的第三方库生态系统,支持广泛的领域,从Web开发、科学计算到机器学习和人工智能。
- 重要人物
- Guido van Rossum:Python 的创始人,被称为“Benevolent Dictator for Life”(终身仁慈独裁者),直到2018年卸任。
1.3 Python特点
- 简洁易读
- 语法简单:Python 的语法设计旨在提高代码的可读性,使得代码更易于理解和维护。
- 缩进:Python 使用缩进来表示代码块,而不是使用花括号
{}
,这使得代码更加整洁。
- 动态类型
- 动态类型:Python 是一种动态类型语言,变量无需事先声明类型即可使用。
- 动态绑定:变量的类型可以在运行时改变。
- 面向对象
- 一切皆对象:在 Python 中,几乎所有的东西都是对象,包括数字、字符串、函数等。
- 类和对象:Python 支持面向对象编程,允许定义类、创建对象、继承和多态。
- 可移植性
- 跨平台:Python 可以在多种操作系统上运行,包括 Windows、macOS 和各种 Linux 发行版。
- 强大的标准库
- 标准库:Python 拥有一个庞大且功能丰富的标准库,涵盖了网络、文件、GUI、数据库等多种领域。
- 易于集成
- 与其他语言集成:Python 可以轻松地调用 C/C++ 代码,也可以被其他语言调用。
- 脚本语言:Python 常被用作脚本语言来快速开发简单的工具或脚本。
- 解释型
- 解释执行:Python 代码在运行时被逐行解释执行,不需要预先编译。
- 动态执行:这使得调试和开发过程更加高效。
- 强大的社区支持
- 开源:Python 是一个开源项目,拥有庞大的开发者社区和丰富的第三方库。
- 文档齐全:Python 有详尽的官方文档和大量的第三方资源。
- 应用广泛
- Web 开发:使用框架如 Django 和 Flask 开发 Web 应用。
- 数据科学:利用 Pandas、NumPy 和 SciPy 等库进行数据分析。
- 机器学习:使用 TensorFlow、PyTorch 和 Scikit-learn 等库进行机器学习和深度学习。
- 自动化脚本:编写自动化脚本来简化日常任务。
- 游戏开发:使用 Pygame 等库开发游戏。
- 强大的第三方库生态系统
- 丰富的库:Python 拥有大量高质量的第三方库,几乎涵盖了所有可能的应用领域。
- 开发效率高
- 快速原型:Python 的简洁性和强大的库支持使得开发原型非常快速。
- 迭代开发:Python 支持敏捷开发和迭代开发方法。
- 可扩展性
- C扩展:可以使用 C 语言编写扩展模块来提高性能。
- 多线程和多进程:Python 支持多线程和多进程编程,尽管全局解释器锁 (GIL) 限制了多线程的并发性能。
- 自动内存管理
- 垃圾回收:Python 自动管理内存,无需手动释放内存。
1.4 Python的应用场景
- Web 开发
- Web 框架:Django 和 Flask 是两个非常流行的 Python Web 框架,用于构建 Web 应用程序和服务。
- API 开发:可以使用 Flask 或 FastAPI 构建 RESTful API 和微服务。
- 数据科学与分析
- 数据处理:Pandas 是一个强大的库,用于数据清洗、转换和分析。
- 统计分析:SciPy 和 Statsmodels 提供了大量的统计工具。
- 数据可视化:Matplotlib 和 Seaborn 可以用于创建图表和图形。
- 机器学习与人工智能
- 机器学习库:Scikit-learn 是一个广泛使用的机器学习库。
- 深度学习框架:TensorFlow 和 PyTorch 用于构建神经网络和深度学习模型。
- 自动化脚本
- 系统管理:编写自动化脚本来执行重复性的任务,如文件备份、系统监控等。
- 网络爬虫:使用 Beautiful Soup 和 Scrapy 等库来抓取网页数据。
- 游戏开发
- 游戏引擎:Pygame 是一个用于开发 2D 游戏的库。
- Unity 插件:可以使用 Python 编写 Unity 的插件和脚本。
- 科学计算
- 数值计算:NumPy 提供高性能的数组运算。
- 科学计算:SciPy 包含用于科学计算的各种工具,如线性代数、优化、信号处理等。
- 桌面应用
- GUI 应用:Tkinter、PyQt 和 Kivy 可以用于开发跨平台的桌面应用程序。
- 网络编程
- Socket 编程:Python 标准库中的 socket 模块用于网络通信。
- 异步编程:使用 asyncio 和 aiohttp 进行异步 I/O 编程。
- 云计算与 DevOps
- 云服务:许多云服务提供商(如 AWS、Azure 和 Google Cloud)支持使用 Python 编写脚本和工具。
- 自动化部署:使用 Ansible、Fabric 和 SaltStack 等工具进行自动化部署和配置管理。
- 教育与教学
- 编程入门:Python 的简单语法使其成为教授编程概念的理想选择。
- 在线课程:许多在线教育平台使用 Python 来创建互动课程和练习。
- 金融与量化交易
- 量化分析:使用 Pandas 和 NumPy 进行数据处理和分析。
- 交易策略:开发算法交易策略和回测系统。
- 生物信息学
- 基因组分析:处理生物序列数据,如 DNA 和 RNA。
- 蛋白质结构预测:使用 BioPython 和其他库进行生物信息学研究。
- 图像处理与计算机视觉
- 图像处理:使用 OpenCV 和 Pillow 进行图像处理。
- 计算机视觉:使用 OpenCV 和 scikit-image 进行特征检测、识别等任务。
- 自然语言处理 (NLP)
- 文本分析:NLTK 和 spaCy 用于分词、语法解析、情感分析等 NLP 任务。
- 机器翻译:使用 TensorFlow 和 PyTorch 构建机器翻译系统。
- 嵌入式系统
- 微控制器:使用 MicroPython 在微控制器上运行 Python 脚本。
- 物联网 (IoT)
- 设备控制:使用 Python 控制物联网设备并通过网络发送数据。
- 智能家居:开发智能家庭设备的控制软件。
- 游戏服务器
- 多人游戏服务器:使用 Python 构建游戏服务器逻辑。
- 软件测试
- 自动化测试:使用 unittest 和 pytest 开发自动化测试脚本。
- 机器人技术
- 机器人控制:使用 ROS (Robot Operating System) 和 Python 控制机器人。
- 区块链技术
- 智能合约:使用 Python 开发智能合约和区块链应用。
1.5 Python的版本
Python 有两个主要版本系列:Python 2.x 和 Python 3.x。每个系列都有多个版本发布。
Python 2.x
- Python 2.0:2000年发布,引入了一些重要的新特性,如列表推导式、垃圾回收机制等。
- Python 2.6:2008年发布,增加了对多线程的支持,并改进了异常处理。
- Python 2.7:2010年发布,这是 Python 2.x 系列的最后一个主要版本,包含了许多改进和修复,并支持 Unicode。
- Python 2.x 的退役:2020年1月1日,Python 2.7 正式停止支持,不再提供安全更新和改进。Python 社区鼓励用户迁移到 Python 3.x。
Python 3.x
- Python 3.0:2008年发布,这是 Python 的一次重大更新,引入了许多改进,包括更好的 Unicode 支持、简化语法和改进的库。
- Python 3.1:2009年发布,引入了新的上下文管理器和语法改进。
- Python 3.2:2011年发布,带来了更好的安全性、性能改进和新特性。
- Python 3.3:2012年发布,引入了新的标准库模块和改进。
- Python 3.4:2014年发布,引入了 asyncio 模块,支持异步 I/O。
- Python 3.5:2015年发布,进一步增强了 asyncio,并引入了新的类型提示功能。
- Python 3.6:2016年发布,引入了 f-strings 和类型注解的新语法。
- Python 3.7:2018年发布,带来了新的数据类(data classes)、异步上下文管理器和其他改进。
- Python 3.8:2019年发布,引入了新的赋值表达式(walrus operator
:=
)和其他新特性。 - Python 3.9:2020年发布,改进了类型提示,增加了新的字符串替换方法,并增强了字典解包等功能。
- Python 3.10:2021年发布,引入了模式匹配(Pattern Matching)和其他新特性。
- Python 3.11:2022年发布,带来了性能提升、改进的错误处理和新的类型检查工具等。
- Python 3.12:预计将于2024年发布,预计将带来新的特性和改进。
第2章 Python环境搭建
2.1 Python软件安装
- 下载 Python
-
访问 Python 官方网站:https://www.python.org/downloads/
-
选择你需要的 Python 版本。通常情况下,建议选择最新的稳定版本,即 Python 3.x(如 Python 3.12)。
- 安装 Python
-
Windows:
- 下载完成后,双击
.exe
文件启动安装程序。 - 在安装界面中勾选 “Add Python to PATH” 选项,以便将 Python 添加到系统路径中。
- 点击 “Install Now” 进行安装。
- 下载完成后,双击
-
macOS:
- 下载完成后,双击
.pkg
文件启动安装程序。 - 按照安装向导的提示完成安装。
- 下载完成后,双击
-
Linux:
-
对于 Debian/Ubuntu 类的系统,可以使用
apt-get
:sudo apt-get update sudo apt-get install python3
-
对于 Fedora 类的系统,可以使用
dnf
:sudo dnf install python3
-
- 验证安装
-
打开命令行或终端。
-
输入
python --version
来查看已安装的 Python 版本。 -
如果安装成功,会显示类似于
Python 3.12.0
的输出。
2.2 编辑器安装
- 下载 PyCharm
-
访问 PyCharm 官方网站:https://www.jetbrains.com/pycharm/download/
-
选择适合你的操作系统的版本。PyCharm 有两种版本:Professional(专业版)和 Community(社区版)。社区版是免费的,而专业版提供了更多高级功能。
-
选择相应的下载链接,下载安装包。
- 安装 PyCharm
-
Windows
- 下载完成后,双击
.exe
文件启动安装程序。- 按照安装向导的提示进行安装。
- 选择安装位置。
- 选择是否创建桌面快捷方式。
- 选择是否启动 PyCharm 后自动创建项目。
- 完成安装后,启动 PyCharm。
- 下载完成后,双击
-
macOS
- 下载完成后,双击
.dmg
文件。 - 将 PyCharm.app 拖拽到 Applications 文件夹。
- 通过 Launchpad 或者 Finder 中的 Applications 文件夹启动 PyCharm。
- 下载完成后,双击
-
Linux
- 下载完成后,解压缩
.tar.gz
文件。 - 打开终端,进入解压后的文件夹。
- 运行
bin/pycharm.sh
来启动 PyCharm。
- 下载完成后,解压缩
第3章 Python基础语法
3.1 第一个Python程序
3.1.1 使用 Python 命令行
-
打开命令提示符 win + R --> cmd enter
-
输入
python
来启动 Python 解释器
>>> print("hello world")
hello world
3.1.2 使用 IPython
IPython 是一个增强的 Python shell,提供了比标准 Python shell 更多的功能,如语法高亮、自动补全等
-
安装 IPython(如果还没有安装的话)
-
在命令行或终端中输入
ipython
来启动 IPython
In [1]: print('hello world')
hello world
3.1.3 使用 PyCharm
- 打开或创建一个 Python 文件
- 在编辑器中输入代码
python 文件名
或编辑器启动
3.2 注释
注释是用来添加说明性文本,帮助其他开发者理解代码的目的和功能
3.2.1 单行注释
单行注释使用 #
符号开始,直到行尾都是注释内容
# 这是一个单行注释
print("hello world") # 这也是一个单行注释
3.2.2 多行注释
Python并没有内置的多行注释符号,但可以使用三个引号 ("""
或 '''
) 来创建一个多行字符串,作为多行注释使用。三个引号通常用于文档字符串(docstrings)
"""
这是一个多行注释,
可以跨越多行,
并且包含任何文本。
"""
print("hello world") # 这里可以继续写代码
注意:文档字符串 (docstrings)
文档字符串是一种特殊的注释形式,通常用于描述模块、函数、类或方法的用途和用法。它们是用三个引号括起来的字符串,位于定义的开头。文档字符串可以被 __doc__
属性访问。
def greet(name):
"""
打印一个友好的问候信息给 name 参数指定的人。
参数:
name (str): 被问候的人的名字。
"""
print(f"Hello, {name}!")
greet.__doc__ # 获取文档字符串
3.3 变量
变量是用来存储数据的标识符。Python是一种动态类型的语言,不需要在声明变量时指定其类型。当你给一个变量赋值时,它的类型就确定了。
3.3.1 变量的赋值
可以直接将值赋给变量
age = 25
height = 1.75
name = "buddha"
is_student = True
3.3.2 变量的命名
-
合法字符:
- 变量名只能包含字母、数字和下划线。
- 变量名不能以数字开头。
-
大小写敏感:
- Python中的变量名是区分大小写的。例如,
Variable
,variable
, 和VARIABLE
是三个不同的变量。
- Python中的变量名是区分大小写的。例如,
-
避免使用保留字:
- 不要使用Python的关键字(如
if
,for
,while
,class
,def
等)作为变量名。
- 不要使用Python的关键字(如
-
有意义的名字:
- 使用描述性的变量名可以使代码更容易理解。例如,使用
total_sales
而不是ts
。
- 使用描述性的变量名可以使代码更容易理解。例如,使用
-
避免使用单个字母:
- 尽管使用单个字母作为变量名是合法的,但通常最好使用更具描述性的名称,除非在特定情况下单个字母足够清楚(例如循环索引变量
i
或j
)。
- 尽管使用单个字母作为变量名是合法的,但通常最好使用更具描述性的名称,除非在特定情况下单个字母足够清楚(例如循环索引变量
-
避免使用内置函数名:
- 避免使用Python内置函数名作为变量名,如
list
,str
,min
,max
等。
- 避免使用Python内置函数名作为变量名,如
-
驼峰命名法与下划线命名法:
- 在Python中,推荐使用下划线分隔单词(snake_case),而不是驼峰式命名法(CamelCase)。例如,使用
this_is_a_variable
而不是thisIsAVariable
。- 对于类名,则推荐使用驼峰式命名法。
- 在Python中,推荐使用下划线分隔单词(snake_case),而不是驼峰式命名法(CamelCase)。例如,使用
-
全局变量和局部变量:
- 全局变量通常建议使用大写字母加下划线(ALL_CAPS_WITH_UNDERSCORES),例如
MAX_CONNECTIONS
。 - 局部变量和函数参数通常使用小写字母加下划线。
- 全局变量通常建议使用大写字母加下划线(ALL_CAPS_WITH_UNDERSCORES),例如
-
特殊变量名:
- Python有一些特殊变量名,如
__name__
,__doc__
,__package__
等,这些应该仅用于它们预定的目的。
- Python有一些特殊变量名,如
-
PEP 8 标准:
- Python有一个官方的风格指南 PEP 8,它提供了一系列关于变量命名以及其他编码风格的最佳实践。
示例:
# 好的变量命名示例
number_of_students = 20
average_score = 75.5
is_valid = True
# 不好的变量命名示例
a = 20
b = 75.5
c = True
3.4 关键字
关键字是指在语言本身具有特殊意义的保留字。这些关键字不能用作变量名、函数名或其他标识符的名称。Python有一套固定的关键字集,这些关键字用于定义语法结构,比如控制流语句、异常处理、类定义等。
3.4.1 Python3.x关键字
In [1]: import keyword
In [2]: keyword.kwlist
Out[2]:
['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程序中都有特定的用途。例如:
if
: 用于条件判断。for
: 用于迭代序列。def
: 用于定义函数。class
: 用于定义类。import
: 用于导入模块或包。try
: 用于异常处理。return
: 用于从函数返回值。pass
: 用于创建一个空的代码块。raise
: 用于引发异常。
示例:
# 使用 def 定义函数
def greet(name):
if name == "buddha":
return "hello buddha"
else:
return "hello world"
3.5 基本数据类型
在 Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象的类型。
-
整数 (int)
- 整数是没有小数部分的数字,可以是正数也可以是负数。
age = 25
-
浮点数 (float)
- 浮点数是有小数部分的数字,同样可以是正数也可以是负数。
height = 1.75
-
复数 (complex)
- 复数由实部和虚部组成,虚部以
j
或J
结尾。
z = 3 + 5j
- 复数由实部和虚部组成,虚部以
-
布尔值 (bool)
- 布尔值表示逻辑值,只有两个可能的值:
True
和False
。
is_student = True
- 布尔值表示逻辑值,只有两个可能的值:
-
字符串 (str)
- 字符串是由零个或多个字符组成的序列,可以用单引号
'
或双引号"
来包围。
greeting = "Hello, world!"
- 字符串是由零个或多个字符组成的序列,可以用单引号
-
列表 (list)
- 列表是有序的元素集合,可以包含不同类型的数据,并且支持修改。
numbers = [1, 2, 3, 4, 5]
-
元组 (tuple)
- 元组也是有序的元素集合,但一旦创建就不能修改。
point = (10, 20)
-
字典 (dict)
- 字典是键值对的集合,其中每个键都是唯一的。
person = {"name": "Bob", "age": 30}
-
集合 (set)
- 集合是无序的不重复元素的集合。
unique_numbers = {1, 2, 3, 4, 5}
-
None
None
类型只有一个值None
,通常用来表示一个没有值的对象。
result = None
3.6 数据类型转换
在Python中,数据类型转换可以分为两种主要形式:强制类型转换(也称为显式类型转换)和自动类型转换(也称为隐式类型转换)
3.6.1 强制类型转换
通过调用特定的数据类型转换函数来完成的,如int()
, float()
, str()
, bool()
等
# 显式转换示例
x = 10 # x 是整数
y = 10.5 # y 是浮点数
s = "123" # s 是字符串
# 转换为浮点数
x_float = float(x)
print(x_float) # 输出: 10.0
# 转换为整数
y_int = int(y)
print(y_int) # 输出: 10
# 转换为整数
s_int = int(s)
print(s_int) # 输出: 123
# 转换为字符串
x_str = str(x)
print(x_str) # 输出: '10'
# 转换为布尔值
x_bool = bool(x)
print(x_bool) # 输出: True
3.6.2 自动类型转换
指Python在某些操作中自动进行的数据类型转换。这种转换主要发生在算术运算中,例如当混合了整数和浮点数的操作时。
# 隐式转换示例
a = 10 # a 是整数
b = 20.5 # b 是浮点数
# 混合类型的加法
result = a + b
print(result) # 输出: 30.5
# 在比较运算中,字符串与数字不会发生隐式转换
# 下面这行代码会引发错误
# c = "100" + 200 # TypeError: can only concatenate str (not "int") to str
布尔值可以被隐式转换为整数。
True
被视为1
,而False
被视为0
3.7 运算符
运算符是在编程语言中用来执行特定类型的操作的符号
3.7.1 算术运算符
+
加法-
减法*
乘法/
除法(结果为浮点数)//
整数除法(结果为整数,向下取整)%
取模(得到除法的余数)**
幂运算(指数)
a = 10
b = 3
print(a + b) # 输出 13
print(a - b) # 输出 7
print(a * b) # 输出 30
print(a / b) # 输出 3.3333333333333335
print(a // b) # 输出 3
print(a % b) # 输出 1
print(a ** b) # 输出 1000
3.7.2 比较运算符
==
等于!=
不等于<
小于>
大于<=
小于或等于>=
大于或等于
x = 5
y = 10
print(x == y) # 输出 False
print(x != y) # 输出 True
print(x < y) # 输出 True
print(x > y) # 输出 False
print(x <= y) # 输出 True
print(x >= y) # 输出 False
3.7.3 赋值运算符
=
赋值+=
加法赋值-=
减法赋值*=
乘法赋值/=
除法赋值//=
整数除法赋值%=
取模赋值**=
幂运算赋值&=
按位与赋值|=
按位或赋值^=
按位异或赋值<<=
左移位赋值>>=
右移位赋值
# = 简单赋值
x = 10
print(x) # 输出: 10
# 加法赋值 +=
x = 5
x += 3 # 等同于 x = x + 3
print(x) # 输出: 8
# 减法赋值 -=
x = 10
x -= 4 # 等同于 x = x - 4
print(x) # 输出: 6
# 乘法赋值 *=
x = 2
x *= 5 # 等同于 x = x * 5
print(x) # 输出: 10
# 除法赋值 /=
x = 15
x /= 3 # 等同于 x = x / 3
print(x) # 输出: 5.0
# 整数除法赋值 //=
x = 15
x //= 3 # 等同于 x = x // 3
print(x) # 输出: 5
# 取模赋值 %=
x = 10
x %= 3 # 等同于 x = x % 3
print(x) # 输出: 1
# 幂运算赋值 **=
x = 2
x **= 3 # 等同于 x = x ** 3
print(x) # 输出: 8
# 按位与赋值 &=
x = 5 # 二进制: 0101
x &= 3 # 二进制: 0011 (等同于 x = x & 3)
print(x) # 输出: 1 (二进制: 0001)
# 按位或赋值 |=
x = 5 # 二进制: 0101
x |= 3 # 二进制: 0011 (等同于 x = x | 3)
print(x) # 输出: 7 (二进制: 0111)
# 按位异或赋值 ^=
x = 5 # 二进制: 0101
x ^= 3 # 二进制: 0011 (等同于 x = x ^ 3)
print(x) # 输出: 6 (二进制: 0110)
# 左移位赋值 <<=
x = 5 # 二进制: 0101
x <<= 1 # 等同于 x = x << 1
print(x) # 输出: 10 (二进制: 1010)
# 右移位赋值 >>=
x = 10 # 二进制: 1010
x >>= 1 # 等同于 x = x >> 1
print(x) # 输出: 5 (二进制: 0101)
3.7.4 逻辑运算符
and
逻辑与or
逻辑或not
逻辑非
bool1 = True
bool2 = False
print(bool1 and bool2) # 输出 False
print(bool1 or bool2) # 输出 True
print(not bool1) # 输出 False
3.7.5 成员运算符
in
判断元素是否在序列中not in
判断元素是否不在序列中
list1 = [1, 2, 3, 4, 5]
print(3 in list1) # 输出 True
print(6 not in list1) # 输出 True
3.7.6 身份运算符
is
判断两个变量是否指向同一个对象is not
判断两个变量是否不指向同一个对象
list1 = [1, 2, 3, 4, 5]
list2 = list1
print(list1 is list2) # 输出 True
print(list1 is not list2) # 输出 False
3.7.7 位运算符
~
按位取反&
按位与|
按位或^
按位异或<<
左移>>
右移
num1 = 5 # 二进制: 0101
num2 = 3 # 二进制: 0011
print(num1 & num2) # 输出 1 (0001)
print(num1 | num2) # 输出 7 (0111)
print(num1 ^ num2) # 输出 6 (0110)
print(~num1) # 输出 -6
print(num1 << 1) # 输出 10 (1010)
print(num1 >> 1) # 输出 2 (0010)
3.8 type() 和 input()函数
3.8.1 type() 函数
type()
函数用于返回对象的数据类型。
a = 5
b = "Hello"
c = [1, 2, 3]
print(type(a)) # 输出: <class 'int'>
print(type(b)) # 输出: <class 'str'>
print(type(c)) # 输出: <class 'list'>
3.8.2 input() 函数
input()
函数用于从用户那里获取输入。它总是返回一个字符串。如果需要其他类型的值,需要强制类型转换
name = input("请输入你的名字: ")
print("你好,", name)
# 获取整数输入
age = int(input("请输入你的年龄: "))
print("你的年龄是:", age)
# 获取浮点数输入
height = float(input("请输入你的身高(米): "))
print("你的身高是:", height, "米")
3.9 字符串运算
3.9.1 拼接字符串
使用 +
运算符来拼接两个字符串
s1 = "Hello"
s2 = "World"
result = s1 + s2
print(result) # 输出: HelloWorld
3.9.2 重复字符串
使用 *
运算符来重复字符串
repeat = "*" * 3
print(repeat) # 输出: ***
3.10 格式化输出
在 Python 中,格式化输出是指将变量的值插入到字符串中,生成易于阅读的输出。
3.10.1 使用 %
运算符
这是 Python 2 中常用的字符串格式化方法,但在 Python 3 中仍然可用。
name = "曹操"
age = 38
# 使用 %s 表示字符串,%d 表示整数
output = "My name is %s and I am %d years old." % (name, age)
print(output) # 输出: My name is 曹操 and I am 38 years old.
3.10.2 使用 str.format()
str.format()
方法是 Python 2.6 及以上版本引入的一种更灵活的字符串格式化方法。
name = "曹操"
age = 38
# 使用 {} 占位符,并通过 format 方法传入参数,默认按顺序匹配
output = "My name is {} and I am {} years old.".format(name, age)
print(output) # 输出: My name is 曹操 and I am 38 years old.
# 指定占位符的位置,使用索引匹配
output = "My name is {0} and I am {1} years old.".format(name, age)
print(output) # 输出: My name is 曹操 and I am 38 years old.
# 使用关键字参数,使用关键字匹配
output = "My name is {name} and I am {age} years old.".format(name=name, age=age)
print(output) # 输出: My name is 曹操 and I am 38 years old.
3.10.3 使用 f-string (f-strings)
从 Python 3.6 开始,引入了 f-string,这是一种更为简洁和直观的格式化字符串的方法。
name = "曹操"
age = 38
# 使用 f-string
output = f"My name is {name} and I am {age} years old."
print(output) # 输出: My name is 曹操 and I am 38 years old.
# 更复杂的表达式
output = f"My name is {name} and I am {age * 2} years old next year."
print(output) # 输出: My name is 曹操 and I am 76 years old next year.
3.10.4 使用 str()
和字符串拼接
虽然不是真正的格式化,但可以使用 str()
函数将其他类型的值转换为字符串,然后使用 +
进行拼接。
name = "曹操"
age = 38
output = "My name is " + name + " and I am " + str(age) + " years old."
print(output) # 输出: My name is 曹操 and I am 38 years old.
3.10.5 格式符号
用于指定变量类型和格式化样式的占位符。格式符号主要用于 %
运算符和 str.format()
方法中。
使用
%
运算符
%s
- 字符串 (string)%d
- 整数 (decimal integer)%f
- 浮点数 (floating point)%.nf
- 浮点数,其中n
是小数点后的位数%e
或%E
- 科学记数法 (exponential notation)%g
或%G
- 自动选择%f
或%e
中较短的一个%c
- 字符 (character)%r
- 原始数据 (raw data) 或 repr() 的输出
age = 38
height = 1.757
name = "曹操"
# 使用 % 运算符
print("Name: %s, Age: %d, Height: %.2f" % (name, age, height))
# 使用 str.format()
print("Name: {}, Age: {}, Height: {:.2f}".format(name, age, height))
# 使用 f-string
print(f"Name: {name}, Age: {age}, Height: {height:.2f}")
第4章 基本控制结构
基本控制结构是编写任何程序的基础。基本控制结构包括顺序结构、选择结构和循环结构。
4.1 顺序结构
顺序结构是最简单的控制结构,按照代码出现的顺序依次执行。
print("第一步")
print("第二步")
print("第三步")
4.2 选择结构
选择结构,也称为条件分支或分支结构。根据不同的条件执行不同的代码块。Python 中的选择结构主要包括 if
语句、if-else
语句以及 if-elif-else
语句。
4.2.1 if 语句
if
语句用于基于一个条件执行一段代码。如果条件为真(True),则执行该段代码;否则跳过。
num = 5
if num > 3:
print("num 大于 3")
4.2.2 if-else 语句
if-else
语句用于基于一个条件执行两段不同的代码。如果条件为真,则执行 if
后面的代码块;否则执行 else
后面的代码块。
age = 15
if age >= 18:
print("已成年")
else:
print("未成年")
4.2.3 if-elif-else 语句
if-elif-else
语句用于基于多个条件执行不同的代码块。程序会从上到下检查每个条件,当遇到第一个为真的条件时,执行对应的代码块,并且不再检查后面的条件。
score = 75
if score >= 90:
print("优秀")
elif score >= 80:
print("良好")
elif score >= 60:
print("及格")
else:
print("不及格")
4.2.4 选择结构的嵌套
在一个 if
、if-else
或 if-elif-else
结构内部,可以包含另一个完整的选择结构。
score = 85
if score >= 90:
print("优秀")
elif score >= 80:
if score < 85:
print("良好但未达到 85 分")
else:
print("良好且达到 85 分")
elif score >= 70:
print("中等")
else:
print("较差")
注意:选择结构的嵌套可以处理更加复杂的条件逻辑,使程序能够根据多个层次的条件做出准确的决策。但过度嵌套会导致代码的可读性降低,实际编程中应尽量保持代码结构清晰。
4.3 循环结构
循环结构允许重复执行一段代码,直到满足某个条件为止。主要分为 for
循环和 while
循环。
4.3.1 for循环
for
循环通常用于遍历一个可迭代对象(如列表、元组、字符串等)
# 遍历列表
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# 遍历字符串
for char in "hello":
print(char)
# 使用 range() 函数指定循环次数
for i in range(5): # 相当于 for i in [0, 1, 2, 3, 4]
print(i)
4.3.2 while循环
while
循环只要指定的条件为真,就会一直执行循环体中的代码
count = 0
while count < 5:
print(count)
count += 1
4.3.3 break关键字
break
用于立即终止当前所在的循环结构,无论循环条件是否仍然为真。
for i in range(10):
if i == 5:
break
print(i)
4.3.4 continue关键字
continue
用于跳过当前循环中的剩余语句,直接开始下一次循环。
for i in range(10):
if i % 2 == 0:
continue
print(i)
for、while完整结构
for 临时变量 in 变量:
执行True代码
else:
执行False代码
while 条件:
执行True代码
else:
执行条件为False代码
第5章 函数
5.1 定义与调用
函数的作用:能够将复杂的程序逻辑分解为可重复使用的模块。
业务→业务逻辑→程序逻辑
语法:
# 定义一个函数
def 函数名(参数列表):
"""
这个函数的功能是实现xxx功能
"""
函数体
# 调用函数
函数名(参数列表)
示例:
# 定义一个函数
def hello():
"""
这个函数的功能是实现输出hello,world功能
"""
print("HelloWorld")
# 调用函数
hello()
5.2 函数名
命名规则
1、可以由字母、数字和下划线组成
2、不能以数字开头
3、不能是 Python 中的关键字(如 if
、for
、while
等)
合法函数名示例
def my_function():
pass
def add_numbers():
pass
def calculate_sum():
pass
不合法函数名示例
# 以数字开头
def 123function():
pass
# 是关键字
def if():
pass
函数最佳命名规则
1、使用小写字母和下划线,函数名应全部使用小写字母,并使用下划线 (_
) 分隔单词。例如,add_numbers
2、简洁但具有描述性,函数名应该尽可能简短,但也要足够描述其功能。例如,get_total
比 gt
更好
3、使用动词,函数名通常以动词开头,因为它表示一个动作。例如,read_file
, send_email
4、使用名词,如果函数用于获取某些信息,可以使用名词。例如,get_list
, fetch_data
5、使用前缀或后缀,使用前缀或后缀可以帮助区分不同类型的函数。例如,is_valid
表示一个布尔检查函数,get_
通常用于获取信息
6、避免使用数字,尽量不要在函数名中使用数字,除非它们有特殊意义。例如,process_data_v2
可能表示这是数据处理函数的第二个版本
最佳函数命名示例
def add_numbers():
pass
def get_total():
pass
def read_file():
pass
def send_email():
pass
def get_list():
pass
def fetch_data():
pass
def is_valid():
pass
def process_data_v2():
pass
5.3 函数参数
在 Python 函数中,函数可以没有参数,也可以有参数。如果有参数,函数参数是用来传递数据给函数的变量。根据不同的需求,Python 支持多种类型的参数,包括位置参数、关键字参数、默认值参数、不定长参数等。
5.3.1 位置参数
位置参数是按照顺序来传递给函数的。
def multiply(x, y):
print(x * y)
multiply(3, 5) # 3 和 5 是位置参数
5.3.2 关键字参数
关键字参数允许你在调用函数时通过参数名指定参数值,这样就不必关心参数的实际位置了。关键字参数可以在任何位置使用,并且可以与位置参数混合使用。
def multiply(x, y):
print(x * y)
multiply(x=3, y=5) # 使用关键字参数
multiply(3, y=5) # 混合使用位置参数和关键字参数
当位置参数和关键字参数混合使用时,位置参数必须出现在关键字参数之前
5.3.3 默认值参数
默认值参数是在定义函数时为参数指定一个默认值。如果调用函数时没有提供这个参数的值,那么就会使用默认值。
def multiply(x, y=5):
print(x * y)
multiply(3, 6)
multiply(3)
multiply(x=3, y=6)
multiply(x=3)
5.3.4 不定长参数
不定长参数允许函数接受不定数量的位置参数或关键字参数。
*不定长位置参数 (args)
当参数列表前面加上星号 (*) 时,可以接收任意数量的位置参数。
def add_numbers(*args):
numbers_sum = 0
for i in args:
numbers_sum += i
print(numbers_sum)
add_numbers(1, 2)
add_numbers(1, 2, 3)
*不定长关键字参数(*kwargs)
当参数列表前面加上两个星号 (**) 时,可以接收任意数量的关键字参数。
def print_message(**kwargs):
for key, value in kwargs.items():
print(key + "=" + str(value))
print_message(name="buddha", age=18, height=1.75)
print("*" * 20)
print_message(name="buddha", age=18)
5.3.5 参数组合
一个函数的参数可以有位置参数、默认值参数、不定长位置参数、不定长关键字参数的组合。如果有参数组合,其函数定义时,参数从左到右的顺序是:位置参数、默认值参数、不定长位置参数、不定长关键字参数。
def show(name, height=1.80, *args, **kwargs):
print(f'{name},{height}')
for i in args:
print(i)
for key, value in kwargs.items():
print(f'{key}-{value}')
show("buddha", 1, 2, says="hello,world")
5.4 函数返回值
1、返回值,就是函数执行完毕,返回给调用者的结果。如果函数没有显式地返回任何值,则通常返回None
2、函数需要显示地返回返回值,用关键字return
3、函数内可以有多个return,碰到第一个return关键字就结束了函数的调用
4、在Python中,可以返回一个值,或用元组的方式返回多个值
返回一个值的示例
# 函数返回一个值
def add_numbers(a, b):
return a + b
sum_numbers = add_numbers(1,2)
print(sum_numbers) # 3
返回多个值的示例
# 函数返回元组,元组中含有多个值
def do_numbers(a, b):
return a + b, a - b
numbers = do_numbers(1, 2)
print(numbers[0], numbers[1])
5.5 作用域
作用域是指变量在程序中的可见性范围。
1、局部作用域:
- 在函数内部定义的变量具有局部作用域,只能在该函数内部访问。
- 当函数调用结束时,局部变量的作用域也随之结束。
2、全局作用域:
- 在函数外部定义的变量具有全局作用域,可以在整个程序中访问。
- 全局变量在程序执行开始时创建,在程序结束时销毁。
3、封闭作用域:
- 当一个函数内部定义了另一个函数时,内部函数可以访问外部函数的变量(局部变量)。
- 外部函数的变量(局部变量)对于内部函数来说处于封闭作用域。
4、内置作用域:
- Python 提供了一系列内置函数和常量,如
print()
、type()
、input()
等,它们在所有作用域中都是可用的。
内层使用外层变量
# 全局变量
x = "全局变量"
def outer_function():
y = "外部函数的局部变量" # 封闭作用域
def inner_function():
z = "内部函数的局部变量" # 局部作用域
print(z)
print(y) # 访问封闭作用域中的变量
print(x) # 访问全局作用域中的变量
inner_function()
outer_function()
# 下面这行会抛出 NameError,因为 y 是封闭作用域中的变量
# print(y)
# 下面这行会打印全局变量 x 的值
print(x)
原则是:内层可以使用外层,外层使用不了内层
内层修改外层变量
函数内部修改全局变量,该全局变量需要在函数内部用global
关键字声明
内层函数修改外层函数的变量,该外层函数的局部变量在内层函数中用nonlocal
关键字声明
外层不直接使用内层的变量,这样子破坏了函数的封装性
5.6 函数的嵌套
在 Python 中,函数的嵌套是指在一个函数内部定义另一个函数。这样的设计可以用来创建更加复杂的功能组合,同时保持代码的整洁和模块化。
简单嵌套
def outer():
print("这是外部函数被调用")
def inner():
print("这是内部函数被调用")
inner()
outer()
返回内部函数
def outer_function():
print("外包函数...")
def inner_function():
return "内部函数..."
return inner_function # 返回内部函数的引用
inner = outer_function() # 获取内部函数的引用
print(inner()) # 调用内部函数
嵌套的应用
def factorial(n):
"""
实现阶乘的功能,内部函数是递归函数
"""
def recursive_factorial(n):
if n == 0:
return 1
else:
return n * recursive_factorial(n - 1)
return recursive_factorial(n)
print(factorial(3)) # 输出 6
5.7 匿名函数
在 Python 中,匿名函数也称为 lambda 函数。它是一种简洁的方式来定义一个小型的、一次性使用的函数。
匿名函数的语法:
lambda 参数: 表达式
说明:
- 参数:可以是一个或多个参数,多个参数之间用逗号分隔
- 表达式:是一个单一的表达式,表达式的结果作为函数的结果返回
示例:
# 示例 1:计算两个数的和
add = lambda x, y: x + y
print(add(3, 5))
# 示例 2:对一个数进行平方运算
square = lambda x: x ** 2
print(square(4))
# 示例 3:判断一个数是否为偶数
is_even = lambda x: x % 2 == 0
print(is_even(6))
5.8 文档字符串
文档字符串是放在函数、类或模块的第一个逻辑行上的字符串,用于描述该对象的用途、行为或用法。__doc__
属性可以用来获取这些文档字符串的内容。
示例:
def function(*args):
"""函数的文档字符串
:param args: 参数说明
:return: 函数返回值说明
"""
pass
# 通过 函数名.__doc__ 获取文档字符串
print(function.__doc__)
# 通过 help(函数名) 获取文档字符串
help(function)
5.9 内置函数
Python 中提供了大量的内置函数,这些函数可以直接在程序中使用。
5.9.1 获取内置函数帮助信息
方式一:官方手册地址:https://docs.python.org/3/library/functions.html
方式二:函数名.__doc__
方式三:help(函数名)
…
5.9.2 常见内置函数示例
# print() 用于输出文本或变量的值
print("Hello, World!")
num = 5
print(num)
# len() 返回对象(如字符串、列表、元组等)的长度
str = "Python"
print(len(str))
list = [1, 2, 3, 4, 5]
print(len(list))
# range() 用于生成一个整数序列
for i in range(5):
print(i)
# sum() 计算可迭代对象(如列表、元组等)中所有元素的总和
numbers = [1, 2, 3, 4, 5]
print(sum(numbers))
# max() 和 min() 分别返回可迭代对象中的最大值和最小值
numbers = [5, 2, 8, 1, 9]
print(max(numbers))
print(min(numbers))
# abs() 返回一个数的绝对值
num = -5
print(abs(num))
# type() 返回对象的类型
num = 5
print(type(num))
# input() 用于获取用户的输入
name = input("请输入您的名字:")
print(f"您好,{name}!")
第6章 面向对象
6.1 面向过程和面向对象
在 Python 中,你可以使用两种主要的编程风格来编写代码:面向过程(Procedural Programming)和面向对象(Object-Oriented Programming, OOP)。
6.1.1 面向过程编程
面向过程编程是一种结构化的编程范式,它将程序视为一系列的过程或者函数。
-
**强调过程和步骤:**面向过程编程关注解决问题的具体步骤和流程,将问题分解为一系列的函数或过程,按照顺序依次执行来完成任务。
-
**数据与操作分离:**数据和对数据的操作通常是分开定义的,数据在各个函数之间传递。
-
**以函数为基本单元:**程序主要由一个个函数组成,函数负责完成特定的任务。
-
**注重流程控制:**通过顺序、选择(如
if-else
语句)和循环(如for
、while
语句)等控制结构来决定程序的执行流程。 -
**程序的可读性依赖于流程的清晰性:**由于重点在于步骤的执行顺序,代码的可读性很大程度上取决于流程是否容易理解。
-
**较难维护和扩展:**当程序规模较大或需求发生变化时,修改和扩展代码可能会比较困难,因为一个函数的修改可能会影响到其他依赖它的部分。
-
**不利于代码复用:**虽然函数可以在一定程度上实现代码复用,但相对面向对象编程来说,复用的程度和灵活性较低。
6.1.2 面向对象编程
面向对象编程是一种编程范式,它将程序设计成由对象(Object)组成的世界。对象包含数据(属性)和对这些数据的操作(方法)。面向对象编程强调的是数据的封装、继承和多态等特性。
-
**封装性(Encapsulation):**将对象的属性(数据)和方法(行为)封装在一起,形成一个独立的单元。外部无法直接访问对象的内部实现细节,只能通过定义好的公共接口(方法)来与对象进行交互。
-
**继承性(Inheritance):**允许创建新的类(子类),这些子类可以继承现有类(父类)的属性和方法,并可以在此基础上添加新的属性和方法,或者修改父类的方法。
-
**多态性(Polymorphism):**不同的对象可以对相同的消息(方法调用)做出不同的响应。这意味着可以使用相同的方法名在不同的类中实现不同的功能。
-
**抽象性(Abstraction):**提取出对象的共同特征和行为,形成类的定义,忽略具体的实现细节。
-
**对象的独立性和自治性:**每个对象都是独立的实体,具有自己的状态和行为,并且能够独立地处理自身的数据和逻辑。
-
**可维护性和可扩展性:**由于封装、继承和多态等特性,使得代码更容易维护和扩展。新的功能可以通过添加新的类或修改现有类来实现,而不会影响到不相关的部分。
-
**代码复用性高:**通过继承和组合等方式,可以重复利用已有的代码和设计,减少重复开发。
6.2 类和对象
6.2.1 类 (Class)
类是对象的模板或蓝图,它定义了一组相关的属性和方法。类可以看作是一种自定义的数据类型,定义了一组具有相同属性和方法的对象的蓝图或模板,用于描述具有相同属性和行为的对象。
6.2.2 类的定义
在 Python 中,定义一个类使用 class
关键字:
class Person:
# 属性
# 方法
说明:
-
属性:属性是类中的变量,用于存储对象的状态信息。属性可以是任何数据类型,如整数、字符串等。
-
方法:方法是类中的函数,用于描述对象的行为。方法通常定义了如何操作类的属性。
class Person:
name = '小明'
age = 6
def eat(self):
print(f'{self.name}在吃饭饭...')
类名采用驼峰命名规范
6.2.3 对象 (Object)
对象是类的具体实例。通过类创建对象的过程称为实例化。
对象具有类所定义的属性和方法,可以对其进行操作和使用。
6.2.4 创建对象
通过类的实例化,创建了该类的一个对象
p = Person()
6.2.5 访问属性和方法
在外部,访问属性和方法,通过对象名.属性名
、 对象名.方法名()
# 访问属性
p.name
# 访问方法
p.eat()
在内部,访问属性和方法,通过self.属性名
、 self.方法名()
# 访问属性
self.name
# 访问方法
self.eat()
6.2.6 构造方法
类实例化对象的时候,会触发一个内置的方法就是__init__
,叫构造方法,也叫初始化方法;在特定的情况下由解释器自动调用;常用来实例化的同时,完成对象的初始化设置
class Person:
name = '小明'
age = 6
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(f'{self.name}在吃饭饭...')
p = Person("小王", 8)
print(p.name)
p.eat()
6.3 魔术方法
在Python面向对象中,方法名类似__xxx___
,在特定情况下由解释器自动调用,称为魔术方法。
6.3.1 __init__(self,...)
方法
- 触发时机:对象被初始化的时候
- 作用:完成对象初始化配置
class Person:
def __init__(self, name):
self.name = name
p = Person("小王")
print(p.name)
6.3.2 __str__(self)
方法
- 触发时机:打印对象的时候
- 作用:执行
__str__()
方法里的代码,能够返回一个字符串
class Person:
name = "小明"
age = 18
def __str__(self):
return f"该实例化对象:名字叫{self.name}, 年龄是{self.age}岁!"
p = Person()
print(p)
6.3.3 __del__(self)
方法
- 触发时机:当一个对象被垃圾回收或显式删除时
- 作用:主要用于执行一些清理工作,例如关闭文件、释放资源等。
注意事项:
- 不确定性:Python 的垃圾回收机制并不保证在程序结束时立即释放所有对象。因此,
__del__()
方法的调用时机可能是不确定的。 - 避免引发异常:在
__del__()
方法中引发异常可能会导致程序崩溃,因为 Python 无法处理这些异常。尽量避免在__del__()
中执行可能引发异常的操作,或者确保能够妥善处理这些异常。 - 显式删除:可以使用
del
语句显式删除对象,这会触发__del__()
方法的调用。
class Person:
def __del__(self):
print("触发__del__()方法")
p = Person()
# 显示删除对象
del p
6.4 面向对象三大特征
6.4.1 封装
封装,指的是隐藏对象的内部状态和实现细节,只暴露必要的接口,不能对内部数据直接访问,只能通过特定的方法操作。助于保护数据的完整性、安全性。
公有属性和方法
属性和方法可以被类的外部直接访问。在Python中,默认情况下,类的所有属性和方法都是公有的。
class Person:
def __init__(self, name, age):
self.name = name # 公有属性
self.age = age # 公有属性
def get_name(self):
return self.name # 公有方法
# 外部直接使用公有属性和方法
p = Person("buddha", 18)
print(p.name) # 输出: buddha
print(p.get_name()) # 输出: buddha
私有属性和方法
属性和方法不可以被类的外部直接访问。在 Python 中,可以在属性名或方法名前加上**单下划线_
或双下划线 __
**来定义私有属性和方法。
class Person:
def __init__(self, name, age):
self.__name = name # 私有属性
self.__age = age # 私有属性
def __display_info(self):
return f"Name: {self.__name}, Age: {self.__age}" # 私有方法
# 外部无法直接访问私有属性和方法
p = Person("buddha", 18)
# print(p.__name) # 这会引发错误,因为__name是私有属性
# print(p.__display_info()) # 这会引发错误,因为__display_info()是私有方法
单下划线或双下划线是Python社区遵循的一种约定,在 Python 中,并没有严格意义上的私有属性或方法。
class Person:
def __init__(self, name, age):
self.__name = name # 私有属性
self.__age = age # 私有属性
def __display_info(self):
return f"Name: {self.__name}, Age: {self.__age}" # 私有方法
# 外部依然可以直接访问私有属性和方法
p = Person("buddha", 18)
print(p._Person__name)
print(p._Person__display_info())
双下划线导致名称改编,通过
_类名__属性名
或_类名__方法名
访问
class Person:
def __init__(self, name, age):
self._name = name # 私有属性
self._age = age # 私有属性
def _display_info(self):
return f"Name: {self._name}, Age: {self._age}" # 私有方法
# 外部依然可以直接访问私有属性和方法
p = Person("buddha", 18)
print(p._name)
print(p._display_info())
class Person:
def __init__(self, name, age):
self._name = name # 私有属性
self._age = age # 私有属性
def _display_info(self):
return f"Name: {self._name}, Age: {self._age}" # 私有方法
# 外部依然可以直接访问私有属性和方法
p = Person("buddha", 18)
print(p._name)
print(p._display_info())
6.4.2 继承
在 Python 中,继承是一种创建新类的方式,新类可以从一个或多个已有的类中继承属性和方法,这个新类被称为子类,而被继承的类称为父类(也可称为基类、超类)。子类可以继承父类的所有公有属性和方法,但不能继承私有属性和方法。
单继承
单继承是指一个子类只继承一个父类。
语法:
class 子类名(父类名):
# 子类的属性和方法
示例:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "汪汪汪!我是{}".format(self.name)
多继承
多继承是指一个子类同时继承多个父类
语法:
class 子类名(父类名 1, 父类名 2,...):
# 子类的属性和方法
示例:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
class Flyable:
def fly(self):
return "我可以飞!"
class Bird(Animal, Flyable):
def speak(self):
return "叽叽叽!我是{}".format(self.name)
当多个父类中存在同名方法时,Python 会按照特定的顺序来确定调用哪个父类的方法。这个顺序是通过方法解析顺序(Method Resolution Order,MRO)来确定的
print(子类名.__mro__)
方法重写
子类中重新定义父类中的方法。当子类继承父类时,可能会发现父类中的某些方法不能完全满足子类的需求。这时,子类可以重写父类的方法,以实现更适合子类的行为。
class Animal:
def make_sound(self):
print("动物发出声音")
class Dog(Animal):
def make_sound(self):
print("汪汪汪!")
子类重写的方法可以访问父类中被重写的方法,使用
super()
函数来调用父类的方法。
class Animal:
def make_sound(self):
print("动物发出声音")
class Dog(Animal):
def make_sound(self):
super().make_sound()
print("汪汪汪!")
当需要在子类中,对父类的构造方法进行重写时,必须在子类的构造方法中,显式地调用父类的构造方法,否则父类的初始化逻辑将不会被执行,可能导致继承自父类的属性无法正确初始化。
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
self.breed = breed
super().__init__(name)
属性遮蔽
在子类中定义了与父类同名的属性,从而遮蔽了父类中的属性。
class Parent:
attr = "Parent's attribute"
class Child(Parent):
attr = "Child's attribute"
c = Child()
print(c.attr) # 输出:Child's attribute
6.4.3 多态
指允许不同类的对象对同一消息作出响应的能力。
方法重写
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "汪汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵喵!"
def animal_speak(animal):
print(animal.speak())
dog = Dog()
cat = Cat()
animal_speak(dog) # 输出: 汪汪汪!
animal_speak(cat) # 输出: 喵喵喵!
鸭子类型
不关注对象的类型,而是关注对象是否具有特定的方法和属性。
class Duck:
def quack(self):
print("嘎嘎嘎!")
class Person:
def quack(self):
print("我在模仿鸭子叫!")
def make_quack(obj):
obj.quack()
6.5 属性
6.5.1 类属性
类属性,属于类本身的属性,类所有实例化的对象都可以使用,定义类的时候直接定义类属性,位于类的方法外,可以通过类名.属性名
或类实例化对象.属性名
访问。
class Circle:
pi = 3.14 # 类属性
def __init__(self, radius):
self.radius = radius
c1 = Circle(5)
c2 = Circle(3)
print(Circle.pi) # 3.14
print(c1.pi) # 3.14
print(c2.pi) # 3.14
Circle.pi = 3.14159
print(c1.pi) # 3.14159
print(c2.pi) # 3.14159
6.5.2 实例属性
实例属性,属于类实例化的属性,也就是对象属性,每个实例属性,都是对应实例对象的属性,在类的实例化过程中,通过构造方法 __init__
中初始化的属性。通过类实例化对象.属性名
访问。
class Circle:
pi = 3.14 # 类属性
def __init__(self, radius):
self.radius = radius # 实例属性
c1 = Circle(5)
c2 = Circle(3)
print(c1.radius) # 5
print(c2.radius) # 3
c1.radius = 6
print(c1.radius) # 6
print(c2.radius) # 3
6.6 方法
6.6.1 实例方法
实例方法是最常见的方法类型,它需要一个实例对象作为第一个参数(通常命名为 self
)。实例方法可以访问和修改实例变量以及类变量。
class Cat:
def __init__(self, name):
self.name = name
def say(self):
print(self.name)
c = Cat("加菲猫")
c.say() # 输出: 加菲猫
6.6.2 类方法
类方法的第一个参数是类本身(通常命名为 cls
),并且可以通过该参数访问和修改类变量。类方法主要用于操作整个类的状态,而不是某个特定实例的状态。要定义类方法,你需要使用 @classmethod
装饰器;类方法可以直接通过类名来调用,也可以通过实例来调用。
class Cat:
name = "加菲猫"
@classmethod
def get_name(cls):
print(cls.name)
@classmethod
def set_name(cls, name):
cls.name = name
c = Cat()
c.get_name() # 输出: 加菲猫
Cat.get_name() # 输出: 加菲猫
Cat.set_name("卡丁猫")
Cat.get_name() # 输出: 卡丁猫
6.6.3 类静态方法
静态方法既不需要实例也不需要类作为参数,它与类或实例没有直接的关系。静态方法通常用于执行与类或实例无关的操作。要定义静态方法,则需要使用 @staticmethod
装饰器;静态方法同样可以直接通过类名来调用,也可以通过实例来调用。
class Cat:
@staticmethod
def say():
print("静态方法")
c = Cat()
c.say() # 输出: 静态方法
Cat.say() # 输出: 静态方法
第7章 模块与包
在 Python 中,模块和包是用来组织代码的重要工具。管理代码结构,避免命名冲突,并使代码更容易管理和复用。
7.1 模块
模块是一个包含 Python 代码的文件。通常,一个模块就是一个 .py
文件。模块内容可以是变量、函数和类。
新建模块
假设新建一个 utils.py
文件,文件内容如下
# utils.py
# π
pi = 3.14
def round_perimeter(r):
"""
计算圆的周长
:param r: 圆的半径
:return: 圆的周长
"""
return 2 * pi * r
class Round(object):
"""
计算圆的面积
"""
def __init__(self, r):
self.r = r
def round_area(self):
return pi * (self.r ** 2)
在每个模块最下面加测试代码,只会在测试情况下运行,被导入时不会被执行
# utils.py
# 在代码的最下方
def main():
# ...
pass
# 根据 __name__ 判断是否执行下方代码
if __name__ == "__main__":
main()
使用模块
导入整个模块
# main.py
import utils
result = utils.round_perimeter(1)
print(result) # 输出 6.28
导入特定变量、函数或类
# main.py
from utils import round_perimeter
result = round_perimeter(1)
print(result) # 输出 6.28
导入所有内容
# main.py
from utils import *
result = round_perimeter(1)
print(result) # 输出 6.28
print(pi) # 输出 3.14
使用别名
# main.py
import utils as u
result = u.round_perimeter(1)
print(result) # 输出 6.28
7.2 包
由多个相关模块组成的集合,用于组织和管理代码。包本身也是一个模块,但通常包含其他模块。
新建包
新建一个目录,目录里面必须包含初始化文件__init__.py
,Python才知道这是一个包,文件内容可以为空。
假设新建一个round_package
的包
包结构示例:
round_package/
│
├── __init__.py
├── round_perimeter.py
└── round_area.py
__init__.py
文件可以包含一些代码来初始化包,也可以在__init.py
文件定义默认导入的内容
# __init__.py 文件把两个模块导入,到时模块调用就不需要加模块名了
from round_perimeter import *
from round_area import *
使用包
# main.py
from round_package import round_perimeter as u, round_area
result = u.round_perimeter(1)
print(result) # 输出 6.28
7.3 包管理工具
pip
是 Python 的包管理工具,用于安装、卸载和管理第三方模块。
安装 pip(如果尚未安装)
# 对于大多数系统
python -m ensurepip --upgrade
# 或者
python -m pip install --upgrade pip
查看已安装的模块
pip list
安装模块
要安装一个模块,可以使用 pip install
命令,后面跟上模块的名称。例如,要安装 numpy
模块,可以使用:
pip install numpy
升级模块
如果想要升级已安装的模块到最新版本,可以使用 pip install --upgrade
命令:
pip install --upgrade numpy
卸载模块
pip uninstall numpy
查找模块
如果你不确定某个模块是否存在或想要查找模块的版本信息,可以使用 pip search
命令:
pip search numpy
显示模块信息
要显示模块的详细信息,可以使用 pip show
命令:
pip show numpy
安装指定版本的模块
如果你想安装特定版本的模块,可以使用 -==
或 ==
后跟版本号的方式:
pip install numpy==1.20.0
第8章 异常处理
8.1 异常的概念
程序运行时,Python 解释器遇到到一个错误,会停止程序的执行,并且提示错误信息,这就是异常。程序停止执行并提示错误信息,这个动作称为:抛出(raise)异常
8.2 捕获异常
将可能会引发异常的代码放在 try
块内,而将处理异常的代码放在 except
块内。
语法:
try:
尝试执行的代码
except:
出现错误的处理
示例:
try:
# 尝试执行的代码
result = 10 / 0
except ZeroDivisionError:
# 处理异常的代码
print("除数不能为零")
遇到不同类型的异常,如果需要针对不同类型异常做出不同处理,则要进行分类型捕获
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except (错误类型2, 错误类型3):
# 针对错误类型2 和 3,对应的代码处理
pass
except Exception as result:
print("未知错误 %s" % result)
异常捕获完整语法
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except 错误类型2:
# 针对错误类型2,对应的代码处理
pass
except (错误类型3, 错误类型4):
# 针对错误类型3 和 4,对应的代码处理
pass
except Exception as result:
# 打印错误信息
print(result)
else:
# 没有异常才会执行的代码
pass
finally:
# 无论是否有异常,都会执行的代码
print("无论是否有异常,都会执行的代码")
8.3 异常的传递
当函数或方法执行的时候,出现异常,会将异常传递给函数或方法的调用方,这就是异常的传递。如果异常传递到主程序,仍然没有进行异常处理,则程序将终止。
在实际开发中,常见做法是在主程序函数中添加异常捕获,主程序函数调用其它函数,只要出现异常,都会传递到主程序函数的异常捕获中,这样就不需要再其它函数的代码上增加大量的异常捕获。
def demo1():
return int(input("请输入一个整数:"))
def demo2():
return demo1()
try:
print(demo2())
except ValueError:
print("请输入正确的整数")
except Exception as result:
print(f"未知错误:{result}")
8.4 抛出(raise)异常
在开发中,除了代码执行出错时,Python
解释器抛出异常外,还可以根据业务需求主动抛出异常。首先实例化一个Exception
异常类的对象或继承异常类的对象;其次用关键字raise抛出这个对象
def input_password():
# 1. 提示用户输入密码
pwd = input("请输入密码:")
# 2. 判断密码长度,如果长度 >= 8,返回用户输入的密码
if len(pwd) >= 8:
return pwd
# 3. 密码长度不够,需要抛出异常
# 1> 创建异常对象 - 使用异常的错误信息字符串作为参数
ex = Exception("密码长度不够")
# 2> 抛出异常对象
raise ex
try:
user_pwd = input_password()
print(user_pwd)
except Exception as result:
print(f"发现错误:{result}")