面向过程和面向对象的对比
面向过程
面向过程是按照问题的解决方式来编写程序。需要先分析出解决问题的方法,然后按照这个方法一步步的去完成程序,所有细节都需要自己去实现,优点是程序细节自己把握,缺点是工作量巨大。
比如:出门旅游
- 买票(去买票:买高铁 or 飞机, 买什么座位,出发时间,下单)
- 出发(去车站or机场: 几点出发几点到,打车or地铁)
- 游玩景点(玩哪些景点,每个景点多长时间)
- 回家(重复步骤1和2)
面向对象
面向对象,更贴近人的思维模式,处理问题需要找到对应的人,然后解决问题。面向对象能使程序员从软件架构的方向去思考程序的开发,有助于梳理结构分析问题。
面向对象的三大特征如下:
- 封装
- 继承
- 多态
有利于代码的复用提高编码效率,可扩展性很强,增加新功能不需要修改原来的代码,软件逻辑结构清晰,有助于后期维护。
比如:出门旅游
- 找旅游公司:
- 买票
- 接送机
- 景点安排
- 回程接送
一站式服务,不需要自己亲自处理。
类和对象:
类
- 类:从具体事务中抽象出共性,比如人类(泛指整个人类)是从每个个人中抽象出共有的特征,从而形成人类的群体。
class StudentInformation: def __init__(self, name): self.name = name def read_stu(self): pass
- 类成员:定义在__init__方法之外,需要通过类名来访问,所有对象共享一个类成员,对也可以通过对象来访问
class StudentInformation:
# 类成员student_number,表示当前student的数量
student_number = 0
def __init__(self, name):
self.name = name
StudentInformation.student_number +=1
def read_stu(self):
pass
stu01 = StudentInformation("abc")
print(stu01.student_number) # 输出 1
-
- 类方法:标识符(@classmethod), 可以访问类成员,不能访问init中的对象成员,因为类方法中没有对象的地址,所以无法访问对象成员。
- 作用:操作类变量
- 通过类名.方法名调用
@classmethod
def display_student(cls, **kwargs):
pass
StudentInformation.display_student()
Note:
- 类名中所有单词首字母大写
- __init()__为构造函数,在创建对象的时候被调用,可省略
- self是指向被实例化的对象
对象
- 对象:实例化的类,归属于某个类别的个体,比如小明(一个具体的人,属于人类)
- 对象成员:定义在__init__方法以内,通过对象地址来访问
- 对象方法:无标识符,可以访问操作对象成员和类成员(需要通过类名来访问)
stu01 = StudentInformation("abc")
Note:
扫描二维码关注公众号,回复:
16842167 查看本文章
- 首次通过对象赋值为创建,再次赋值为修改.这种新创建的对象成员仅当前对象能用,之后新建的对象没有age这个成员变量
# 创建新对象成员age
stu01.age = 10
# 创建新对象成员age
stu01.age = 20
# age = 20
print(stu01.age)
- 每个对象存储一份,通过对象地址访问。
- 静态方法:标识符(@staticmethod), 既不需要操作类变量也不需要操作对象变量,则用静态方法,通过类名调用静态方法(不建议使用对象调用静态方法)
@staticmethod
def static_student():
pass
StudentInformation.static_student()
Note:
- 使用@ staticmethod修饰的目的是该方法不需要隐式传参数。
静态方法不能访问实例成员和类成员
作用:定义常用的工具函数。
封装
- 从数据角度来说:
- 将基本的数据类型复合组成一个自定义类型
- 优势:将数据和对数据的操作相互关联,代码可读性高
- 从行为角度来说:
- 隐藏实现细节,只向外提供必要的功能
- 调用者不必了解实现细节,只需要知道调用功能即可
- 私有成员:
- 作用:无需向类外提供的成员,可通过成员私有化进行屏蔽
- 语法:使用双下划线开头
- 类的外部是无法直接访问,需要通过类提供的方法来访问。
- 使用property来封装类的成员:成员名 = property(成员set类方法,成员get类方法),可以增加相应的逻辑判断
- 写法1可以单独设置get或者set 属性,而写法2中能单独设置get属性,但是不能单独设置set属性,实际操作多选用写法2.
class Enemy:
def __init__(self, name, hp, atk):
self.name = name
self.hp = hp
self.atk = atk
# *******************写法1 start *****************************
def set_hp(self, hp):
if 100 < hp < 200:
self.__hp = hp
else:
raise ValueError("hp out of range")
def get_hp(self):
return self.__hp
hp = property(get_hp, set_hp)
def set_atk(self, atk):
if 20 < atk < 30:
self.__atk = atk
else:
raise ValueError("atk out of range")
def get_atk(self):
return self.__atk
atk = property(get_atk, set_atk)
# *******************写法1 end *****************************
# # *********************写法2 start ********************************
# # 设置hp读取属性
# @property
# def hp(self):
# return self.__hp
# # 设置hp 写属性
# @hp.setter
# def hp(self,hp):
# if 100 < hp < 200:
# self.__hp = hp
# else:
# raise ValueError("hp out of range")
#
# # 设置atk 读属性
# @property
# def atk(self):
# return self.__atk
#
# #设置atk 写属性
# @atk.setter
# def atk(self, atk):
# if 20< atk <30:
# self.__atk = atk
# else:
# raise ValueError("atk out of range")
# # ****************写法2 end***********************************
e01 = Enemy("wukong",101,25)
- 从设计角度来讲:
- 分而治之:将一个大的需求分解为许多类,每个类处理一个独立的功能。
- 变则疏之:变化的地方独立封装,避免影响其他类。
- 高内聚:类中各个方法都在完成一项任务(单一职责的类)。
- 低耦合:类与类的关联性与依赖度要低(每个类独立),让一个类的改变,尽少影响其他类。
- 优势:便于分工,便于复用,可扩展性强
例如软件设计的结构之一 MVC(Model, View, Control)就是使用的这种思想,将界面,数据和逻辑单元分开设计。
多态
设计角度
定义
父类的一种行为在子类中有不同的实现方式。
作用
- 在继承的基础上体现类型的个性化(同一种行为的不同实现)
- 增强程序的扩展性,体现开闭原则
语法角度
重写
- 子类中实现了父类中相同的方法(函数名、参数)
- 在调用子类中该方法时实际使用的是子类中的方法,只有当子类中没有实现该方法时,才调用父类中的该方法
# 父类Thing
class Thing():
def __init__(self, name):
self.name = name
# 子类中必须实现的方法
def reduce_hp(self):
raise NotImplementedError
class Granades:
def damage(self, thing):
if isinstance(thing, Thing): #判断传入的参数thing是不是要求传入的参数对象Thing
thing.reduce_hp()
else:
raise ValueError("Not Object Things")
# Thing 的子类Tree
class Tree(Thing):
def __init__(self, name):
super().__init__(name=name)
def reduce_hp(self):
print("手雷炸断了{}".format(self.name))
# Thing 的子类House
class House(Thing):
def __init__(self, name):
super().__init__(name=name)
def reduce_hp(self):
print("手雷炸塌了{}".format(self.name))
g01 = Granades()
h01 = House("别墅01")
t01 = Tree("大树01")
g01.damage(h01)
g01.damage(t01)