一、面向对象,这个对象到底是什么?
这个对象不是python中的实例,python中我们把一个类的实例也叫做对象,这种对象严格的说应该是面向对象的编程实现(OOP)中的对象,面向对象编程,也不是面向类的实例编程。对象的定义是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。也有的定义为“一切都是对象”然而面向对象也不能简单的等价理解成面向任何事物编程,面对一切编程?开玩笑,呵呵。
因此面向对象这个对象,指的是客体。所谓客体是指客观存在的对象实体和主观抽象的概念。
二、面向对象程序设计的由来
1、编程语言的发展
程序设计这东西一开始出现,是按照人类的语言习惯,将尽量符合人类语言的语法结构来描述要实现的功能,然后通过各种软件环境[XX语言编译器、XX语言解释器]将这样符合人类语言的语法编译或者解释成计算机能认识和执行的语言去执行并实现功能的过程,于是出现了高级语言。
2、面向过程的程序设计
高级语言出现之初,程序设计的思路,也是参考了人类解决问题的思路;
遇到一个问题,人类习惯性的思维方式是第一步做什么、第二步做什么、紧接着做什么,这样按照一定的步骤一直到实现最终想要的功能。
这样的按照事情/功能的处理过程和步骤来进行程序的设计和开发的过程,是一种解决问题的思路,我们称之为:面向过程的程序设计
3、面向过程程序设计的缺陷
面向过程的程序设计发展了一定的时间之后,我们发现出现了一个非常重要的问题,如果仅仅是处理某一个功能的流程而言非常适合,但是如果一旦涉及到业务过程比较复杂的系统来说的话,面向过程的思路设计的程序出现了大量的代码冗余、同时不同的功能之间的冲突随着系统功能的增多冲突越来越多,另外当系统中的某些功能如果需要升级或者改动,会涉及到大量的代码的修改和功能的影响造成维护的不方便
4、面向对象
这时候,一帮大佬们围坐在一起,开始商量怎么样让我们的程序更加适合开发结构完整、流程复杂的系统项目呢!
有人就提出了,我们的程序,其实一直都是在模拟符合正常人的思维逻辑习惯的,小功能的处理就像我们处理一件小事一样,可以按照步骤进行处理,也就是按照面向过程的设计思路进行处理;
三、首先看看面向对象的三大特征:
封装:将对象的敏感的信息封装在对象的内部,不让外界直接访问,提高数据的安全性
继承:通过继承关系,梳理对象和对象之间的关系,同时提高了程序设计功能的强大的扩展性和代码的复用性
多态:程序在运行过程中,实时根据不同的数据执行不同的处理逻辑展现不同的状态,让程序的功能更加的完善健壮
因此面向对象能实现人们追求的系统可维护性,可扩展性,可重用性。面向对象是一种编程思想,起初,“面向对象”是专指在程序设计中采用封装、继承、多态等设计方法,但面向对象的思想已经涉及到软件开发的各个方面,比如现在细分为了面向对象的分析(OOA),面向对象的设计(OOD),面向对象的编程实现(OOP)
四、面对对象编程,分为几个步骤?
面向对象是一种思想,他让我们在分析和解决问题时,把思维和重点转向现实中的客体中来,然后通过工具理清这些客体之间的联系,最后用面向对象的语言实现这种客体以及客体之间的联系。它分为面向对象的分析(OOA),面向对象的设计(OOD),面向对象的编程实现(OOP)三个大的步骤。
1、首先是分析需求,先不要思考怎么用程序实现它,先分析需求中稳定不变的客体都是些什么,这些客体之间的关系是什么。
2、把第一步分析出来的需求,通过进一步扩充模型,变成可实现的、符合成本的、模块化的、低耦合的模型。
3、使用面向对象的实现模型
五、面向过程到面向对象思维如何转变?
当我们习惯了面向过程编程时,发现在程序过程中到处找不到需要面向对象的地方,最主要的原因,是思维没有转变。程序员通常在拿到一个需求的时候,第一个反应就是如何实现这个需求,这是典型的面向过程的思维过程,而且很快可能就实现了它。而面向对象,面对的却是客体,第一步不是考虑如何实现需求,而是进行需求分析,就是根据需求找到其中的客体,再找到这些客体之间的联系。因此面向过程和面向对象的思维转变的关键点,就是在第一步设计,拿到需求后,一定先不要考虑如何实现它,而是通过建模,然后按照模型去实现它。这种思路的转变,可能需要个过程。
六、Python3面向对象
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。下面将详细介绍Python的面向对象编程。
如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。
接下来我们先来简单的了解下面向对象的一些基本特征。
面向对象技术简介
类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
实例变量:定义在方法中的变量,只作用于当前实例的类。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
方法:类中定义的函数。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
和其它编程语言相比,Python在尽可能不增加新的语法和语义的情况下加入了类机制。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
类定义
语法格式如下:
Class类名称:
Pass
类的组成:类名称、属性、方法
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名称访问其属性。
类对象
类的对象支持两种操作:属性引用和实例化。
属性引用使用和Python中所有的属性引用一样的标准语法:obj.name。
类的对象创建后,类命名空间中所有的命名都是有效属性名。U = User
创建对象的过程:
首先,用创建的类型的__new__()函数创建对象
其次,调用__init__()函数初始化对象的数据
Self关键字
self代表对象本身,可以是任意变量,则必须放在第一个参数位,但是规范要求必须使用self。
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,按照惯例它的名称是self。
类的方法
在类的内部,用def来定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数,self代表的是类的实例。
面向对象的特征——封装
封装?将对象敏感的数据封装在类的内部,不让外界直接访问,而是通过当前类提供的set/get方法间接访问数据,此时就可以在set/get中添加限制条件进行访问数据的控制。
封装实现的步骤:
定义类型,封装零散数据【抽象的属性】
[使用__slots__属性,限制当前类的属性列表为了代码的统一性]
所有属性私有化【属性使用双下划线开头,外界就不能直接访问这样的属性了】
给每个属性提供set/get方法,在方法中添加限制条件
高级封装
使用@property和@get_method.setter注解,来注释set/get方法,隐藏set/get方法的实现,让方法的使用方式和属性一致
伪方法重载:python中,默认不提供方法重载,但是在高级封装的过程中,又出现了类似方法重载的代码语法,所以~称之为伪方法重载。
对方法的封装
在封装的过程中,除了封装私有属性,还可以针对一些底层的操作方法进行私有化,将方法封装在类的内部,通过提供的一个公共方法来控制该方法的访问权限
再说各种变量
全局变量:程序中任何位置都可以访问的数据;声明在类的外部
变量/类属性:当前类创建的各种对象,可以共享的数据;声明在类的内部,方法的外部
员变量/成员属性:【创建的指定对象的特征】被对象所私有,对象之间不能使用对方的数据
局部变量:声明在对象的方法或者函数中,函数中有效,出了函数无效【变量销毁】
面向对象的特征——继承
继承?一个类型继承另一个类型,当前类型就会拥有另一个类型的公共的属性和方法,达到代码的重复使用的目的。
继承的语法:
class类型(被继承的类型):
pass
继承中出现的术语:
父类:被继承的类,也称为基类、超类
子类:当前类,也称为派生类
子类继承父类,体现的时A is a B的关系
子类继承父类,就可以使用父类中所有的公开的属性和方法
继承链
A继承B,B继承C,C继承D
接继承了B,间接继承了C,D;此时A创建的对象,可以同时使用B,C,D所有公开的属性和方法
那么问题又来了,多继承呢?
·是否可以继承多个类
·如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?
1、Python的类可以继承多个类,Java和C#中则只能继承一个类
2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:
深度优先和广度优先
·当类是经典类时,多继承情况下,会按照深度优先方式查找
·当类是新式类时,多继承情况下,会按照广度优先方式查找
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
经典类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
新式类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
注意:在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
python中,一个类型,可以同时继承多个类型,同时拥有所有继承类型的所有公开的属性和方法
备注:在进行代码设计的过程中,可能会出现多继承,所以尽量不要在父类中定义相同名称的属性或者方法
备注2:如果父类中出现了相同名称的属性和方法,在使用的时候子类调用时会优先继承优先调用。
方法重写:
类在自己类中重新定义父类中已经存在的方法,在执行该方法时,如果子类中没有重写就直接调用父类的方法,如果子类重写了该方法,就直接调用子类重写的方法!
扩展:子类中,访问父类的属性和方法:
class User(Person):
def __init__(self, name, age):
#直接通过父类的类名称调用父类的属性和方法
Person.__init__(name, age)
#通过super()来调用父类的属性和方法
super().__init__(name, age)
面向对象的特征:多态
程序在运行的过程中,根据传递的参数的不同,执行不同的函数或者操作不同的代码,这种在运行过程中才确定调用的方式成为运行时多态
态即多种形态,在运行时确定其状态,在编译阶段无法确定其类型,这就是多态。Python中的多态和Java以及C++中的多态有点不同,Python中的变量是弱类型的,在定义时不用指明其类型,它会根据需要在运行时确定变量的类型(个人觉得这也是多态的一种体现),并且Python本身是一种解释性语言,不进行预编译,因此它就只在运行时确定其状态,故也有人说Python是一种多态语言。在Python中很多地方都可以体现多态的特性,比如内置函数len(object),len函数不仅可以计算字符串的长度,还可以计算列表、元组等对象中的数据个数,这里在运行时通过参数类型确定其具体的计算过程,正是多态的一种体现。
Python以它这种独有的方式体现多态的根本原因我觉得有两点:
1)Python是解释性语言;
2)Python中变量是弱类型的。