1、面向对象与面向过程
面向过程:核心过程二字,过程即解决问题的步骤,就是先干什么后干什么
基于该思想写程序就好比在这是一条流水线,是一种机械式的思维方式
优点:复杂的过程流程化
缺点:扩展性差
面向对象:核心是对象二字,对象指特征与技能的结合体
基于该思想编写程序就好比在创造一个世界,世界是由一个个对象组成,是一种‘上帝式’的思维方式
优点:可扩展性强
缺点:变成复杂度高,极容易出现过度设计的问题
2、类
对象是特征与技能的结合体,类就是一系列对象相似的特征与技能的结合体
在现实生活中:一定是先有一个个具体的对象,后总结出类
在程序中:一定是先定义类,后产生对象
创建类的时候,是首字母要大写
类属性的增删改查:
class Studnets(object): school = '实验中学' def choose_course(self): print('选课') stu1 = Studnets() print(stu1.school) #查看 stu1.school ='实验' #改 print(stu1.school) stu1.contry = '北京' #增加 print(stu1.contry) # del stu1.contry #删除 # print(stu1.contry)
运行结果:
定义个类:
__init__(self)用法中,self表示,谁调用就代表谁
先考虑立场,再考虑归类,再考虑每一个对象的特征和技能
class Studnets(object): school = '实验中学'#数据属性 def __init__(self, name, age): #类的初始化方法,可以把每个人不同的特征定义下来,自动调用初始化函数 self.name = name self.age = age def choose_course(self):#函数属性 print('%s正在选课,年纪是%s' % (self.name, self.age)) stu1 = Studnets('张三', 18) stu1.choose_course() stu2 = Studnets('李四', 19) stu2.choose_course() stu3 = Studnets('王五', 20) stu3.choose_course()
运行结果:
例2:
class Studnets(object): school = '实验中学'#数据属性 def __init__(self, name, age): self.name = name self.age = age def choose_course(self):#函数属性 print('%s正在选课,年纪是%s' % (self.name, self.age)) def run(self): print('%s正在奔跑...' % (self.name)) stu1 = Studnets('帅帅', 25) stu1.run() stu2 = Studnets('六六', 18) stu2.run()
运行结果:
面向对象的三大特征:封装,继承,多态
封装
封装根据职责将属性和方法封装到一个抽象的类中
·定义类的准则
1.封装是面相对象一大特点
2.面向对象编程的第一步,将属性和方法封装到一个抽象的类当中
3.外界使用类创建对象,然后让对象调用方法
4.对象方法的细节都被封装在类的内部
封装案例1.小明爱跑步
需求
1.小明体重75公斤
2.小明每次跑步都会减肥0.5公斤
3.小明每次吃东西体重会增加1公斤
#创建类 class Person(object): def __init__(self, name, weight): self.name = name self.weight = weight def eat(self): self.weight += 1 def run(self): self.weight -= 0.5 def __str__(self):#返回结果 return '姓名:%s\n体重:%s公斤\n' % (self.name, self.weight) #拟定对象 xiaoming = Person('小明', 75) xiaoming.eat()#加1 xiaoming.eat()#加1 xiaoming.run()#减0.5 print(xiaoming)
运行结果:
封装案例2,买家具
需求:
1、房子有户型、总面积、家具名称列表
房子默认没有任何家具
2、家具有名字和占地面积,其中
席梦思(bed):4平米
衣柜(chest): 2平米
餐桌(table): 1.5平米
3、将以上3个家具添加到房子中
4、打印房子中,要求输出:户型、总面积、剩余面积、家具名称列表
创建多个类的时候,从小的开始
class Items(object):#创建一个家具类 def __init__(self, name, area): #初始化出不同的类对象 self.name = name self.area = area def __str__(self): return '家具名称:%s\n面积:%s平米\n' % (self.name, self.area) class House(object):#创建房子类 def __init__(self, house_type, total_area):#初始化房子类(因为新房子没有家具,剩余面积等于总面积,所以不用传参) self.house_type = house_type self.total_area = total_area self.free_area = total_area self.items = [] def add_item(self, item):#添加家具的技能 self.items.append(item.name)#一触发添加家具的技能就添加家具到列表中 if self.free_area > item.area:#假如剩余面积大于家具面积就添加成功 self.free_area = self.free_area - item.area else:#否则添加不进去 del self.items[-1] print('家具太大了,装不进去....') def __str__(self):#打印房子当前状态 return '户型:%s\n总面积:%s平米\n剩余面积:%s平米\n家具列表:%s\n' % \ (self.house_type, self.total_area,self.free_area, self.items) bed = Items('席梦思',4)#实例化出一个床对象 chest = Items('衣柜', 2)#实例化出一个衣柜对象 table = Items('餐桌', 1.5)#实例化出一个餐桌对象 train = Items('火车', 100) 路飞 = Items('海贼王', 10) house = House('两室一厅', 90)#实例化出一个房子对象 house.add_item(bed)#执行添加家具动作 house.add_item(chest) house.add_item(table) house.add_item(train) house.add_item(路飞) print(house)
运行结果:火车由于太大,无法放进去
封装案例3:士兵突击
属性可以是另外一个类创建的对象:
需求:
1、士兵许三多,枪AK47
2、士兵可以开火
3、枪能够发射子弹
4、枪装填子弹——增加子弹数量
class Gun(object):#创建枪类 def __init__(self, name):#初始化枪类属性(子弹默认没有,所以不写了) self.name = name self.bullet = 0#子弹默认是零 def shoot(self):#射击技能 if self.bullet > 0:#判断子弹数 # for i in range(self.bullet): #直接把子弹打空 self.bullet -= 5 print('冲啊.......突突突突突.......[%s]' % self.bullet) else: print('没子弹,上刺刀......') def add_bullet(self, count):#装填子弹技能 self.bullet += count def __str__(self): return '枪型号:%s\n剩余子弹:%s\n' % (self.name, self.bullet) class Soldier(object):#创建士兵类 def __init__(self, name):#初始化士兵类属性(枪默认没有所以不写在这了) self.name = name self.gun = None#没有枪 def fire(self): if self.gun: self.gun.shoot()#调用子弹函数 else: print('[%s]:没有枪,赶紧撤......' % self.name) ak47 = Gun('AK47')#上枪 xsd = Soldier('许三多')#上士兵 xsd.gun = ak47#把枪给士兵 xsd.gun.add_bullet(50)#上子弹 xsd.fire()
xsd.fire()
运行结果:
继承
继承实现代码的重用,相同的代码不需要重复的编写
·设计类的技巧
·子类针对自己特有的需求,编写特定的代码
单继承
class Anamal(object): def eat(self): print('吃') def drink(self): print('喝') def run(self): print('跑') def sleep(self): print('睡') class Dog(Anamal):#继承Anamal def bark(self): print('汪汪叫') class XiaoTianQuan(Dog):#继承Dog def fly(self): print('我会飞啦!!!!') dog = XiaoTianQuan() dog.bark() dog.run() dog.eat() dog.sleep() dog.drink() dog.fly()
运行结果:
多继承
class Anamal(object): def eat(self): print('吃') def drink(self): print('喝') def run(self): print('跑') def sleep(self): print('睡') class Dog(object): def bark(self): print('汪汪叫') class XiaoTianQuan(Anamal,Dog):#继承Anamal和 Dog def fly(self): print('我会飞啦!!!!') dog = XiaoTianQuan() dog.bark() dog.run() dog.eat() dog.sleep() dog.drink() dog.fly()
运行结果:
方法的重写
子类拥有父类的所有方法和属性
子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
应用场景:当父类的方法不能满足子类需求时,可以对方法进行重写
class Anamal(object): def eat(self): print('吃') def drink(self): print('喝') def run(self): print('跑') def sleep(self): print('睡') class Dog(Anamal): def bark(self): print('汪汪叫') class XiaoTianQuan(Dog): def fly(self): print('我会飞啦!!!!') def bark(self): print('狂傲的汪汪叫.......')#直接重写会覆盖之前的 dog = XiaoTianQuan() dog.eat() dog.run() dog.sleep() dog.drink() dog.bark() dog.fly()
运行结果:
对父类的方法进行扩展
1.在子类中重写父类的方法
2.在需要的位置使用super().父类方法来调用父类方法的执行
3.代码其他的位置针对子类的需求,编写子类特有的代码实现
关于super
在python中super是一个特殊的类
super()就是使用super类创建出来的对象
最常使用的场景:就是在重写父类方法时,调用在父类中封装的方法实现
class Anamal(object): def eat(self): print('吃') def drink(self): print('喝') def run(self): print('跑') def sleep(self): print('睡') class Dog(Anamal): def bark(self): print('汪汪叫') class XiaoTianQuan(Dog): def fly(self): print('我会飞啦!!!!') def bark(self): print('狂傲的汪汪叫.......') super().bark()#继承bark方法 dog = XiaoTianQuan() dog.eat() dog.run() dog.sleep() dog.drink() dog.bark() dog.fly()
运行结果:
初始化__init__继承
class Person(object):#创建一个人类 def __init__(self, name): self.name = name class KOBE(Person):#创建一个科比类,继承人类 def __init__(self, age):#定义自己的初始化 super(KOBE, self).__init__('科比')#继承的初始化,如果有参数需要传参 self.age = age kobe = KOBE(18) print(kobe.name) print(kobe.age)
运行结果:
多态
多态不同的子类对象调用相同的父类方法,产生不同的执行结果
1.多态可以增加代码的灵活度
2.以继承和重写父类方法为前提
3.是调用方法的技巧,不会影响到类的内部设计
多态的特性:让不同的子类对象调用相同的代码产生不同的结果
class Dog(object): def __init__(self, name): self.name = name def game(self): print('%s 开开心心去玩耍.....' % self.name) class XiaoTianQuan(Dog): def game(self): print('%s 开开心心去玩耍.....' % self.name) class Person(object): def __init__(self, name): self.name = name def game_with_dog(self, dog): print('%s 和 %s 正在开开心心的玩耍......' % (self.name, dog.name)) dog.game() #创建人对象 xiaoming = Person('小明') #创建狗对象 dog = Dog('旺财') #让小明跟狗玩耍 xiaoming.game_with_dog(dog) xtq = XiaoTianQuan('飞天旺财') xiaoming.game_with_dog(xtq)
运行结果:
类方法
@classmethod,只访问类属性
class Tool(object):#创建工具类 count = 0#类属性:工具的数量 @classmethod#装饰函数为类方法 def show_tools_count(cls):#如果只访问类属性,那么就把他定义成类方法 print('当前工具数量为%s' % cls.count)#类方法要用cls访问和调用 def __init__(self, name): self.name = name Tool.count += 1 tool1 = Tool('锤子') tool2 = Tool('榔头') Tool.show_tools_count()
运行结果:
静态方法
@staticmethod
- 既不需要访问实例属性或者调用实例方法
- 也不需要访问类属性或者调用类方法
- 这个时候我们可以考虑把这个方法封装成静态方法
class Dog(object): @staticmethod#声明这是一个静态方法 def run():#不用实例化,就可以不用self #不访问实例属性,也不访问类属性 print('小狗要跑.....') def jump(self):#用self就会报错 print('小狗要跳.....') Dog.run() Dog.jump()
运行结果:
如果加了self,那么就要实例化
class Dog(object): @staticmethod#声明这是一个静态方法 def run(): #不访问实例属性,也不访问类属性 print('小狗要跑.....') def jump(self): print('小狗要跳.....') Dog.run()
xiaotianquan = Dog() xiaotianquan.jump()
运行结果: