首页 后端开发 Python教程 Python面向对象编程(二)

Python面向对象编程(二)

Jul 09, 2017 pm 06:13 PM
python 编程 面向

1.继承与派生

上文我们已经说过,Python中一切皆对象。我们从对象中抽取了共同特征和技能,得到了类的概念。类与类之间也有共同特征,我们可以从有共同特征和技能的类中提取共同的技能和特征,叫做父类。

比如老师和学生,都有名字,年纪,生日,性别等等,都会走,说话,吃饭。。。我们就可以从老师和学生中总结出来一个‘人’类,称为父类,那老师和学生就是‘人’类的子类,子类继承父类,就有了父类的特征和方法。

继承是一种什么‘是’什么的关系,继承是一种产生新类的方法,当然目的也是为了减少代码重用。

继承的 基本形式是:

<span style="color: #0000ff">class</span><span style="color: #000000"> People:
    </span><span style="color: #0000ff">pass</span>
<span style="color: #0000ff">class</span> Student(People):<span style="color: #008000">#</span><span style="color: #008000">People称为基类或者父类</span>
    <span style="color: #0000ff">pass</span>
登录后复制

在Python中支持多继承,一个子类可以继承多个父类

我们可以通过__bases__的方法查看继承的所有父类,会返回一个元组。 

<span style="color: #0000ff">class</span><span style="color: #000000"> People:
    </span><span style="color: #0000ff">pass</span>
<span style="color: #0000ff">class</span><span style="color: #000000"> Animals:
    </span><span style="color: #0000ff">pass</span>
<span style="color: #0000ff">class</span><span style="color: #000000"> Student(People,Animals):
    </span><span style="color: #0000ff">pass</span>

<span style="color: #0000ff">print</span>(Student.<span style="color: #800080">__bases__</span>)<span style="color: #008000">#</span><span style="color: #008000">(<class '__main__.People'>, <class '__main__.Animals'>)</span>
<span style="color: #0000ff">print</span>(People.<span style="color: #800080">__bases__</span>)<span style="color: #008000">#</span><span style="color: #008000">(<class 'object'>,)</span>
登录后复制

可以看到,在People父类中,默认也继承了一个object类,这就是新式类和经典类的区别:
凡是继承了object类的类及其子类,都称为新式类,没有继承object类的类,称为经典类。

在Python 3中,默认就是新式类,而在Python2.X中,默认都是是经典类

继承怎么减少代码呢?看例子

