Python 进阶 — 面向对象编程
目录
文章目录
- 目录
- 面向对象思想
- 面向对象编程
- 面向对象编程的特性
- 封装
- 继承
- 多态
- 面向对象编程的优势
- Python 的类属性与类方法
- Python 类的实例化
- Python 的对象属性与对象方法
- Python 类的继承
- 单重继承
- 多重继承
面向对象思想
面向对象不仅是一种编程思想,更是解决问题和处理数据的方式,面向对象是一种对现实世界的理解和抽象的方法。
以面向对象思想为基础发展而来的技术主要有:
- OOA(Object Oriented Analysis,面向对象的分析)
- OOD(Object Oriented Design,面向对象的设计)
- OOP(Object Oriented Programming,面向对象的编程实现)
面向对象编程
面向对象编程,又称为面向对象的程序设计,简称 OOP,本质是一种程序设计的范型,也是计算机编程技术发展到一定阶段后的产物。
在客观世界中,对象是人们要进行研究的任何 “事” 或 “物”,例如:某些规则、计划或事件等等概念上的 “事”,以及某些动物、汽车或书籍等等实际上的 “物”。
在数字世界中,对象(Object)实现了数据和操作的结合,使数据和操作封装到对象的统一个体中。主要具有两个特征:
- 对象状态:通过某些 “数据” 来描述一个对像的状态。
- 对象行为:通过某些 “操作” 来改变一个对象的状态。
同样在数字世界中,类(Class)则是对具有相同状态(数据)和行为(操作)的对象的抽象。
- 类属性:是对象状态的抽象,用数据结构来描述。
- 类方法:是对象行为的抽象,用实现特定操作的方法来描述。
因此,在很多 OOP 编程语言中,对象的抽象就是类,类的实例(具体)化就是对象。抽象指将具有一致的 “状态” 和 “行为” 的某种对象,抽象为具有统一 “属性” 和 “方法” 的类。类的抽象划分往往是主观的,应该要反映与程序应用相关的重要性质,而忽略其他一些无关的内容。
简而言之,OOP 是以 “数据” 和 “操作” 为中心的,通过数据结构设计来组织数据,并提供对此类数据所允许的操作。计算机程序的本质就是 “数据结构 + 算法”。
面向对象编程的特性
封装
封装,顾名思义是 “封闭性的包装”,其目的是将 “数据” 以及 “行为” 进行适度的隐藏,通过 “接口” 的方式进行暴露,使的代码逻辑模块化(松耦合、高内聚)。具体地说,在类的定义和实现时,需要为数据提供相应的接口,以免 Client 对数据进行不规范的操作。
被封装好的每个类都是独立的,由类所实例化得到的任何对象也都具有唯一性。OOP 中的对象都应该能够接受数据、处理数据、传达数据给其他的对象。并且对象之间只能够通过 “消息” 来进行通信。在对象的操作中,当一个消息发送给某个接收对象时,消息应该包含了该接收对象去执行某种操作的数据。
可见,封装能够实现:类的属性和方法能够只让可信的类或者对象进行操作,对不可信的操作进行信息隐藏。为类和对象中的属性、方法提供了安全的保障。具体的说,在一个对象内部,某些数据或行为可以是 Private(私有的),它们不能被外界访问。
换言之,一个类就是一个封装了数据以及操作这些数据的方法的逻辑实体。OOP 通过类和对象的封装技术以及消息机制,使得编程可以像搭积木的一样快速开发出一个全新的系统。
继承
继承使得不同的类之间拥有了一定的结构与关系。
继承是一种子类自动继承父类属性和方法的机制,在定义和实现一个子类的时候,可以在一个已经定义好的夫类的基础之上进行,加入若干新的内容,这些都不会影响到父类。所以,继承所带来的最明显的好处在于代码的可重用性。
继承的实现方式大致上有 2 大类、4 小类:
- Inheritance(继承),又名 “单重继承”:子类只继承一个父类的属性和方法。
- 实现继承:子类的属性和方法完全继承于父类。
- 可视继承:子类继承了父类的外观和方法。
- Composition(组合),又名 “多重继承”:子类继承了多个父类的属性和方法。
- 接口继承:子类的属性命和方法名继承于父类,但是具体的属性值和方法实现由子类重写。
- 纯虚类
注意,在实现多重继承时,如果继承的多个父类中均有名称相同的属性或方法时,要注意继承的顺序。
多态
多态指对于相同的类方法或函数,可作用于多种类型的对象上,并获得不同的结果,即:在不同的对象中可以拥有相同名称的属性或方法,但是属性值或方法实现却各不相同。也就是说,多种类型的对象都可以使用同一个类方法或函数,并且可以得到相应且不同的结果。这种现象称为多态性。
多态使得不同的对象能够通过它们共同的属性和方法来进行操作,而不需考虑它们具体的类型是否相同,继而使得动态绑定(运行时)成为了可能,允许重载及运行时类型确定。
多态常用于 “接口重用” 场景,保证了在类发生继承时,仍然能够正确的调用这些相关类的实例化对象的属性和方法。
面向对象编程的优势
- 以人更容易理解的方式对复杂的系统进行分析和设计。
- 降低开发难度:模块之间、组件之间、系统之间通过 API 来进行交互,以此屏蔽底层复杂性。
- 提高代码重用性:继承和多态提供了极高的代码重用性。
- 提到软件架构的可扩展性:松耦合的模块化设计,对单一模块的修改并不会影响到整合系统。
Python 的类属性与类方法
现在 Python 主流的类定义是 “新式类定义”,要求每个类都必须至少继承一个父类,如果没有特定的父类时,则继承基类 object。
Python 使用 cls 关键字来作为类的句柄。
- 类方法:将 cls 关键字作为第一个形式参数。当类通过句点标识符来调用一个类方法时,Python 解析器会隐式的将类的引用作为实参传递给 cls 形参。在类方法中可以直接使用 cls 关键字来调用类属性或方法。
使用类方法修饰符来进行声明:
class NewClass(object):@classmethodfoo(cls):pass
- 类属性:在类体中直接定义,是一个与具体某个对象无关的属性。所以类属性只能通过类方法或类调用来进行访问或更新。相对于对象属性而言,类属性更加 “静态”,当类属性被定义在了类方法中时,该类属性并不会因为类方法调用完毕而被回收,直到这个类被回收为止。
特殊的类属性:
__name__
:类的名字__module__
:类的模块名称__dict__
:类的属性和方法映射字典__class__
:类实例化对象的类名称
Python 类的实例化
类的构造器 __new__()
是一个类方法,用于实例化(生成)一个对象,再将该对象传入 __init__()
实现初始化操作。
实际上 __new__()
通常不需要进行重载,一般只会在派生 Python build-in 的不可变类型(e.g. string、float etc…)的子类时候(从标准类中进行派生)才需要。例如:通过重载 float 的构造器 __new__()
来定制一个新的不可变类型 RoundFloat。
class RoundFloat(float):def __new__(cls, val):return float.__new__(cls, round(val, 2))
而 __init__()
则是一个对象方法,用于在构造器实例化了对象之后,执行一些特定的初始化工作。它在实例化一个新的对象时被自动调用,所以除了初始化对象属性之外,还常被用于运行一些初步的诊断代码。
需要注意的是,在继承中,基类的 __init__()
不会被自动调用,需要在子类的 __init__()
中进行显式调用。
Python 的对象属性与对象方法
Python 使用 self 关键字来作为对象的句柄,类似于 Java 的 this 关键字,用于支撑封装特性,保证同一个类的多个对象之间的数据隔离安全。对象属性和对象方法都会绑定到 self,表示绑定到一个具体的对象。
- 对象属性:通过 self 调用的属性。
- 对象方法:第一个形参为 self 的方法。
使用 self 来标识对象方法时,self 会作为第一个形参。当对象通过句点标识符来调用一个对象方法时,Python 解析器会隐式的将对象的引用作为实参传递给 self 形参。
其中,对象的 __dict__
属性是一个包含了所有对象属性和方法的字典,方 Python 解析器访问一个对象属性或方法时,就会在这个字典中搜索。如果在该类的字典中没有搜索到,那么就会按照位置先后的顺序逐一到父类的字典中搜索。如此的,就能够将不同类之间的命名隔离开来,在子类中对 __dict__
字典的修改并不会影响到父类。
Python 类的继承
子类会继承父类所有公开的(public)属性和方法,或者在子类中对这些属性和方法进行重载。反过来说,子类不能够继承父类中私有的(Private)属性和方法(以 __
为前缀的命名)。
子类也同样应该拥有自己的类初始化器,这意味着在实例化子类的对象时,需要同时传递子类和父类的类初始化器所要求的实参列表,且需要在子类初始化器中显式的调用父类初始化器来完成实参的传递。
另外,由于 Python 是支持多重继承的,所以 Python 提供了 super()
build-in 函数来实自动且准确的找出子类的父类来进行继承。也因此,在进行多重继承时,要严格注意父类列表的顺序位置。
在一些复杂的继承关系中,Python 需要通过 C3 或 MRO 算法来将类图转换成序列。MRO 算法,可实现以下几个理想特性:
- 每个祖先类只出现一次。
- 单调性:子类总是出现在其祖先类之前。
- 一致的本地优先顺序:同一类的直接父类应按照类定义中列出的顺序显示。
- 一致的扩展优先顺序:如果 A 类的子类总是出现在 B 类的子类之前,则 A 应出现在 B 类之前。
单重继承
class Car():"""这是一个汽车类"""def __init__(self, brand, color):self.brand = brandself.color = colordef run(self, s):print("当前行驶速度:%s KM/S" % s)class OilCar(Car):"""这是燃油汽车类"""def __init__(self, car_power, brand, color):super().__init__(brand, color)self.car_power = car_powerdef Info(self):print("子类中调用父类方法:", self.run(444))class Oil(OilCar):def __init__(self,car_power, brand, color, oilInfo):super().__init__(car_power, brand, color)self.oilInfo = oilInfodef oil_info(self):print(self.brand)print(self.Info())oil = Oil("燃油","宝马","蓝色","汽油")
oil.oil_info()
多重继承
多重继承一般会有两种继承方式:
- 链式继承:A 继承 B,B 继承 C。
- 菱形继承:A继承 B 和 C(B、C 无关系)。
class A(object):def __init__(self, aval, **kwargs):print("A: rcd value: ", aval)self.aval = avalsuper().__init__(**kwargs)class B(object):def __init__(self, b1val ,b2val, **kwargs):print("B: rcd 2 values: ",b2val)self.b1val = b1valself.b2val = b2valsuper().__init__(**kwargs)class C(A, B):def __init__(self, a, b, c, **kwargs):super().__init__(aval=a, b1val=b, b2val=c, **kwargs)c = C(1, 2, 3)
在多重继承中需要避免重复继承一个类,可能会造成一些错误。例如:
class A(object):def __init__(self, name):self.name = namedef get(self):return self.nameclass B(A):def get(self):super(B, self).get()class C(A,B):def get(self):super(C, self).get()c = C("Name")# TypeError: Cannot create a consistent method resolution
Python 进阶 — 面向对象编程相关推荐
- python进阶 多线程编程 —— threading和queue库实现多线程编程
python进阶 多线程编程 -- threading和queue库实现多线程编程) 摘要 多线程实现逻辑封装 模型参数选择实例 摘要 本文主要介绍了利用python的 threading和queue ...
- python用类名直接调用方法_一文读全 Python 的面向对象编程方法
背景介绍: Python 支持三种形式的编程,分别是:"命令式"."函数式"和"面向对象式". 很多优秀的开源 Python 项目里都用到了 ...
- Python进阶-----面向对象2.0(特有属性和方法与私有属性和方法)
目录 前言: 1.添加特有属性/方法 示例1:添加特有属性 示例2:添加特有方法 2.私有属性/方法 (1)私有化示例 (2) 私有化属性/方法可以在类的内部使用 (3)强制访问私有化属性/方法 (4 ...
- python基础 面向对象编程
目录 面向对象编程 1.什么是面向对象编程? 面向过程编程思想 面向对象编程思想 2.什么是类?如何定义. 类: 对象 3.如何产生对象? 调用类时的事件: 4.对象属性的查找顺序: 5.类内部的函数 ...
- Python设计模式面向对象编程
前言 本篇文章是基于极客时间王争的<设计模式之美>做的总结和自己的理解. 说到面向对象编程,作为一个合格的Pythoner,可以说信手拈来.毕竟在Python里"万物都是对象 ...
- 零基础入门学习Python(35)面向对象编程
self是什么? Python的self相当于C++的this指针 由同一个类可以生成无数对象,当一个对象的方法被调用的时候,对象会将自身的引用作为第一个参数传给该方法,Python就知道要操作哪个对 ...
- Python基础-面向对象编程
本文完全转载自廖雪峰大神的教程: 面向对象编程 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数 ...
- python的面向对象编程学生成绩_python的类_面向对象编程
摘自谬雪峰https://www.liaoxuefeng.com/wiki/1016959663602400/1017496031185408 面向对象编程(定义对象)和面向过程(定义函数)的区别,各 ...
- python采用面向对象编程模式吗_在python中,面向对象还有用吗?
面向对象是一种编程思想,跟语言无关. 任何人但凡稍微看一下面向对象的概念和意义就会知道,目前的工程化的编程是不可能脱离面向对象的.例如编程语言界的扛把子 Java 就是完全的面向对象语言,用 Java ...
最新文章
- jenkins需安装插件总结
- WindowManager.LayoutParams类22
- 压缩追踪Compressive Tracking源码理解
- POJ - 2559 Largest Rectangle in a Histogram(笛卡尔树,单调栈实现)
- 处理SAP gateway service使用过程中遇到的400 error - Malformed URI literal syntax
- 架构为什么要以领域为核心
- Maven的Scored介绍
- Linux内核CPU负载均衡机制
- SQL中Case的使用方法(上篇)
- MacBooster CleanMyMac CCleaner三款Mac清理工具该如何选择
- 搭建安卓开发环境并测试运行安卓开发环境
- 指针数组与二维数组指针的本质区别
- 夏天来了,教你怎么选西瓜
- “小度小度”开启AI硬件的“量贩”时代
- base64转MultipartFile并压缩得到压缩后对的MultipartFile
- 智能工厂体系,主要划分为哪五个层级?
- 用ASP.NET实现简单的超市管理系统-登录页面
- 性能监控命令vmstat详解【杭州多测师】【杭州多测师_王sir】
- [iOS开发]Category、Extension和关联对象
- 移动护理、护士工作站 UI界面及业务
热门文章
- PlayMaker的特殊事件FINISHED
- Wireshark数据抓包教程之认识捕获分析数据包
- 北京语言大学计算机调剂,北京语言大学2019考研调剂通知
- localdate转date时区问题_时间戳和LocalDateTime和Date互转和格式化
- 如何维持手机电池寿命_一块能用百年的手机电池将诞生,你愿意花高价购买吗?...
- flowable设计器节点属性扩展_Flowable-流程定义扩展属性
- mysql -d_mysqld
- 在世界第二届半机械人奥运会上,瘫痪驾驶员在Cybathlon BCI竞赛中争夺金牌
- eeglab中文教程系列(4)-预处理工具
- c语言链表拆分,C语言拆分链表程序