Python的面向对象
一、面向过程与面向对象的对比
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点是:极大的降低了程序的复杂度
缺点是:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得是大改,改一个组件,牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象的程序设计的核心是对象,Python中 一切皆对象,上帝思维,在上帝眼中这世间的一切都是对象,没有的东西也能创造出来。
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致某个游戏的角色出现数据异常的技能,比如一刀砍死3个人,这样就会很影响游戏的平衡。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
二、类与对象
基于面向对象设计一个款游戏:英雄联盟,每个玩家选一个英雄,每个英雄都有自己的特征和和技能,特征即数据属性,技能即方法属性,特征与技能的结合体就一个对象。
从一组对象中提取相似的部分就是类,类所有对象都具有的特征和技能的结合体
在python中,用变量表示特征,用函数表示技能,因而类是变量与函数的结合体,对象是变量与方法(指向类的函数)的结合体。
1.类的定义
'''
class 类名:
类的文档字符串
类体
'''
class Student:#class语句与定义函数类似 定义类名
school = 'oldboy' #变量 这个类的特征(每个对象的共同特征)
def __init__(self,name,age): #初始化函数(各个对象的所独有的特征)
#只用来初始化的,并且一定不能有返回值,
self.name=name
self.age=age
def study(self): #函数 这个类的技能(每个对象的共有技能)
pass
2.类的两种作用:实例化和属性引用
2.1实例化:类名加括号
class Oldboy: #定义oldboy类
teacher_tyle="python"
def __init__(self,name,age,sex):
if not isinstance(name,str):
raise TypeError
self.name=name
self.age=age
self.sex=sex
def teach(self):
print("teach python")
def talk(self):
print("talk english")
def eat(self):
print("is eating")
name1=Oldboy("egon","18","boy")#实例化,其实就是在执行__init__这个初始化函数将参数传入函数,实例化之后的内容被称为对象。
2.2属性引用:类名加属性
Oldboy.teacher_tyle#引用类的数据属性,该属性与所有的实例(对象)共享。
Oldboy.teach#引用类的函数属性,该属性与所有的对象共享。
2.3对象的只有一个作用:属性引用
name1.name
对象/实例本身只有数据属性,但是python的class机制会将类的函数绑定到对象上,称为对象的方法,或者叫绑定方法,绑定方法唯一绑定一个对象,同一个类的方法绑定到不同的对象上,属于不同的方法,内存地址都不会一样
name1.eat
3.类的名称空间与对象的名称空间。
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性
而类有两种属性:数据属性和函数属性其中类的数据属性是共享给所有对象的
创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性。
name1.name会先从对象自己的名称空间中找name,找不到就去类里面找,类找不到就去它父类中找,还是找不到的话抛出异常报错!
三、类的继承与派生
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
class People:
pass
class Animal:
pass
class Student(People,Animal): #people称为基类或父类
pass
print(Student.__bases__)
print(People.__bases__)
print(Animal.__bases__)
#在python3中,所有类默认继承object,
#但凡是继承了object类的子类,以及该子类的子类,都称为新式类(在python3中所有的类都是新式类)
#没有继承object类的子类成为经典类(在python2中,没有继承object的类,以及它的子类,都是经典类)
解决代码重用的问题,减少代码冗余
继承是一种什么‘是’什么的关系
class People:
def __init__(self, name, age):
# print('People.__init__')
self.name = name
self.age = age
def walk(self):
print('%s is walking' %self.name)
class Teacher(People):
pass
class Student(People):
pass
# t=Teacher('egon',18)
# print(t.name,t.age)
# print(t.__dict__)
# t.walk()
# s=Student('alex',13)
# print(s.name,s.age)
# s.walk()
四、组合
软件重用的重要方式除了继承之外还有另外一种方式,即:组合
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
组合:是一种什么有什么的关系,也是为了减少重复代码
class People:
def __init__(self, name, age, year, mon, day):
self.name = name
self.age = age
self.birth = Date(year, mon, day)
def walk(self):
print('%s is walking' % self.name)
class Date:
def __init__(self,year,mon,day):
self.year=year
self.mon=mon
self.day=day
def tell_birth(self):
print('出生于<%s>年 <%s>月 <%s>日' % (self.year,self.mon,self.day))
class Teacher(People):
def __init__(self, name, age, year, mon, day,level,salary):
People.__init__(self,name,age,year,mon,day)
self.level=level
self.salary=salary
def teach(self):
print('%s is teaching' %self.name)
class Student(People):
def __init__(self, name, age, year, mon, day,group):
People.__init__(self,name,age,year,mon,day)
self.group=group
def study(self):
print('%s is studying' %self.name)
# t=Teacher('egon',18,1990,2,33)
# print(t.name,t.age)
# print(t.birth)
# t.birth.tell_birth()
# print(t.birth.year)
# print(t.birth.mon)
# print(t.birth.day)
五、接口
class File:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。
# def read(self): #定接口函数read
# pass
#
# def write(self): #定义接口函数write
# pass
#
#
# class Txt(File): #文本,具体实现read和write
# def du(self):
# print('文本数据的读取方法')
#
# def xie(self):
# print('文本数据的读取方法')
#
# class Sata(File): #磁盘,具体实现read和write
# def read(self):
# print('硬盘数据的读取方法')
#
# def write(self):
# print('硬盘数据的读取方法')
#
# class Process(File):
# def read(self):
# print('进程数据的读取方法')
#
# def write(self):
# print('进程数据的读取方法')
#
#
# txt=Txt()
# disk=Sata()
# process=Process()
#
#
# txt.du()
# # disk.read()
# # process.read()
#
#
#父类要限制
#1;子类必须要有父类的方法
#2:子类实现的方法必须跟父类的方法的名字一样
import abc
class File(metaclass=abc.ABCMeta):
@abc.abstractmethod
def read(self):
pass
@abc.abstractmethod
def write(self):
pass
class Txt(File): #文本,具体实现read和write
def read(self):
pass
def write(self):
pass
t=Txt()