一、封装
(1)封装是面向对象的一大特点
(2)面向对象编程的第一步--将属性和方法封装到一个抽象的类当中
(3)外界使用类创建对象,然后让对象调用方法
(4)对象方法的细节都被封装在类的内部
1、案例1
''' 小明爱跑步 需求 1.小明体重75公斤 2.小明每次跑步都会减肥0.5公斤 3.小明每次吃东西体重会增加1公斤
''' class Human: 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的体重是%s"% (self.name,self.weight) xm = Human('小明',75) xm.eat() xm.run() print(xm) #当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据
2、案例2
''' 需求: 1、房子有户型、总面积、家具名称列表 房子没有任何家具 2、家具有名字和占地面积,其中 席梦思(bed):4平米 衣柜(chest): 2平米 餐桌(table): 1.5平米 3、将以上3个家具添加到房子中 4、打印房子中,要求输出:户型、总面积、剩余面积、家具名称列表 ''' class Furniture: def __init__(self,name,area): self.name = name self.area = area def __str__(self): return "%s家具占地面积为%s"% (self.name,self.area) class House: def __init__(self,house_type,all_area): self.house_type = house_type self.all_area = all_area self.free_area = all_area self.furnitures = [] def add(self,item): if self.free_area > item.area: self.furnitures.append(item.name) self.free_area -= item.area else: print("%s家具面积为%s,大于房子的剩余面积!"%(item.name,item.area)) def __str__(self): return "该房子户型是:%s|总面积为:%s|剩余面积为:%s|家具名称列表:%s" % (self.house_type,self.all_area,self.free_area,self.furnitures) house1 = House('两室一厅',100) print(house1) bed = Furniture('席梦思',4) chest = Furniture('衣柜',2) table = Furniture('餐桌',1.5) # cj = Furniture("茶几",120) house1.add(bed) house1.add(table) house1.add(chest) # house1.add(cj) print(house1)
3、案例3
''' 需求: 1、士兵 许三多 有一把AK47; 2、士兵可以开火; 3、枪能够发射子弹; 4、枪能够装填子弹(增加子弹数量) ''' class Gun: #创建枪类 def __init__(self,gun_type): self.gun_type = gun_type #初始化枪的型号 self.bullet = 0 #初始化子弹的数量 def add_count(self, count): #添加子弹 self.bullet += count def shoot(self): #射击 if self.bullet > 0: #假如子弹数量大于0 self.bullet -= 1 # 那就射击,并且减少子弹数量 print('开火.......%s' % self.bullet) else: print('没有子弹啊,兄弟,别这么坑我啊???') #否则没有就显示没有子弹 class Soldier: #创建一个士兵的类 def __init__(self, name,gun=None): self.name = name #初始化士兵的姓名 self.gun = gun #初始化枪 def fire(self): #开火方法 if self.gun: #假如有枪 self.gun.shoot() #那就射击 else: #不然就显示没有枪 print('没有枪啊,兄弟,你让我去送死吗??') ak47 = Gun('AK47') #创建一个枪的对象叫ak47 ak47.add_count(10) #添加10颗子弹 xsd = Soldier('许三多') #实例化一个许三多的士兵对象 xsd.gun = ak47 #把枪交到许三多手中 xsd.fire() #开火
二、继承(单继承、多继承)
1、子类在继承的时候,在定义类时,小括号()中为父类的名字
父类的属性、方法,会被继承给子类
继承:继承实现代码的重用,相同的代码不需要重复的编写
class Anamal: 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('我会飞啦!!!!') dog = XiaoTianQuan() dog.eat() dog.run() dog.sleep() dog.drink() dog.bark() dog.fly()
2、重写父类方法与调用父类方法
所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
class Cat: def sayHello(self): print("hello-----1") class Bosi(Cat): def sayHello(self): print("hello-----2") bosi = Bosi() bosi.sayHello()
3、私有方法、私有属性在继承中的表现
如果调用的继承的父类中的公有方法,可以在这个公有方法中访问父类中的私有属性和私有方法;但是,如果在子类中实现一个公有方法,那么这个方法不能调用继承的父类中的私有方法和私有属性。
class A: def __init__(self): self.num1 = 100 self.__num2 = 200 def test1(self): print("------test1----") def __test2(self): # 私有方法 print("----test2-----") def test3(self): self.__test2() # 私有属性 print(self.__num2) class B(A): pass b = B() b.test1() # b.test2() # 私有方法不会被继承 # print(b.num1) # 继承默认共有方法,默认调用__init__方法 # print(b.__num2) # 私有的方法或者是属性不会被继承 b.test3() #既可以访问私有属性也可以访问私有方法
4、多继承
多继承,即子类有多个父类,并且具有它们的特征
class base(object): def test(self): print('----base test----') class A(base): # pass def test(self): print('----A test----') # 定义一个父类 class B(base): def test(self): print('----B test----') # 定义一个子类,继承自A、B class C(A,B): pass # def test(self): # print("-----test-C---") c = C() c.test() print(C.__mro__) #可以查看C类的对象搜索方法时的先后顺序 ------------------------------------------------------------------------- ----A test---- (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.base'>, <class 'object'>)
注意:尽量不要在类里面定义相同的方法名称
当要调用同名方法的时候,搜寻方法过程,当在某个类中找到方法,调用结束。
5、对父类的方法进行扩展
(1)在子类中重写父类的方法
(2)在需要的位置使用super().父类方法来调用父类方法的执行
(3)代码其它的位置针对子类的需求,编写子类特有的代码实现
关于super:
(1)在python中super是一个特殊的类
(2)super()就是使用super类创建出来的对象
(3)最常使用的场景就是在重写父类方法时,调用在父类中封装的方法实现
#用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() print('%*#*@^$*(@') dog = XiaoTianQuan() dog.eat() dog.run() dog.sleep() dog.drink() dog.bark() dog.fly()
三、多态
多态指的是一类事物有多种形态:如,动物有多种形态:人,狗,猪
多态指的是同一种事物的多种状态:如,水这种事物有多种状态:冰,水蒸气
例子1:
class Dog(object): def test(self): print("大家好,我是xxx,我是test1") class Xtq(Dog): def test(self): print("hello everybody") def introduce(temp): #temp 是接受参数自我功能的参数。此时temp指向dog1这个对象 temp.test() # 当传dog1的时候其实调用了基类这个方法 # 当传dog2的时候其实调用了子类这个方法 # 创建对象 dog1 = Dog() dog2 = Xtq() # 自我介绍的功能 introduce(dog1) # dog1自我介绍需要把dog1当做参数传进来 introduce(dog2) # 多态的定义 # 当写完程序的时候,我只是知道程序调用了一个方法,但是不确定调用基类的还是子类的 # 在执行的时候才根据对象是谁,才确定调用的是哪个方法,这就是叫做多态
例子2:
#多态的特性:让不同的子类对象调用相同的代码产生不同的结果 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)
面向对象的三大特性:
1、封装:根据职责将属性和方法封装到一个抽象的类中
定义类的准则
2、继承:实现代码的重用,相同的代码不需要重复的编写
设计类的技巧
子类针对自己特有的需求,编写特定的代码
3、多态:不同的子类对象调用相同的父类方法,产生不同的执行结果
多态可以增加代码的灵活度
以继承和重写父类方法为前提
是调用方法的技巧,不会影响到类的内部设计
面向对象三要素: (1)、封装 有些时候我们不希望把对象的属性公开,就可以把它设为私有,python并没有像其他语言对成员的权限控制系统,默认情况下,python的所有属性都是公有的,可以被访问到,要设成私有,则在前面加双下划线 (2)、继承 继承可以使子类拥有父类的属性和方法,并且可以重些这些方法,加强代码的复用性,python中子类可以有多个父类,但是不建议这样使用,一般会产生重复调用的问题,Super().方法名,可以调用父类的方法(不用传参,作用是调用父类的方法,传的是子类实例的值) (3)、多态 指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。