<span style="color: #0000ff">class</span><span style="color: #000000"> People:
    </span><span style="color: #0000ff">def</span> <span style="color: #800080">__init__</span><span style="color: #000000">(self,name,age):
        self.name</span>=<span style="color: #000000">name
        self.age</span>=<span style="color: #000000">age
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> walk(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">%s is walkig</span><span style="color: #800000">'</span>%<span style="color: #000000">self.name)

</span><span style="color: #0000ff">class</span><span style="color: #000000"> Teacher(People):
    </span><span style="color: #0000ff">def</span> <span style="color: #800080">__init__</span><span style="color: #000000">(self,name,age,level):
        People.</span><span style="color: #800080">__init__</span><span style="color: #000000">(self,name,age)
        self.level</span>=<span style="color: #000000">level

t1</span>=Teacher(<span style="color: #800000">'</span><span style="color: #800000">zhang</span><span style="color: #800000">'</span>,18,10<span style="color: #000000">)
</span><span style="color: #0000ff">print</span>(t1.level) <span style="color: #008000">#</span><span style="color: #008000">10</span>
<span style="color: #0000ff">print</span>(t1.name)  <span style="color: #008000">#</span><span style="color: #008000">zhang          子类可以用父类定义的属性</span>
t1.walk()   <span style="color: #008000">#</span><span style="color: #008000">zhang is walking   子类无需定义就可以用父类的方法</span>
<span style="color: #0000ff">print</span>(issubclass(Teacher,People))   <span style="color: #008000">#</span><span style="color: #008000">True查看Teacher类是不是People类的子类</span>
登录后复制

从上面的例子中可以看到,Teacher类继承了父类People类,但是Teacher又有自己特有的属性level,子类也可以定义自己独有的方法,甚至可以和父类的方法重名,但是执行时会以子类定义的为准。

这就叫做派生

2.组合

继承是解决什么‘是’什么的问题,那还有一种场景就是什么有什么,比如老师有生日,学生也有生日,生日有年月日这些属性,如果每个类都写的话,又是重复代码。但是又不能让学生和老师继承生日类。这时就用到了组合。组合就是解决什么‘有’什么的问题。看例子

<span style="color: #0000ff">class</span><span style="color: #000000"> Date:
    </span><span style="color: #0000ff">def</span> <span style="color: #800080">__init__</span><span style="color: #000000">(self,year,mon,day):
        self.year</span>=<span style="color: #000000">year
        self.mon</span>=<span style="color: #000000">mon
        self.day</span>=<span style="color: #000000">day
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> tell_birth(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">出生于%s年%s月%s日</span><span style="color: #800000">'</span>%<span style="color: #000000">(self.year,self.mon,self.day))

</span><span style="color: #0000ff">class</span><span style="color: #000000"> Teacher:
    </span><span style="color: #0000ff">def</span> <span style="color: #800080">__init__</span><span style="color: #000000">(self,name,age,year,mon,day):
        self.name</span>=<span style="color: #000000">name
        self.age</span>=<span style="color: #000000">age
        self.birth</span>=<span style="color: #000000">Date(year,mon,day)
t</span>=Teacher(<span style="color: #800000">'</span><span style="color: #800000">egon</span><span style="color: #800000">'</span>,19,2010,10,10<span style="color: #000000">)
</span><span style="color: #0000ff">print</span>(t.birth)          <span style="color: #008000">#</span><span style="color: #008000"><__main__.Date object at 0x0000017E559380F0></span>
t.birth.tell_birth()    <span style="color: #008000">#</span><span style="color: #008000">出生于2010年10月10日</span>
登录后复制

什么?嫌参数太多?*args学过吧,你高兴就好

<span style="color: #008080"> 1</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Date:
</span><span style="color: #008080"> 2</span>     <span style="color: #0000ff">def</span> <span style="color: #800080">__init__</span><span style="color: #000000">(self,year,mon,day):
</span><span style="color: #008080"> 3</span>         self.year=<span style="color: #000000">year
</span><span style="color: #008080"> 4</span>         self.mon=<span style="color: #000000">mon
</span><span style="color: #008080"> 5</span>         self.day=<span style="color: #000000">day
</span><span style="color: #008080"> 6</span>     <span style="color: #0000ff">def</span><span style="color: #000000"> tell_birth(self):
</span><span style="color: #008080"> 7</span>         <span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">出生于%s年%s月%s日</span><span style="color: #800000">'</span>%<span style="color: #000000">(self.year,self.mon,self.day))
</span><span style="color: #008080"> 8</span> 
<span style="color: #008080"> 9</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Teacher:
</span><span style="color: #008080">10</span>     <span style="color: #0000ff">def</span> <span style="color: #800080">__init__</span>(self,name,age,*<span style="color: #000000">args):
</span><span style="color: #008080">11</span>         self.name=<span style="color: #000000">name
</span><span style="color: #008080">12</span>         self.age=<span style="color: #000000">age
</span><span style="color: #008080">13</span>         self.birth=Date(*<span style="color: #000000">args)
</span><span style="color: #008080">14</span> t=Teacher(<span style="color: #800000">'</span><span style="color: #800000">egon</span><span style="color: #800000">'</span>,19,2010,10,10<span style="color: #000000">)
</span><span style="color: #008080">15</span> <span style="color: #0000ff">print</span>(t.birth)          <span style="color: #008000">#</span><span style="color: #008000"><__main__.Date object at 0x0000017E559380F0></span>
<span style="color: #008080">16</span> t.birth.tell_birth()    <span style="color: #008000">#</span><span style="color: #008000">出生于2010年10月10日</span>
登录后复制
View Code

3.抽象类与接口

继承有两种用途:1.代码重用,子类继承父类的方法

        2.声明某个子类兼容于某父类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

需要注意的是,Python中并没有接口的关键字,我们只能是模仿接口的功能
比如在 Python中,一切皆文件嘛,那程序是文件,硬件是文件,文本文档也是文件,我们知道什么叫文件呢,就是能读能写,那程序,文本文档这些,都应该有读和写的功能,我们来模拟一下

<span style="color: #0000ff">class</span><span style="color: #000000"> Interface:
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> read(self):
        </span><span style="color: #0000ff">pass</span>
    <span style="color: #0000ff">def</span><span style="color: #000000"> write(self):
        </span><span style="color: #0000ff">pass</span>
    
    
<span style="color: #0000ff">class</span><span style="color: #000000"> Txt(Interface):
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> read(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">文本文档的读取方式</span><span style="color: #800000">'</span><span style="color: #000000">)
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> write(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">文本文档的写入方式</span><span style="color: #800000">'</span><span style="color: #000000">)
        
</span><span style="color: #0000ff">class</span><span style="color: #000000"> Sata(Interface):
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> read(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">硬盘文件的读取方式</span><span style="color: #800000">'</span><span style="color: #000000">)
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> write(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">硬盘文件的写入方式</span><span style="color: #800000">'</span><span style="color: #000000">)

</span><span style="color: #0000ff">class</span><span style="color: #000000"> process(Interface):
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> read(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">进程数据的读取方式</span><span style="color: #800000">'</span><span style="color: #000000">)
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> write(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">进程数据的写入方式</span><span style="color: #800000">'</span>)
登录后复制
View Code

这么做的意义就是:我们不需要知道子类有什么具体的方法,既然他们继承了文件类,那他们就是文件,那他们就有读和写这两个功能

父类限制了子类子类必须有read和write这两个方法,而且名字也必须一样(当然现在只是我们主观上的限制,一会我们说完抽象类,就可以从代码级别上限制了),这样就实现了统一,模拟了接口的概念,这就是归一化设计。在归一化设计中,只要是基于一个接口设计的类,那么所有的这些类实例化出来的对象,在用法上是一样的

我们再来说一下抽象类:

Python中的抽象类需要导入一个模块来实现。抽象类只能被继承,不能被实现

抽象类的写法:

<span style="color: #0000ff">import</span><span style="color: #000000"> abc
</span><span style="color: #0000ff">class</span> File(metaclass=<span style="color: #000000">abc.ABCMeta):
    @abc.abstractmethod
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> read(self):
        </span><span style="color: #0000ff">pass</span><span style="color: #000000">
    @abc.abstractmethod
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> write(self):
        </span><span style="color: #0000ff">pass</span>
<span style="color: #008000">#</span><span style="color: #008000">父类使用了抽象类,那子类就必须继承父类的方法,而且名字也必须一样</span><span style="color: #008000">
#</span><span style="color: #008000">这样就实现了代码级别的限制</span>

<span style="color: #0000ff">class</span><span style="color: #000000"> Txt(File):
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> read(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">文本文档的读取方式</span><span style="color: #800000">'</span><span style="color: #000000">)
    </span><span style="color: #0000ff">def</span><span style="color: #000000"> write(self):
        </span><span style="color: #0000ff">print</span>(<span style="color: #800000">'</span><span style="color: #800000">文本文档的写入方式</span><span style="color: #800000">'</span>)
登录后复制

 

4.继承的实现原理

1)继承顺序:

python支持多继承,当一个类继承多个父类时,继承顺序是怎样的呢?这个顺序在新式类和经典类中是不一样的。

在新式类中,继承顺序是广度优先,在经典类中是深度优先,举个栗子:

图不重要,看内容
在这个图中,H是子类,H继承E,F,G,E,F,G,又分别继承B,C,D,B,C,D,同时继承A

在新式类中的顺序是:H E B F C G D A 

在经典类中的顺序是:H E B A F C G D

2)继承原理:

当我们定义一个类后,Python就会根据上面的继承规律解析出一个继承顺序的列表(MRO列表),可以通过mro()查看,但是这个方法只有在新式类中才有,经典类没有

mro

 

以上是Python面向对象编程(二)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP和Python:代码示例和比较 PHP和Python:代码示例和比较 Apr 15, 2025 am 12:07 AM

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。

CentOS上PyTorch的GPU支持情况如何 CentOS上PyTorch的GPU支持情况如何 Apr 14, 2025 pm 06:48 PM

在CentOS系统上启用PyTorchGPU加速,需要安装CUDA、cuDNN以及PyTorch的GPU版本。以下步骤将引导您完成这一过程:CUDA和cuDNN安装确定CUDA版本兼容性:使用nvidia-smi命令查看您的NVIDIA显卡支持的CUDA版本。例如,您的MX450显卡可能支持CUDA11.1或更高版本。下载并安装CUDAToolkit:访问NVIDIACUDAToolkit官网,根据您显卡支持的最高CUDA版本下载并安装相应的版本。安装cuDNN库:前

docker原理详解 docker原理详解 Apr 14, 2025 pm 11:57 PM

Docker利用Linux内核特性,提供高效、隔离的应用运行环境。其工作原理如下:1. 镜像作为只读模板,包含运行应用所需的一切;2. 联合文件系统(UnionFS)层叠多个文件系统,只存储差异部分,节省空间并加快速度;3. 守护进程管理镜像和容器,客户端用于交互;4. Namespaces和cgroups实现容器隔离和资源限制;5. 多种网络模式支持容器互联。理解这些核心概念,才能更好地利用Docker。

CentOS上如何进行PyTorch模型训练 CentOS上如何进行PyTorch模型训练 Apr 14, 2025 pm 03:03 PM

在CentOS系统上高效训练PyTorch模型,需要分步骤进行,本文将提供详细指南。一、环境准备:Python及依赖项安装:CentOS系统通常预装Python,但版本可能较旧。建议使用yum或dnf安装Python3并升级pip:sudoyumupdatepython3(或sudodnfupdatepython3),pip3install--upgradepip。CUDA与cuDNN(GPU加速):如果使用NVIDIAGPU,需安装CUDATool

Python vs. JavaScript:社区,图书馆和资源 Python vs. JavaScript:社区,图书馆和资源 Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

CentOS下PyTorch版本怎么选 CentOS下PyTorch版本怎么选 Apr 14, 2025 pm 02:51 PM

在CentOS下选择PyTorch版本时,需要考虑以下几个关键因素:1.CUDA版本兼容性GPU支持:如果你有NVIDIAGPU并且希望利用GPU加速,需要选择支持相应CUDA版本的PyTorch。可以通过运行nvidia-smi命令查看你的显卡支持的CUDA版本。CPU版本:如果没有GPU或不想使用GPU,可以选择CPU版本的PyTorch。2.Python版本PyTorch

PyTorch在CentOS上的数据预处理怎么做 PyTorch在CentOS上的数据预处理怎么做 Apr 14, 2025 pm 02:15 PM

在CentOS系统上高效处理PyTorch数据,需要以下步骤:依赖安装:首先更新系统并安装Python3和pip:sudoyumupdate-ysudoyuminstallpython3-ysudoyuminstallpython3-pip-y然后,根据您的CentOS版本和GPU型号,从NVIDIA官网下载并安装CUDAToolkit和cuDNN。虚拟环境配置(推荐):使用conda创建并激活一个新的虚拟环境,例如:condacreate-n

centos如何安装nginx centos如何安装nginx Apr 14, 2025 pm 08:06 PM

CentOS 安装 Nginx 需要遵循以下步骤:安装依赖包,如开发工具、pcre-devel 和 openssl-devel。下载 Nginx 源码包,解压后编译安装,并指定安装路径为 /usr/local/nginx。创建 Nginx 用户和用户组,并设置权限。修改配置文件 nginx.conf,配置监听端口和域名/IP 地址。启动 Nginx 服务。需要注意常见的错误,如依赖问题、端口冲突和配置文件错误。性能优化需要根据具体情况调整,如开启缓存和调整 worker 进程数量。

See all articles