面向对象的 Python - 快速指南
面向对象的 Python - 简介
编程语言不断涌现,不同的方法论也在不断涌现。面向对象编程就是这样一种方法论,在过去几年中变得非常流行。
本章讨论 Python 编程语言的特性,使其成为一种面向对象的编程语言。
语言编程分类方案
Python 的特点是面向对象的编程方法。下图展示了各种编程语言的特点。观察 Python 的面向对象特性。
语言班 | 类别 | 语言 |
---|---|---|
编程范式 | 程序 | C、C++、C#、Objective-C、java、Go |
脚本编写 | CoffeeScript、JavaScript、Python、Perl、Php、Ruby | |
功能性 | Clojure、Eralang、Haskell、Scala | |
编译类 | 静止的 | C、C++、C#、Objective-C、java、Go、Haskell、Scala |
动态的 | CoffeeScript、JavaScript、Python、Perl、Php、Ruby、Clojure、Erlang | |
类型类别 | 强的 | C#、java、Go、Python、Ruby、Clojure、Erlang、Haskell、Scala |
虚弱的 | C、C++、C#、Objective-C、CoffeeScript、JavaScript、Perl、Php | |
内存等级 | 管理 | 其他的 |
非托管 | C、C++、C#、Objective-C |
什么是面向对象编程?
面向对象意味着针对对象。换句话说,它意味着在功能上针对对象建模。这是通过数据和Behave描述交互对象的集合来对复杂系统进行建模的众多技术之一。
Python 是一种面向对象编程 (OOP),是一种专注于使用对象和类来设计和构建应用程序的编程方式。面向对象编程 (OOP) 的主要支柱是继承、多态性、抽象和封装。
面向对象分析(OOA)是检查问题、系统或任务并识别对象以及它们之间的交互的过程。
为什么选择面向对象编程?
Python 是采用面向对象的方法设计的。OOP 具有以下优点 -
提供清晰的程序结构,可以轻松映射现实世界的问题及其解决方案。
便于轻松维护和修改现有代码。
增强程序模块化,因为每个对象独立存在,并且可以轻松添加新功能而不会干扰现有功能。
为代码库提供了一个良好的框架,其中提供的组件可以由程序员轻松调整和修改。
赋予代码可重用性
过程编程与面向对象编程
基于过程的编程源自基于函数/过程/例程概念的结构编程。在面向过程的编程中,访问和更改数据很容易。另一方面,面向对象编程(OOP)允许将问题分解为许多称为对象的单元,然后围绕这些对象构建数据和函数。它更强调数据而不是过程或函数。同样在 OOP 中,数据是隐藏的,外部过程无法访问。
下图中的表格显示了 POP 和 OOP 方法之间的主要区别。
面向过程编程(POP)与面向过程编程的区别 面向对象编程(OOP)。
面向过程的编程 | 面向对象编程 | |
---|---|---|
基于 | 在 Pop 中,全部焦点都在数据和函数上 | Oops 基于现实世界的场景。整个程序被分为称为对象的小部分 |
可重复使用性 | 有限的代码重用 | 代码复用 |
方法 | 自上而下的方法 | 以对象为中心的设计 |
访问说明符 | 没有 | 公共、私人和受保护的 |
数据移动 | 数据可以在系统中的功能之间自由移动 | 在Oops中,数据可以通过成员函数相互移动和通信 |
数据存取 | 在pop中,大多数函数都使用全局数据进行共享,系统中函数与函数之间可以自由访问这些数据 | 在 Oops 中,数据不能在方法之间自由移动,它可以保存在公共或私有中,这样我们就可以控制数据的访问 |
数据隐藏 | 在流行音乐中,隐藏数据的特定方式,因此安全性稍差 | 它提供数据隐藏,因此更加安全 |
超载 | 不可能 | 函数和运算符重载 |
示例语言 | C、VB、Fortran、帕斯卡 | C++、Python、Java、C# |
抽象 | 在过程级别使用抽象 | 在类和对象级别使用抽象 |
面向对象编程原理
面向对象编程(OOP)基于对象而不是动作、数据而不是逻辑的概念。为了使编程语言成为面向对象的,它应该有一种机制来处理类和对象,以及实现和使用基本的面向对象原则和概念,即继承、抽象、封装和多态性。
让我们简要了解面向对象编程的每个支柱 -
封装
该属性隐藏了不必要的细节,使管理程序结构变得更加容易。每个对象的实现和状态都隐藏在明确定义的边界后面,并提供了一个干净、简单的界面来使用它们。实现此目的的一种方法是将数据设为私有。
遗产
继承,也称为泛化,使我们能够捕获类和对象之间的层次关系。例如,“水果”是“橙色”的泛化。从代码重用的角度来看,继承非常有用。
抽象
此属性允许我们隐藏细节并仅公开概念或对象的基本特征。例如,驾驶踏板车的人知道按下喇叭时会发出声音,但他不知道按下喇叭时声音实际上是如何产生的。
多态性
多态性意味着多种形式。也就是说,事物或动作以不同的形式或方式呈现。多态性的一个很好的例子是类中的构造函数重载。
面向对象的Python
Python 编程的核心是对象和OOP,但是您不必通过将代码组织到类中来限制自己使用 OOP。OOP 补充了 Python 的整体设计理念,并鼓励采用干净、务实的编程方式。OOP 还可以编写更大、更复杂的程序。
模块与类和对象
模块就像“字典”
在模块上工作时,请注意以下几点 -
Python 模块是封装可重用代码的包。
模块驻留在包含__init__.py文件的文件夹中。
模块包含函数和类。
使用import关键字导入模块。
回想一下,字典是一个键值对。这意味着如果您有一个带有EmployeID键的字典并且您想要检索它,那么您将必须使用以下代码行 -
employee = {“EmployeID”: “Employee Unique Identity!”} print (employee [‘EmployeID])
您将必须按照以下流程处理模块 -
模块是一个Python 文件,其中包含一些函数或变量。
导入您需要的文件。
现在,您可以使用“.”访问该模块中的函数或变量。(点)运算符。
考虑一个名为employee.py的模块,其中有一个名为employee的函数。该函数的代码如下 -
# this goes in employee.py def EmployeID(): print (“Employee Unique Identity!”)
现在导入模块,然后访问函数EmployeID -
import employee employee. EmployeID()
您可以在其中插入一个名为Age的变量,如下所示 -
def EmployeID(): print (“Employee Unique Identity!”) # just a variable Age = “Employee age is **”
现在,通过以下方式访问该变量 -
import employee employee.EmployeID() print(employee.Age)
现在,让我们将其与字典进行比较 -
Employee[‘EmployeID’] # get EmployeID from employee Employee.employeID() # get employeID from the module Employee.Age # get access to variable
请注意,Python 中有一个常见的模式 -
取一个key=value样式的容器
通过钥匙的名称从中获取一些东西
将模块与字典进行比较时,两者相似,除了以下内容 -
对于字典来说,键是一个字符串,语法是 [key]。
对于module来说,键是一个标识符,语法是 .key。
类就像模块
Module 是一个专门的字典,可以存储 Python 代码,因此您可以使用“.”来访问它。操作员。类是一种将一组函数和数据放入容器中的方法,以便您可以使用“.”运算符访问它们。
如果您必须创建一个类似于员工模块的类,您可以使用以下代码来完成:
class employee(object): def __init__(self): self. Age = “Employee Age is ##” def EmployeID(self): print (“This is just employee unique identity”)
注意- 类优于模块,因为您可以按原样重用它们,而不会产生太多干扰。而使用模块时,整个程序只有一个。
对象就像迷你导入
类就像一个迷你模块,您可以使用名为instantiate的概念以与类类似的方式导入。请注意,当您实例化一个类时,您会得到一个对象。
您可以实例化一个对象,类似于像函数一样调用类,如下所示 -
this_obj = employee() # Instantiatethis_obj.EmployeID() # get EmployeId from the class print(this_obj.Age) # get variable Age
您可以通过以下三种方式之一来执行此操作 -
# dictionary style Employee[‘EmployeID’] # module style Employee.EmployeID() Print(employee.Age) # Class style this_obj = employee() this_obj.employeID() Print(this_obj.Age)
面向对象的Python - 环境设置
本章将详细介绍如何在本地计算机上设置Python环境。
先决条件和工具包
在继续进一步学习 Python 之前,我们建议您检查是否满足以下先决条件 -
您的计算机上已安装最新版本的 Python
已安装 IDE 或文本编辑器
您对 Python 的编写和调试有基本的熟悉,也就是说您可以在 Python 中执行以下操作 -
能够编写和运行Python程序。
调试程序并诊断错误。
使用基本数据类型。
编写for循环、while循环和if语句
代码功能
如果您没有任何编程语言经验,您可以在以下位置找到大量 Python 初学者教程
https://www.tutorialpoints.com/安装Python
以下步骤详细介绍了如何在本地计算机上安装 Python -
步骤 1 - 访问 Python 官方网站https://www.python.org/,单击“下载”菜单并选择您选择的最新版本或任何稳定版本。
步骤 2 - 保存您正在下载的 Python 安装程序 exe 文件,下载后将其打开。点击运行,默认选择下一步,完成安装。
步骤 3 - 安装后,您现在应该看到 Python 菜单,如下图所示。通过选择 IDLE (Python GUI) 启动程序。
这将启动 Python shell。输入简单的命令来检查安装。
选择 IDE
集成开发环境是一个面向软件开发的文本编辑器。在使用 Python 时,您必须安装 IDE 来控制编程流程并将项目分组在一起。以下是一些在线可用的 IDE。您可以根据自己的方便选择其中之一。
- Pycharm集成开发环境
- 科莫多集成开发环境
- 埃里克 Python IDE
注意- Eclipse IDE 主要用于 Java,但它有一个 Python 插件。
皮查姆
Pycharm 是跨平台 IDE,是当前最流行的 IDE 之一。它提供编码帮助和分析,包括代码完成、项目和代码导航、集成单元测试、版本控制集成、调试等等
下载链接
https://www.jetbrains.com/pycharm/download/#section=windows支持的语言- Python、HTML、CSS、JavaScript、Coffee Script、TypeScript、Cython、AngularJS、Node.js、模板语言。
截屏
为什么选择?
PyCharm 为其用户提供以下功能和好处 -
- 跨平台 IDE 兼容 Windows、Linux 和 Mac OS
- 包括 Django IDE,以及 CSS 和 JavaScript 支持
- 包括数千个插件、集成终端和版本控制
- 与 Git、SVN 和 Mercurial 集成
- 为Python提供智能编辑工具
- 与 Virtualenv、Docker 和 Vagrant 轻松集成
- 简单的导航和搜索功能
- 代码分析和重构
- 可配置的注射
- 支持大量 Python 库
- 包含模板和 JavaScript 调试器
- 包括 Python/Django 调试器
- 可与 Google App Engine、其他框架和库配合使用。
- 具有可定制的 UI、VIM 仿真可用
科莫多集成开发环境
它是一个多语言 IDE,支持 100 多种语言,基本上支持 Python、PHP 和 Ruby 等动态语言。它是一款商业 IDE,可免费试用 21 天并具有完整功能。ActiveState 是一家管理 Komodo IDE 开发的软件公司。它还提供了 Komodo 的精简版本,称为 Komodo Edit,用于简单的编程任务。
该IDE包含从最基本到高级的各种功能。如果您是学生或自由职业者,那么您几乎可以以实际价格的一半购买。但是,对于来自认可机构和大学的教师和教授来说,它是完全免费的。
它拥有 Web 和移动开发所需的所有功能,包括对所有语言和框架的支持。
下载链接
Komodo Edit(免费版)和 Komodo IDE(付费版)的下载链接如下 -
科莫多编辑(免费)
https://www.activestate.com/komodo-editKomodo IDE(付费)
https://www.activestate.com/komodo-ide/downloads/ide截屏
为什么选择?
- 功能强大的 IDE,支持 Perl、PHP、Python、Ruby 等。
- 跨平台 IDE。
它包括集成调试器支持、自动完成、文档对象模型 (DOM) 查看器、代码浏览器、交互式 shell、断点配置、代码分析、集成单元测试等基本功能。简而言之,它是一个专业的 IDE,具有许多提高生产力的功能。
埃里克 Python IDE
它是一个适用于 Python 和 Ruby 的开源 IDE。Eric 是一个功能齐全的编辑器和 IDE,用 Python 编写。它基于跨平台的Qt GUI工具包,集成了高度灵活的Scintilla编辑器控件。IDE 的可配置性非常强,人们可以选择使用什么和不使用什么。您可以从以下链接下载 Eric IDE:
https://eric-ide.python-projects.org/eric-download.html为什么选择
- 伟大的缩进,错误突出显示。
- 代码协助
- 代码完成
- 使用 PyLint 进行代码清理
- 快速搜索
- 集成 Python 调试器。
截屏
选择文本编辑器
您可能并不总是需要 IDE。对于学习使用 Python 或 Arduino 进行编码等任务,或者在 shell 脚本中编写快速脚本以帮助您自动执行某些任务,简单且轻量级的以代码为中心的文本编辑器即可完成。此外,许多文本编辑器还提供语法突出显示和程序内脚本执行等功能,与 IDE 类似。这里给出了一些文本编辑器 -
- Atomics
- 崇高的文字
- 记事本++
Atomics文本编辑器
Atom 是由 GitHub 团队构建的可破解文本编辑器。它是一个免费、开源的文本和代码编辑器,这意味着所有代码都可供您阅读、修改以供自己使用,甚至可以做出改进。它是一个跨平台文本编辑器,兼容 macOS、Linux 和 Microsoft Windows,支持用 Node.js 编写的插件和嵌入式 Git 控件。
下载链接
https://atom.io/截屏
支持的语言
C/C++、C#、CSS、CoffeeScript、HTML、JavaScript、Java、JSON、Julia、Objective-C、PHP、Perl、Python、Ruby on Rails、Ruby、Shell 脚本、Scala、SQL、XML、YAML 等等。
崇高文本编辑器
Sublime text 是一款专有软件,它为您提供免费试用版,以便您在购买之前进行测试。根据stackoverflow.com 的数据,它是第四大最受欢迎的开发环境。
它提供的一些优势是令人难以置信的速度、易用性和社区支持。它还支持许多编程语言和标记语言,并且用户可以使用插件添加功能,这些插件通常是社区构建的,并在自由软件许可下维护。
截屏
支持语言
- Python、Ruby、JavaScript 等
为什么选择?
自定义键绑定、菜单、片段、宏、补全等。
自动完成功能
- 使用片段、字段标记和占位符通过 sublime 文本片段快速插入文本和代码
快速打开
Mac、Linux 和 Windows 的跨平台支持。
将光标跳转到您想去的地方
选择多行、单词和列
记事本++
它是一个免费的源代码编辑器和记事本替代品,支持从汇编到 XML 的多种语言,包括 Python。运行在 MS windows 环境中,其使用受 GPL 许可证约束。除了语法突出显示之外,Notepad++ 还有一些对编码人员特别有用的功能。
截屏
主要特征
- 语法高亮和语法折叠
- PCRE(Perl 兼容正则表达式)搜索/替换
- 完全可定制的图形用户界面
- S自动补全
- 选项卡式编辑
- 多视图
- 多语言环境
- 可使用不同的参数启动
支持语言
- 几乎所有语言(60 多种语言),例如 Python、C、C++、C#、Java 等。
面向对象的 Python - 数据结构
从语法的角度来看,Python 数据结构非常直观,并且提供了大量的操作选择。您需要根据数据涉及的内容、是否需要修改、或者是否是固定数据以及需要什么访问类型(例如开始/结束/随机等)来选择Python数据结构。
列表
列表代表了 Python 中最通用的数据结构类型。列表是一个容器,其中在方括号之间保存逗号分隔的值(项目或元素)。当我们想要使用多个相关值时,列表很有用。由于列表将数据保存在一起,我们可以同时对多个值执行相同的方法和操作。列表索引从零开始,与字符串不同,列表是可变的。
数据结构 - 列表
>>> >>> # Any Empty List >>> empty_list = [] >>> >>> # A list of String >>> str_list = ['Life', 'Is', 'Beautiful'] >>> # A list of Integers >>> int_list = [1, 4, 5, 9, 18] >>> >>> #Mixed items list >>> mixed_list = ['This', 9, 'is', 18, 45.9, 'a', 54, 'mixed', 99, 'list'] >>> # To print the list >>> >>> print(empty_list) [] >>> print(str_list) ['Life', 'Is', 'Beautiful'] >>> print(type(str_list)) <class 'list'> >>> print(int_list) [1, 4, 5, 9, 18] >>> print(mixed_list) ['This', 9, 'is', 18, 45.9, 'a', 54, 'mixed', 99, 'list']
访问 Python 列表中的项目
列表中的每个项目都分配有一个数字 - 即该数字的索引或位置。索引始终从零开始,第二个索引是 1,依此类推。要访问列表中的项目,我们可以在方括号内使用这些索引号。例如,观察以下代码 -
>>> mixed_list = ['This', 9, 'is', 18, 45.9, 'a', 54, 'mixed', 99, 'list'] >>> >>> # To access the First Item of the list >>> mixed_list[0] 'This' >>> # To access the 4th item >>> mixed_list[3] 18 >>> # To access the last item of the list >>> mixed_list[-1] 'list'
空对象
空对象是最简单、最基本的 Python 内置类型。我们在没有注意到的情况下多次使用它们,并将其扩展到我们创建的每个类。编写空类的主要目的是暂时阻止某些内容,然后对其进行扩展和添加Behave。
向类添加Behave意味着用对象替换数据结构并更改对其的所有引用。因此,在创建任何内容之前,检查数据是否是伪装的对象非常重要。请观察以下代码以更好地理解:
>>> #Empty objects >>> >>> obj = object() >>> obj.x = 9 Traceback (most recent call last): File "<pyshell#3>", line 1, in <module> obj.x = 9 AttributeError: 'object' object has no attribute 'x'
从上面我们可以看出,不可能在直接实例化的对象上设置任何属性。当Python允许对象具有任意属性时,需要一定量的系统内存来跟踪每个对象具有哪些属性,用于存储属性名称及其值。即使没有存储任何属性,也会为潜在的新属性分配一定量的内存。
因此,Python 默认情况下禁用对象和其他几个内置函数的任意属性。
>>> # Empty Objects >>> >>> class EmpObject: pass >>> obj = EmpObject() >>> obj.x = 'Hello, World!' >>> obj.x 'Hello, World!'
因此,如果我们想将属性分组在一起,我们可以将它们存储在一个空对象中,如上面的代码所示。然而,并不总是建议使用这种方法。请记住,仅当您想要指定数据和Behave时才应使用类和对象。
元组
元组与列表类似,可以存储元素。然而,它们是不可变的,所以我们不能添加、删除或替换对象。元组由于其不变性而提供的主要好处是我们可以将它们用作字典中的键,或者对象需要哈希值的其他位置。
元组用于存储数据,而不是Behave。如果您需要操作元组的Behave,则需要将元组传递到执行该操作的函数(或另一个对象上的方法)。
由于元组可以充当字典键,因此存储的值彼此不同。我们可以通过用逗号分隔值来创建一个元组。元组用括号括起来,但不是强制的。以下代码显示了两个相同的分配。
>>> stock1 = 'MSFT', 95.00, 97.45, 92.45 >>> stock2 = ('MSFT', 95.00, 97.45, 92.45) >>> type (stock1) <class 'tuple'> >>> type(stock2) <class 'tuple'> >>> stock1 == stock2 True >>>
定义元组
元组与列表非常相似,只是整个元素集都括在括号而不是方括号中。
就像当你对列表进行切片时,你会得到一个新列表,当你对元组进行切片时,你会得到一个新元组。
>>> tupl = ('Tuple','is', 'an','IMMUTABLE', 'list') >>> tupl ('Tuple', 'is', 'an', 'IMMUTABLE', 'list') >>> tupl[0] 'Tuple' >>> tupl[-1] 'list' >>> tupl[1:3] ('is', 'an')
Python 元组方法
以下代码显示了 Python 元组中的方法 -
>>> tupl ('Tuple', 'is', 'an', 'IMMUTABLE', 'list') >>> tupl.append('new') Traceback (most recent call last): File "<pyshell#148>", line 1, in <module> tupl.append('new') AttributeError: 'tuple' object has no attribute 'append' >>> tupl.remove('is') Traceback (most recent call last): File "<pyshell#149>", line 1, in <module> tupl.remove('is') AttributeError: 'tuple' object has no attribute 'remove' >>> tupl.index('list') 4 >>> tupl.index('new') Traceback (most recent call last): File "<pyshell#151>", line 1, in <module> tupl.index('new') ValueError: tuple.index(x): x not in tuple >>> "is" in tupl True >>> tupl.count('is') 1
从上面显示的代码中,我们可以理解元组是不可变的,因此 -
您无法将元素添加到元组中。
您不能追加或扩展方法。
您无法从元组中删除元素。
元组没有删除或弹出方法。
计数和索引是元组中可用的方法。
字典
字典是Python的内置数据类型之一,它定义键和值之间的一对一关系。
定义字典
观察以下代码以了解如何定义字典 -
>>> # empty dictionary >>> my_dict = {} >>> >>> # dictionary with integer keys >>> my_dict = { 1:'msft', 2: 'IT'} >>> >>> # dictionary with mixed keys >>> my_dict = {'name': 'Aarav', 1: [ 2, 4, 10]} >>> >>> # using built-in function dict() >>> my_dict = dict({1:'msft', 2:'IT'}) >>> >>> # From sequence having each item as a pair >>> my_dict = dict([(1,'msft'), (2,'IT')]) >>> >>> # Accessing elements of a dictionary >>> my_dict[1] 'msft' >>> my_dict[2] 'IT' >>> my_dict['IT'] Traceback (most recent call last): File "<pyshell#177>", line 1, in <module> my_dict['IT'] KeyError: 'IT' >>>
从上面的代码我们可以观察到:
首先,我们创建一个包含两个元素的字典并将其分配给变量 my_dict。每个元素都是一个键值对,整个元素集用大括号括起来。
数字1是键,msft是它的值。同样,2是键,IT是它的值。
您可以通过键获取值,但反之则不然。因此,当我们尝试my_dict['IT']时,它会引发异常,因为IT不是键。
修改字典
观察以下代码以了解如何修改字典 -
>>> # Modifying a Dictionary >>> >>> my_dict {1: 'msft', 2: 'IT'} >>> my_dict[2] = 'Software' >>> my_dict {1: 'msft', 2: 'Software'} >>> >>> my_dict[3] = 'Microsoft Technologies' >>> my_dict {1: 'msft', 2: 'Software', 3: 'Microsoft Technologies'}
从上面的代码我们可以观察到 -
字典中不能有重复的键。更改现有键的值将删除旧值。
您可以随时添加新的键值对。
字典没有元素之间的顺序概念。它们是简单的无序集合。
在字典中混合数据类型
观察以下代码以了解如何在字典中混合数据类型 -
>>> # Mixing Data Types in a Dictionary >>> >>> my_dict {1: 'msft', 2: 'Software', 3: 'Microsoft Technologies'} >>> my_dict[4] = 'Operating System' >>> my_dict {1: 'msft', 2: 'Software', 3: 'Microsoft Technologies', 4: 'Operating System'} >>> my_dict['Bill Gates'] = 'Owner' >>> my_dict {1: 'msft', 2: 'Software', 3: 'Microsoft Technologies', 4: 'Operating System', 'Bill Gates': 'Owner'}
从上面的代码我们可以观察到 -
不仅仅是字符串,字典值可以是任何数据类型,包括字符串、整数,包括字典本身。
与字典值不同,字典键受到更多限制,但可以是任何类型,例如字符串、整数或任何其他类型。
从词典中删除项目
观察以下代码以了解如何从字典中删除项目 -
>>> # Deleting Items from a Dictionary >>> >>> my_dict {1: 'msft', 2: 'Software', 3: 'Microsoft Technologies', 4: 'Operating System', 'Bill Gates': 'Owner'} >>> >>> del my_dict['Bill Gates'] >>> my_dict {1: 'msft', 2: 'Software', 3: 'Microsoft Technologies', 4: 'Operating System'} >>> >>> my_dict.clear() >>> my_dict {}
从上面的代码我们可以观察到 -
del - 允许您通过键从字典中删除单个项目。
clear - 删除字典中的所有项目。
套
Set() 是一个无序集合,没有重复元素。虽然单个项目是不可变的,但集合本身是可变的,也就是说我们可以从集合中添加或删除元素/项目。我们可以使用集合执行数学运算,例如并集、交集等。
虽然集合通常可以使用树来实现,但 Python 中的集合可以使用哈希表来实现。这使得它成为一种高度优化的方法来检查集合中是否包含特定元素
创建一个集合
通过将所有项目(元素)放在大括号{}内并用逗号分隔或使用内置函数set() 来创建集合。观察以下代码行 -
>>> #set of integers >>> my_set = {1,2,4,8} >>> print(my_set) {8, 1, 2, 4} >>> >>> #set of mixed datatypes >>> my_set = {1.0, "Hello World!", (2, 4, 6)} >>> print(my_set) {1.0, (2, 4, 6), 'Hello World!'} >>>
集合方法
观察以下代码以了解集合的方法 -
>>> >>> #METHODS FOR SETS >>> >>> #add(x) Method >>> topics = {'Python', 'Java', 'C#'} >>> topics.add('C++') >>> topics {'C#', 'C++', 'Java', 'Python'} >>> >>> #union(s) Method, returns a union of two set. >>> topics {'C#', 'C++', 'Java', 'Python'} >>> team = {'Developer', 'Content Writer', 'Editor','Tester'} >>> group = topics.union(team) >>> group {'Tester', 'C#', 'Python', 'Editor', 'Developer', 'C++', 'Java', 'Content Writer'} >>> # intersets(s) method, returns an intersection of two sets >>> inters = topics.intersection(team) >>> inters set() >>> >>> # difference(s) Method, returns a set containing all the elements of invoking set but not of the second set. >>> >>> safe = topics.difference(team) >>> safe {'Python', 'C++', 'Java', 'C#'} >>> >>> diff = topics.difference(group) >>> diff set() >>> #clear() Method, Empties the whole set. >>> group.clear() >>> group set() >>>
集合运算符
观察以下代码以了解集合运算符 -
>>> # PYTHON SET OPERATIONS >>> >>> #Creating two sets >>> set1 = set() >>> set2 = set() >>> >>> # Adding elements to set >>> for i in range(1,5): set1.add(i) >>> for j in range(4,9): set2.add(j) >>> set1 {1, 2, 3, 4} >>> set2 {4, 5, 6, 7, 8} >>> >>> #Union of set1 and set2 >>> set3 = set1 | set2 # same as set1.union(set2) >>> print('Union of set1 & set2: set3 = ', set3) Union of set1 & set2: set3 = {1, 2, 3, 4, 5, 6, 7, 8} >>> >>> #Intersection of set1 & set2 >>> set4 = set1 & set2 # same as set1.intersection(set2) >>> print('Intersection of set1 and set2: set4 = ', set4) Intersection of set1 and set2: set4 = {4} >>> >>> # Checking relation between set3 and set4 >>> if set3 > set4: # set3.issuperset(set4) print('Set3 is superset of set4') elif set3 < set4: #set3.issubset(set4) print('Set3 is subset of set4') else: #set3 == set4 print('Set 3 is same as set4') Set3 is superset of set4 >>> >>> # Difference between set3 and set4 >>> set5 = set3 - set4 >>> print('Elements in set3 and not in set4: set5 = ', set5) Elements in set3 and not in set4: set5 = {1, 2, 3, 5, 6, 7, 8} >>> >>> # Check if set4 and set5 are disjoint sets >>> if set4.isdisjoint(set5): print('Set4 and set5 have nothing in common\n') Set4 and set5 have nothing in common >>> # Removing all the values of set5 >>> set5.clear() >>> set5 set()
面向对象的 Python - 构建块
在本章中,我们将详细讨论面向对象的术语和编程概念。类只是一个实例的工厂。该工厂包含描述如何制作实例的蓝图。实例或对象是从类构造的。在大多数情况下,我们可以拥有一个类的多个实例。每个实例都有一组属性,并且这些属性在类中定义,因此特定类的每个实例都应该具有相同的属性。
类包:Behave和状态
类可以让您将对象的Behave和状态捆绑在一起。观察下图以便更好地理解 -
在讨论类包时,以下几点值得注意 -
Behave这个词与功能相同——它是一段执行某事(或实现某种Behave)的代码
状态这个词与变量相同——它是在类中存储值的地方。
当我们一起断言一个类的Behave和状态时,这意味着一个类封装了函数和变量。
类有方法和属性
在 Python 中,创建方法定义类Behave。“方法”这个词是为类中定义的函数指定的 OOP 名称。总结一下 -
类函数- 是方法的同义词
类变量- 是名称属性的同义词。
类- 具有精确Behave的实例的蓝图。
对象- 类的实例之一,执行类中定义的功能。
类型- 表示实例所属的类
属性- 任何对象值:object.attribute
方法- 类中定义的“可调用属性”
例如,观察以下代码片段 -
var = “Hello, John” print( type (var)) # < type ‘str’> or <class 'str'> print(var.upper()) # upper() method is called, HELLO, JOHN
创建和实例化
下面的代码展示了如何创建我们的第一个类及其实例。
class MyClass(object): pass # Create first instance of MyClass this_obj = MyClass() print(this_obj) # Another instance of MyClass that_obj = MyClass() print (that_obj)
这里我们创建了一个名为MyClass 的类,它不执行任何任务。MyClass类中的参数对象涉及类继承,将在后面的章节中讨论。传入上面的代码表明该块是空的,即它是一个空的类定义。
让我们创建MyClass()类的实例this_obj并打印它,如下所示 -
<__main__.MyClass object at 0x03B08E10> <__main__.MyClass object at 0x0369D390>
在这里,我们创建了MyClass 的一个实例。十六进制代码指的是存储对象的地址。另一个实例指向另一个地址。
现在让我们在类MyClass()中定义一个变量,并从该类的实例中获取该变量,如以下代码所示 -
class MyClass(object): var = 9 # Create first instance of MyClass this_obj = MyClass() print(this_obj.var) # Another instance of MyClass that_obj = MyClass() print (that_obj.var)
输出
执行上面给出的代码时,您可以观察到以下输出 -
9 9
由于实例知道它是从哪个类实例化的,因此当从实例请求属性时,实例会查找该属性和类。这称为属性查找。
实例方法
类中定义的函数称为方法。实例方法需要一个实例才能调用它,并且不需要装饰器。创建实例方法时,第一个参数始终是self。尽管我们可以用任何其他名称来称呼它(self),但建议使用 self,因为它是一种命名约定。
class MyClass(object): var = 9 def firstM(self): print("hello, World") obj = MyClass() print(obj.var) obj.firstM()
输出
执行上面给出的代码时,您可以观察到以下输出 -
9 hello, World
请注意,在上面的程序中,我们定义了一个以 self 作为参数的方法。但我们无法调用该方法,因为我们尚未声明任何参数。
class MyClass(object): def firstM(self): print("hello, World") print(self) obj = MyClass() obj.firstM() print(obj)
输出
执行上面给出的代码时,您可以观察到以下输出 -
hello, World <__main__.MyClass object at 0x036A8E10> <__main__.MyClass object at 0x036A8E10>
封装
封装是 OOP 的基础之一。OOP 使我们能够隐藏对象内部工作的复杂性,这对开发人员有以下好处 -
简化并易于理解在不了解内部结构的情况下使用对象。
任何变化都可以轻松管理。
面向对象编程严重依赖封装。术语封装和抽象(也称为数据隐藏)通常用作同义词。它们几乎是同义词,因为抽象是通过封装实现的。
封装为我们提供了限制对对象某些组件的访问的机制,这意味着从对象定义的外部无法看到对象的内部表示。访问这些数据通常是通过特殊方法来实现的——Getters和Setters。
该数据存储在实例属性中,并且可以从类外部的任何位置进行操作。为了确保其安全,只能使用实例方法来访问该数据。不应允许直接访问。
class MyClass(object): def setAge(self, num): self.age = num def getAge(self): return self.age zack = MyClass() zack.setAge(45) print(zack.getAge()) zack.setAge("Fourty Five") print(zack.getAge())
输出
执行上面给出的代码时,您可以观察到以下输出 -
45 Fourty Five
仅当数据正确且有效时,才应使用异常处理结构来存储数据。正如我们在上面看到的,setAge() 方法对用户输入没有限制。它可以是字符串、数字或列表。所以我们需要检查上面的代码以确保存储的正确性。
class MyClass(object): def setAge(self, num): self.age = num def getAge(self): return self.age
zack = MyClass() zack.setAge(45) print(zack.getAge()) zack.setAge("Fourty Five") print(zack.getAge())
初始化构造函数
一旦实例化类的对象,就会隐式调用__ init __ 方法。这将初始化该对象。
x = MyClass()
上面显示的代码行将创建一个新实例并将该对象分配给局部变量 x。
实例化操作,即调用类对象,创建一个空对象。许多类喜欢创建具有定制为特定初始状态的实例的对象。因此,一个类可以定义一个名为“__init__()”的特殊方法,如下所示 -
def __init__(self): self.data = []
Python 在实例化期间调用 __init__ 来定义一个附加属性,该属性在实例化类时应出现,该属性可能会为该对象设置一些起始值或运行实例化所需的例程。因此,在这个例子中,可以通过以下方式获得一个新的初始化实例 -
x = MyClass()
__init__() 方法可以具有单个或多个参数,以获得更大的灵活性。init 代表初始化,因为它初始化实例的属性。它被称为类的构造函数。
class myclass(object): def __init__(self,aaa, bbb): self.a = aaa self.b = bbb x = myclass(4.5, 3) print(x.a, x.b)
输出
4.5 3
类属性
在类中定义的属性称为“类属性”,在函数中定义的属性称为“实例属性”。定义时,这些属性不以 self 为前缀,因为它们是类的属性,而不是特定实例的属性。
类属性可以由类本身 (className.attributeName) 以及类的实例 (inst.attributeName) 访问。因此,实例可以访问实例属性和类属性。
>>> class myclass(): age = 21 >>> myclass.age 21 >>> x = myclass() >>> x.age 21 >>>
类属性可以在实例中被重写,尽管这不是破坏封装的好方法。
Python 中有一个属性的查找路径。第一个是类中定义的方法,然后是它上面的类。
>>> class myclass(object): classy = 'class value' >>> dd = myclass() >>> print (dd.classy) # This should return the string 'class value' class value >>> >>> dd.classy = "Instance Value" >>> print(dd.classy) # Return the string "Instance Value" Instance Value >>> >>> # This will delete the value set for 'dd.classy' in the instance. >>> del dd.classy >>> >>> # Since the overriding attribute was deleted, this will print 'class value'. >>> print(dd.classy) class value >>>
我们正在覆盖实例 dd 中的“classy”类属性。当它被覆盖时,Python 解释器会读取被覆盖的值。但是,一旦用“del”删除了新值,覆盖的值就不再存在于实例中,因此查找会上升到更高的级别并从类中获取它。
使用类和实例数据
在本节中,让我们了解类数据如何与实例数据相关。我们可以将数据存储在类中或实例中。当我们设计一个类时,我们决定哪些数据属于实例,哪些数据应该存储到整个类中。
实例可以访问类数据。如果我们创建多个实例,那么这些实例可以访问它们各自的属性值以及整个类数据。
因此,类数据是在所有实例之间共享的数据。请观察下面给出的代码以更好地理解 -
class InstanceCounter(object): count = 0 # class attribute, will be accessible to all instances def __init__(self, val): self.val = val InstanceCounter.count +=1 # Increment the value of class attribute, accessible through class name # In above line, class ('InstanceCounter') act as an object def set_val(self, newval): self.val = newval def get_val(self): return self.val def get_count(self): return InstanceCounter.count a = InstanceCounter(9) b = InstanceCounter(18) c = InstanceCounter(27) for obj in (a, b, c): print ('val of obj: %s' %(obj.get_val())) # Initialized value ( 9, 18, 27) print ('count: %s' %(obj.get_count())) # always 3
输出
val of obj: 9 count: 3 val of obj: 18 count: 3 val of obj: 27 count: 3
简而言之,类属性对于类的所有实例都是相同的,而实例属性对于每个实例都是特定的。对于两个不同的实例,我们将有两个不同的实例属性。
class myClass: class_attribute = 99 def class_method(self): self.instance_attribute = 'I am instance attribute' print (myClass.__dict__)
输出
执行上面给出的代码时,您可以观察到以下输出 -
{'__module__': '__main__', 'class_attribute': 99, 'class_method': <function myClass.class_method at 0x04128D68>, '__dict__': <attribute '__dict__' of 'myClass' objects>, '__weakref__': <attribute '__weakref__' of 'myClass' objects>, '__doc__': None}
实例属性myClass.__dict__如图所示 -
>>> a = myClass() >>> a.class_method() >>> print(a.__dict__) {'instance_attribute': 'I am instance attribute'}
面向对象的快捷方式
本章详细讨论Python中的各种内置函数、文件I/O操作和重载概念。
Python 内置函数
Python 解释器有许多称为内置函数的函数,可以随时使用。在最新版本中,Python 包含 68 个内置函数,如下表所示 -
内置功能 | ||||
---|---|---|---|---|
绝对值() | 字典() | 帮助() | 分钟() | 设置属性() |
全部() | 目录() | 十六进制() | 下一个() | 片() |
任何() | divmod() | ID() | 目的() | 排序() |
ASCII() | 枚举() | 输入() | 十月() | 静态方法() |
垃圾桶() | 评估() | 整数() | 打开() | 字符串() |
布尔() | 执行() | isinstance() | 订单() | 和() |
字节数组() | 筛选() | 是子类() | 战俘() | 极好的() |
字节() | 漂浮() | 迭代器() | 打印() | 元组() |
可调用() | 格式() | 长度() | 财产() | 类型() |
chr() | 冻结集() | 列表() | 范围() | 变量() |
类方法() | 获取属性() | 当地人() | 代表() | 压缩() |
编译() | 全局变量() | 地图() | 反转() | __进口__() |
复杂的() | 哈萨特() | 最大限度() | 圆形的() | |
德拉特() | 散列() | 内存视图() | 放() |
本节简要讨论一些重要的功能 -
len() 函数
len() 函数获取字符串、列表或集合的长度。它返回对象的长度或项目数,其中对象可以是字符串、列表或集合。
>>> len(['hello', 9 , 45.0, 24]) 4
len() 函数内部的工作方式类似于list.__len__()或tuple.__len__()。因此,请注意 len() 仅适用于具有 __ len__()方法的对象。
>>> set1 {1, 2, 3, 4} >>> set1.__len__() 4
然而,在实践中,我们更喜欢len()而不是__len__()函数,因为以下原因 -
它更有效率。并且没有必要编写特定的方法来拒绝对特殊方法(例如 __len__ )的访问。
易于维护。
它支持向后兼容性。
反转(顺序)
它返回反向迭代器。seq 必须是具有 __reversed__() 方法或支持序列协议(__len__() 方法和 __getitem__() 方法)的对象。当我们想要从后到前循环项目时,它通常用在for循环中。
>>> normal_list = [2, 4, 5, 7, 9] >>> >>> class CustomSequence(): def __len__(self): return 5 def __getitem__(self,index): return "x{0}".format(index) >>> class funkyback(): def __reversed__(self): return 'backwards!' >>> for seq in normal_list, CustomSequence(), funkyback(): print('\n{}: '.format(seq.__class__.__name__), end="") for item in reversed(seq): print(item, end=", ")
最后的 for 循环打印正常列表的反向列表以及两个自定义序列的实例。输出显示,reverse()适用于所有三个,但当我们定义__reversed__时,结果却截然不同。
输出
执行上面给出的代码时,您可以观察到以下输出 -
list: 9, 7, 5, 4, 2, CustomSequence: x4, x3, x2, x1, x0, funkyback: b, a, c, k, w, a, r, d, s, !,
枚举
enumerate ()方法向可迭代对象添加一个计数器并返回枚举对象。
enumerate () 的语法是 -
enumerate(iterable, start = 0)
这里第二个参数start是可选的,默认情况下索引从零 (0) 开始。
>>> # Enumerate >>> names = ['Rajesh', 'Rahul', 'Aarav', 'Sahil', 'Trevor'] >>> enumerate(names) <enumerate object at 0x031D9F80> >>> list(enumerate(names)) [(0, 'Rajesh'), (1, 'Rahul'), (2, 'Aarav'), (3, 'Sahil'), (4, 'Trevor')] >>>
因此enumerate()返回一个迭代器,该迭代器生成一个元组,该元组保留所传递序列中元素的计数。由于返回值是一个迭代器,直接访问它并没有多大用处。enumerate() 的一个更好的方法是在 for 循环中保持计数。
>>> for i, n in enumerate(names): print('Names number: ' + str(i)) print(n) Names number: 0 Rajesh Names number: 1 Rahul Names number: 2 Aarav Names number: 3 Sahil Names number: 4 Trevor
标准库中还有许多其他函数,这里是一些更广泛使用的函数的另一个列表 -
hasattr、getattr、setattr和delattr,它们允许通过字符串名称来操作对象的属性。
all和any,接受可迭代对象,如果所有或任何项目评估为 true,则返回True 。
nzip,它接受两个或多个序列并返回一个新的元组序列,其中每个元组包含每个序列的单个值。
文件输入/输出
文件的概念与术语“面向对象编程”相关。Python 封装了操作系统提供的抽象接口,使我们能够使用文件对象。
open ()内置函数用于打开文件并返回文件对象。它是最常用的带有两个参数的函数 -
open(filename, mode)
open() 函数调用两个参数,第一个是文件名,第二个是模式。这里的模式可以是'r'表示只读模式,'w'表示只写(同名的现有文件将被删除),'a'打开文件进行追加,写入文件的任何数据都会自动添加到最后。'r+' 打开文件以进行读取和写入。默认模式为只读。
在 Windows 上,模式后附加“b”将以二进制模式打开文件,因此还有“rb”、“wb”和“r+b”等模式。
>>> text = 'This is the first line' >>> file = open('datawork','w') >>> file.write(text) 22 >>> file.close()
在某些情况下,我们只想追加到现有文件而不是覆盖它,因为我们可以提供值“a”作为模式参数,以追加到文件末尾,而不是完全覆盖现有文件内容。
>>> f = open('datawork','a') >>> text1 = ' This is second line' >>> f.write(text1) 20 >>> f.close()
一旦打开文件进行读取,我们就可以调用 read、readline 或 readlines 方法来获取文件的内容。read 方法将文件的全部内容作为 str 或 bytes 对象返回,具体取决于第二个参数是否为“b”。
为了提高可读性,并避免一次性读取大文件,通常最好直接在文件对象上使用 for 循环。对于文本文件,它将读取每一行,一次一行,我们可以在循环体内处理它。然而,对于二进制文件,最好使用 read() 方法读取固定大小的数据块,并传递要读取的最大字节数的参数。
>>> f = open('fileone','r+') >>> f.readline() 'This is the first line. \n' >>> f.readline() 'This is the second line. \n'
写入文件,通过文件对象的 write 方法将字符串(二进制数据的字节)对象写入文件。writelines 方法接受字符串序列并将每个迭代值写入文件。writelines 方法不会在序列中的每个项目后附加新行。
最后,当我们完成读取或写入文件时,应该调用 close() 方法,以确保所有缓冲的写入都写入磁盘,文件已被正确清理,并且与文件相关的所有资源都被释放回操作系统。调用 close() 方法是更好的方法,但从技术上讲,当脚本存在时,这会自动发生。
方法重载的替代方案
方法重载是指拥有多个具有相同名称的方法,这些方法接受不同的参数集。
给定一个方法或函数,我们可以自己指定参数的数量。根据函数定义,可以使用零个、一个、两个或多个参数来调用它。
class Human: def sayHello(self, name = None): if name is not None: print('Hello ' + name) else: print('Hello ') #Create Instance obj = Human() #Call the method, else part will be executed obj.sayHello() #Call the method with a parameter, if part will be executed obj.sayHello('Rahul')
输出
Hello Hello Rahul
默认参数
函数也是对象
可调用对象是可以接受一些参数并且可能返回一个对象的对象。函数是 Python 中最简单的可调用对象,但也有其他对象,例如类或某些类实例。
Python 中的每个函数都是一个对象。对象可以包含方法或函数,但对象不一定是函数。
def my_func(): print('My function was called') my_func.description = 'A silly function' def second_func(): print('Second function was called') second_func.description = 'One more sillier function' def another_func(func): print("The description:", end=" ") print(func.description) print('The name: ', end=' ') print(func.__name__) print('The class:', end=' ') print(func.__class__) print("Now I'll call the function passed in") func() another_func(my_func) another_func(second_func)
在上面的代码中,w