面向对象的编程思想的发展历程
当歌
我理解的面向过程与面向对象
自从学习python以来,以前所接触的代码是根据实际的案例,按照过程,像踩西瓜皮那样,从上到下的按照思路来走,这样的编程思路只适合于中小型的项目案例开发,如果面对较多的数据以及变量,就有些力不从心了,会产生很冗余的代码量,但是面向对象就不同了,虽说面向对象较面向过程来说,相对复杂,但是面向对象对于代码模块化来说是明显高于面向过程的,而且因为其显著特点在扩展功能以及维护上是明显优于面向过程的,所以说二者没有好坏之分,只有合不合适,对于我们来讲更是会不会,熟练不熟练的问题了。所以学好面向对象的编程思路也是很有必要的。
面向对象编程的基本概念
类:
类是一类事物的总称,这类事物有着或多或少的相似之处,称为特征,类是一个概念。
对象:
对象就是实际存在的事物,世间万物都是对象,是类型表示的具体的实际存在一个实例
类与对象的关系:
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数
怎样定义一个类:
组成部分包括,类型名称,属性,方法。通过关键字class定义类型,通过_init_()函数,来初始化累的属性数据,通过普通的函数来实现类的行为方法(ps:类中的函数第一个参数必须是self)。
怎样创建一个对象:
可以直接通过类的名称,来创建对象。
怎样使用对象的属性:
对象的属性,可以直接通过对象的引用变量.属性名称来使用。
再怎样使用对象的方法(调用函数):
对象的方法,可以直接通过对象的引用变量.方法名称()来调用方法
创建对象的过程:
首先,调用对象的_new_()函数申请内存,创建对象。其次,给创建好的对象,初始化对象的数据,会自动调用_init_()函数,给对象的属性赋值。
创建好的对象,赋值给了一个变量,变量是什么类型?存放的是什么数据?
对象赋值给一个变量,变量存放的是对象的存储地址数据,存放的是类类型
面向对象的特征---封装的意义和操作过程
什么是封装
从字面上来讲就是把事物装起来而且封上,就像在收拾东西的时候把一些零碎的,彼此之间有些关联的东西放在一个收纳箱里,比如说把衣服放进衣柜,无论上衣下衣,春装夏装,他们都是属于一个“衣服”的类型,再比如拖鞋和运动鞋都放在鞋柜里,所以说,面向对象的封装就是把一些相关联而又零散的数据封装在一个类型中。比如和商品类型有关的会有商品价格,商品种类,商品的库存等等等等。
#定义了一个商品类型,封装和商品有关系的数据
class Goods:
def __init__(self,name, price, stock):
self.name = name
self.price = price
self.stock = stock
怎么封装
属性私有化:一些对象的属性往往不是对所有人都能够访问的,就像生活中不能直接把手伸进人家的口袋,小偷是未经允许的偷盗行为你是不知情的,而乞丐是你允许的,然后把钱给人家的行为,所以属性的私有化,不能够被外界直接访问。
所以,不带下划线的属性可以直接访问,就像推门而入。约定以一个下划线开头的变量,是私有变量外界可以访问但是不能直接访问,需要先敲门然后在进入。要求两个下划线开头的属性,表示当前的私有属性外界不能访问,门里是锁着的,不仅要敲门,还需要得到屋里人的同意给你开门,你才能进。
封装实现的步骤
1.完成一个类的定义
2.所有属性私有化
3.给每个属性提供set/get方法
具体案例
1. 类型的定义:零散数据包含在一个类中,封装
class Users:
def __init__(self, name):
self.name = name
u = Users("tom")
print(u.name)
u.name = "jerry"
print(u.name)
--------------------------------------
2.属性私有化,提供set/get函数:封装进阶
class Person:
def __init__(self, name):
self.__name = name # 属性私有化
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
p = Person("shuke")
print(p.get_name())
p.set_name("beita")
print(p.get_name())
--------------------------------------
3.添加@property和@method.setter,隐藏set/get函数:高级封装
class Computer:
def __init__(self, name):
self.__name = name
@property #给获取值的方法,添加@property
def get_name(self):
return self.__name
@get_name.setter
def set_name(self, name):
self.__name = name
c = Computer("Alienware")
print(c.get_name)
c.set_name = "HP"
print(c.get_name)
--------------------------------------
4.扩展:同一个类中,出现了相同名称但是参数不同的函数:方法重载
class Animal(object):
def __init__(self, name, age):
# 将属性私有化,外界不能访问了
self.__name = name
self.__age = age
# 在同一个类中,出现了两个或者两个以上同名函数/方法:方法重载
@property
def name(self): # name()
return self.__name
@name.setter
def name(self, n):# name("tom")
self.__name = n
def age(self):
return self.__age
def age(self, a):
if (a >= 0) and (a <= 20):
self.__age = a
else:
print("年龄不合法...")
a = Animal("cat", 18)
a.name = "tom"# 设置值
print(a.name)#获取值
a.age = 22# 设置值
print(a.age)# 获取值
# print(a.age())
# a.age(20)
# print(a.age())
面向对象的特征---继承的意义和操作过程
我所理解的继承
我所理解的继承,就像字面上的那样的意思的继承,儿子继承父亲的东西,比如,票子、车子、房子,在编程中的继承也是这样的子类会继承父类的公共的属性和方法,从而达到代码重复使用的目的,之所以是说公共的,是因为一些私有的是不能够继承来的,就像儿子不能继承老爸的回忆和一些想法,这是不能够给别的的,属于自身私有的,就算是亲儿子那也给不了啊,所以这也是继承的特性的一部分。
在python中,一个类型不但可以被继承给多个类型(相当于一个爸爸有好几个孩子这是允许的)而且一个类型还可以同时继承多个类型的公开的属性和方法,就像一个人有很多的王叔叔那样,强行解释一波吧,,周末,妈妈让王叔叔们带着出去玩,肯定先要跟第一个来接你的王叔叔一起去,坐着他的车子,花着他的票子,但路上他不跟你讲他跟妈妈的一些回忆,这是属于王叔叔自己的私人的,不能告诉你的。所以反映在程序中一个类型可以继承多个类型公共的属性和方法,是公共的。而且按照继承的先后顺序优先调用,一号王叔叔和十八号王叔叔都在等着,但是一号先来的,所以理应跟着一号王叔叔去玩,另一方面,如果本身就可以单独去玩,不需要调用一群王叔叔,那就自己一个人去,反映在程序中叫做方法的重写!
为什么要继承
达到代码的重复使用的目的。
继承的语法
class 类型(被继承的类型):
pass
继承中出现的术语
父类:被继承的类,也称为基类、超类
子类:当前类,也称为派生类
子类继承父类,体现的时A is a B的关系
子类继承父类,就可以使用父类中所有的公开的属性和方法
继承链
A继承B,B继承C,C继承D
A直接继承了B,间接继承了C,D;此时A创建的对象,可以同时使用B,C,D中所有公开的属性和方法
多继承
python中,一个类型,可以同时继承多个类型,同时拥有所有继承类型的所有公开的属性和方法
备注:在进行代码设计的过程中,可能会出现多继承,所以尽量不要在父类中定义相同名称的属性或者方法
备注2:如果父类中出现了相同名称的属性和方法,在使用的时候子类调用时会优先继承优先调用。
方法重写:
子类在自己类中重新定义父类中已经存在的方法,在执行该方法时,如果子类中没有重写就直接调用父类的方法,如果子类重写了该方法,就直接调用子类重写的方法!
扩展:子类中,访问父类的属性和方法:
classUser(Person):
def__init__(self, name, age):
#直接通过父类的类名称调用父类的属性和方法
Person.__init__(name, age)
#通过super()来调用父类的属性和方法
super().__init__(name, age)
面向对象的特征---多态的意义和操作过程
多态就是多种状态,美其名曰变态!程序在运行的过程中,根据传递的参数的不同,执行不同的函数或者操作不同的代码,这种在运行过程中才确定调用的方式成为运行时多态
人民医院.治疗(病人)
当治疗方法在执行的过程中,根据传递的数据的不同,在执行时调用
病人甲(人)不同的处理代码或者处理函数,来完成治疗效果,动态处理(多态)
病人乙(男人)
病人丙(女人)人的类型 VS 动物类型,不是多态~而是通过if条件判断执行代码
病人丁(动物)人/男人/女人,执行的代码一致【运行过程中,才确定调用谁的方法】
# 定义一个人的类型
class Person:
# name姓名 age年龄 health健康值【0~50极度虚弱,51~70亚健康,71~85健康,86~100强壮】
def __init__(self, name, age, health):
self.name = name
self.age = age
self.health = health
# 康复的方法
def recure(self):
print("[%s]康复了,当前健康值%s" % (self.name, self.health))
class Man(Person):
def __init__(self, name, age, health):
Person.__init__(self,name, age, health)
def recure(self):
print("%s哇咔咔,康复了" % self.name)
class Women(Person):
def __init__(self, name, age, health):
Person.__init__(self,name, age, health)
def recure(self):
print("[%s]死鬼,终于康复了..." % self.name)
class Animal:
# name姓名 age年龄 health健康值【0~50极度虚弱,51~70亚健康,71~85健康,86~100强壮】
def __init__(self, name, age, health):
self.name = name
self.age = age
self.health = health
# 康复的方法
def recure(self):
print("[%s]嘿嘿嘿,终于康复了,当前健康值%s" % (self.name, self.health))
# 定义人民医院
class Hospital:
def __init__(self):
self.name = "人民医院"
def care(self, person):
# 类型判断,判断变量person是否Person类型
if isinstance(person, Person):
if person.health > 0 and person.health <= 50:
print("手术......")
person.health += 30
person.recure()
elif person.health > 50 and person.health <= 70:
print("输液......")
person.health += 15
person.recure()
else:
print("健康")
else:
print("不好意思,请出门左转,哪里是兽医院")
# 医院对象
hospital = Hospital()
# 生病的人
old_wang = Person("王先生", 58, 30)
mrs_li = Women("李夫人", 28, 56)
mr_li = Man("李先生", 30, 60)
# 调用了治疗的方法
hospital.care(old_wang)
hospital.care(mrs_li)
hospital.care(mr_li)
a = Animal("tom", 22, 10)
hospital.care(a)