面向过程:
1.把需要完成需求的方法都设计出来
2.能独立封装的代码都独立封装成每一个方法
3.按顺序调用这些方法
面向对象:
基于面向过程更高级的封装
1.完成需要前明确职责
2.根据职责创建不同对象,在不同对象中设计需要实现的方法
3.按顺序让不同的对象调用不同的方法
举个例子,比如一个家里有爸爸妈妈和小明,我们在这里设计每个人(即每个对象)的需求都不一样。爸爸需要做饭,打扫卫生,接送小明上下学(3个不同的方法),妈妈需要做饭,打扫卫生,上班赚钱(同样3个方法),小明需要完成作业,玩耍,以及去上学(也是3个方法)。
如果按时间顺序来看,爸爸的一天应该是:先起床做饭,送小明上学,回家打扫卫生,做饭,接小明放学。每个方法轮流调用,这就是面向过程。
同理,妈妈和小明的一天也是一个调用顺序的面向过程。
在这个家里我们需要明确每个人的分工和职责,比如说做饭和打扫卫生是爸爸和妈妈都拥有的方法,而对爸爸来说,接送小明上下学就是他特有的方法,这件事只有他能完成,对妈妈来说就是上班赚钱,对小明来说就是完成作业、玩耍和上学。而一个家庭的正常运转,需要每个人都在自己的位置上完成自己特有的封装方法。我们把一个家庭运转当成需要完成的需求,那么一个家里需要每个成员都各司其职,把这些对象(爸爸、妈妈和小明)都封装起来,再抽象出一个家庭的类,那么每次新建一个家庭类,都必须要有以上三个对象,而我们要从每个对象中调用各自特有的方法让这个家庭正常运转起来,这就是面向对象。
类 就相当于一个模板 我们可以用类来创建对象
比如说把爸爸的行为定义为一个父亲类Class Dad,那么每次创建一个爸爸,只要new Dad()就可以创建出来。(Python里面创建对象只需直接调用类名
而初始化一个对象的时候一般都会有这个对象的基本属性,比如说我创建一个人的类,那么基本属性一般是姓名、身高、体重,这个人有的行为方法,可以是吃、喝、睡。
Python中的init方法就是初始化方法,对象被初始化时会被自动调用,类似于C++中的构造方法。
示例:
#!/usr/bin/python3 # coding=utf-8 #object类是基类 class Person: def __init__(self,name,age,height): self.name = name self.age = age self.height = height def run(self): print('I can run.') def eat(self): print('I can eat.') xiaoming = Person('xiaoming',18,180) print(xiaoming) xiaoming.eat() print(xiaoming.name) print(xiaoming.age)
运行结果如下:
除了init以外还有几个基础的方法:
new方法在创建的时候就会被调用,而del方法是对象在内存中被销毁时会被自动调用,str是返回对象的描述信息。
在刚才的代码上我们修改一下输出:
#!/usr/bin/python3 # coding=utf-8 #object类是基类 class Person: def __init__(self,name,age,height): self.name = name self.age = age self.height = height def run(self): print('I can run.') def eat(self): print('I can eat.') xiaoming = Person('xiaoming',18,180) print(Person) print(xiaoming)
这时候打印出来的就是:
可以看出对象xiaoming打印出来的是所在类(object是默认基类),以及0x000002509A5408D0 xiaoming这一对象所在的内存地址。
这里我们写一个str方法就能观察出来对对象的信息描述:
#!/usr/bin/python3 # coding=utf-8 #object类是基类 class Person: def __init__(self,name,age,height): self.name = name self.age = age self.height = height #对象返回的信息描述:就是这个对象输出的时候,可以打印它的相关信息。 def __str__(self): return 'I am a str method.' def run(self): print('I can run.') def eat(self): print('I can eat.') xiaoming = Person('xiaoming',18,180) print(Person) print(xiaoming)
这时再打印输出,会发现对象xiaoming输出的是我们在str方法内返回的对xiaoming的描述:
传入的初始化参数内包括缺省参数,即需要一开始就赋值,这样往后创建对象时,如果对象没有给这个变量传参,也不影响运行。
比如这里传入参数house:
def __init__(self,name,age,height,house=None): self.name = name self.age = age self.height = height self.house = house
然后新建两个对象,针对house参数一个赋值一个不赋值:
xiaoming = Person('xiaoming',18,180,'公寓') print(xiaoming.house) xiaohong = Person('xiaohong',17,170) print(xiaohong.house)
运行结果:
del方法则是在在对象销毁时会调用一次:
#!/usr/bin/python3 # coding=utf-8 #object类是基类 class Person: def __init__(self,name,age,height,house=None): self.name = name self.age = age self.height = height self.house = house #对象返回的信息描述:就是这个对象输出的时候,可以打印它的相关信息。 def __str__(self): return 'I am a str method.' def run(self): print('I can run.') def eat(self): print('I can eat.') #对象结束就会调用 def __del__(self): print('over') xiaoming = Person('xiaoming',18,180,'公寓') print(xiaoming.house) xiaohong = Person('xiaohong',17,170) print(xiaohong.house)
运行结果如图,第一个over是xiaoming结束时销毁调用del方法,第二个over时xiaohong结束时调用del方法。
面向对象练习
设计类的时候应该优先设计不需要依赖他人就能独立存在的类,所以应该先开发家具类。
#!/usr/bin/python3 # coding=utf-8 class HouseItem: def __init__(self,name,area): self.name = name self.area = area def __str__(self): return '[%s]占地面积 %.2f' %(self.name ,self.area) #创建家具 bed = HouseItem('席梦思',4) chest = HouseItem('衣柜',2) table = HouseItem('餐桌',1.5) print(bed) print(chest) print(table)
运行如下:
完善房子类:
#!/usr/bin/python3 # coding=utf-8 class HouseItem: def __init__(self,name,area): self.name = name self.area = area def __str__(self): return '[%s]占地面积 %.2f' %(self.name ,self.area) #创建家具 bed = HouseItem('席梦思',4) chest = HouseItem('衣柜',2) table = HouseItem('餐桌',1.5) print(bed) print(chest) print(table) class House: def __init__(self,house_type,area,item_list=[]): self.house_type = house_type self.area = area self.free_area = area self.item_list = item_list def __str__(self): return '%s 剩余的面积是 %.2f,拥有家具%s' \ %(self.house_type,self.free_area,self.item_list) def add_item(self,item): #1.判断家具面积是否大于房间剩余面积 if item.area > self.free_area: return '不能放家具啦' #2.置放家具 self.item_list.append(item.name) self.free_area -= item.area my_house = House('两室一厅',60) my_house.add_item(bed) my_house.add_item(table) print(my_house)
这里需要注意的是,如果在置放家具一行代码中append的是item而不是item.name,那么运行返回的是item的内存地址。
最后运行结果: