目录:导读

  • 一、三大特性
  • 封装
  • 继承
  • 多态
  • 二、封装实现
  • 三、继承实现
  • 抽象类
  • 四、三大特性之多态实现
  • 多态性


一、三大特性

面向对象编程有三个特性:封装、继承、多态

封装

面向对象的程序设计中,某个类把所需要的数据(也可以说是类的属性)和对数据的操作(也可以说是类的行为)全部都封装在类中,分别称为类的成员变量和方法(或成员函数)。这种把成员变量和成员函数封装在一起的编程特性称为封装

继承

继承是指可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展

多态

多态指的是一类事物有多种形态。如序列类型有多种形态:字符串,列表,元组;动物有多种形态:猫,狗,猪。多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作
 

二、封装实现

封装分为数据封装与方法封装
  数据封装即把对象的属性具体的值隐藏起来,对外部显示的只是对象的属性名。比如刘泽的名字,钱包里的钱等

  方法封装即对外只需要通过方法名就能调用方法,而不需要了解具体方法中的细节。比如洗衣机,按洗衣的功能按钮,就能进行洗衣,我们不需要知道这个过程中的原理;在用支付宝进行付款的时候,只需要在用的时候把二维码给收款方或是扫一下收款方提供的二唯码就可以完成支付,不需要知道支付宝的支付接口,以及后台的处理数据的能力等

封装的作用:封装数据的主要原因是保护隐私;封装方法的主要有因是隔离复杂度

封装分为两个层面:
第一层面的封装:创建类和对象时,分别创建两者的名称空间。只能通过类名加“.”或者obj.的方式访问里面的名字

第二层面的封装:类中把某些属性和方法隐藏起来,或者定义为私有,只在类的内部使用,在类的外部无法访问,或者留下少量的接口(函数)供外部访问
 

三、继承实现

当我们定义一个class的时候,可以从某个现有的class 继承属性和方法,新的class称为子类

(Subclass),而被继承的class称为基类、父类或超类 (Base class、Super class)

如下图:

python面向对象特性 python面向对象三大特性_后端


在python中,object类是所有类的父类。Python3中默认都是继承object,称为新式类;在

python2中,不指定继承object类的类称为经典类

继承语法如下:

class 派生类名(基类名)
...

例如:

class Parent: # 定义父类
	parentAttr = 100;
	def __init__(self):
		print("调用父类构造函数");
	def parentMethod(self):
		print('调用父类方法');
class Child(Parent): # 定义子类
	def __init__(self):
		print("调用子类构造方法");
	def childMethod(self):
		print('调用子类方法');

isinstance() 及 issubclass()
Python 与其他语言不同点在于,当我们定义一个 class 的时候,我们实际上就定义了一种数据类型,我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样

Python 有两个判断继承的函数:isinstance(obj, Class) 用于检查实例类型;issubclass(sub,sup) 用于检查类继承

python中的继承特点
1.在Python中,如果父类和子类都重新定义了构造方法__init__( ),在进行子类实例化的时候,子类的构造方法不会自动调用父类的构造方法,必须在子类中显示调用

2.如果需要在子类中调用父类的方法:需要以 父类名.方法 这种方式调用,以这种方式调用的时候,注意要传递self参数过去;另一种方法是使用super() ,直接使用 super().xxx 或 super(Class, self).xxx

3.Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)

4.对于继承关系,子类继承了父类所有的公有属性和方法,可以在子类中通过父类名来调用,而对于私有的属性和方法,子类是不进行继承的,因此在子类中是无法通过父类名来访问的

5.Python支持多继承,能够让一个子类有多个父类
  如果有多个父类,多个父类名之间用逗号隔开,classSubClass(SuperClass1,SuperClass2)

  如果SubClass没有重新定义构造方法,它会自动调用第一个父类的构造方法,以第一个父类为中心

  如果SubClass重新定义了构造方法,需要显示去调用父类的构造方法,此时调用哪个父类的构造方法由你自己决定;若SubClass没有重新定义构造方法,则只会执行第一个父类的构造方法。并且若SuperClass1和SuperClass2中有同名的方法,通过子类的实例化对象去调用该方法时调用的是第一个父类中的方法

例如:

class UniversityMember:
	def __init__(self,name,age):
		self.name = name;
		self.age = age;
	def getName(self):
		return self.name;
class Student(UniversityMember):
	def __init__(self,name,age,sno,mark):
		UniversityMember.__init__(self,name,age); #注意要显示调用父类构造方法
		self.sno = sno;
		self.mark = mark;
	def getMark(self):
		return self.mark;

代码解释:大学中的每个成员都有姓名和年龄,而学生有学号和分数这2个属性,大学成员为父类,学生为子类

抽象类

抽象类是包含抽象方法的类,而抽象方法不包含任何可实现的代码,只能在其子类中实现抽象函数的代码

为什么要有抽象类?
  如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性

  比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子,你永远无法吃到一个叫做水果的食物

  python要实现抽象类,必须使用自带的abc.py库,定义抽象类在定义抽象类前需要从类库abc导入ABCmeta类(即Metaclass for defining Abstract BaseClasses,抽象基类的元类)和abstractmethod类

  在定义抽象类时需要在类定义中加入如下代码:__metaclass__ = ABCmeta,即指定该类的元类是ABCmeta。所谓元类就是创建类的类

  在定义抽象方法时需要在前面加入如下代码:@abstractmethod因为抽象方法不包含任何可实现的代码,因此其函数体通常使用pass

抽象类实现举例:

from abc import ABCMeta,abstractmethod

class People:
	__metaclass__ = ABCMeta;
	@abstractmethod
	def set_name(self):
		pass;
		
class Student(People):
	def set_name(self,name): #参数个数不同
		print('Student,set_name = %s'%name);

四、三大特性之多态实现

多态指的是一类事物具有多种形态,只有存在父子类关系才会让一类事物具有多种不同的形态,因而多态的前提是必须要实现继承。在多态的实现过程中,经常会使用抽象类

例如:
1.序列类型有多种形态:字符串,列表,元组
2.动物有多种形态:狗,猫,猪

多态性

多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数

例如:
内置函数len(object),len函数不仅可以计算字符串的长度,还可以计算列表、元组等对象中的数据个数,这里在运行时通过参数类型确定其具体的计算过程,正是多态的一种体现

代码举例:

import abc

class File(metaclass=abc.ABCMeta): # 同一类事物:文件
	@abc.abstractmethod
	def click(self):
		pass
		
class Text(File): # 文件的形态之一:文本文件
	def click(self):
		print('open file');
		
class ExeFile(File): # 文件的形态之二:可执行文件
	def click(self):
		print('execute file');

def openFile(obj):
	obj.click();

txt = Text();
exe = ExeFile();
openFile(exe);