python笔记(19)--面向对象三大特性补充
内容目录:
- 继承
- 多态
- 封装
内容回顾
-
面向对象编程:
-
思想:角色的抽象,创建类,创建角色(实例化),操作这些实例
-
面向对象的关键字
-
#示例: class Object: #类名首字母大写 name = 'lyn' def __init__(self):pass Object.name #存储在类的命名空间里 obj = Object() #实例化:创造一个self对象,执行init方法,返回self对象给obj #对象.属性 #对象.方法 相等于 类名.方法(对象) #对象可以使用静态变量吗? True #类可以使用对象的属性吗? False
-
组合(最起码是两个类)
-
一个类的对象是另外一个类对象的属性
-
class A: def __init__(self): self.name = 'alec' class B: def __init__(self,year,month,day): self.year = year self.month = month self.day = day b = B(19, 1, 17) print(b.year,b.month,b.day) a = A() a.birth = b print(a.birth.year)
-
-
内容详细:
1.继承
1.1 单继承
-
类和类之间才能被称为继承,类和对象之间只能是实例化
-
一个类可以被多个类继承 ----只在python里适用
class A:pass #父类,基类,超类 class B:pass #父类,基类,超类 class A_son(A):pass #子类,派生类 class AB_son(A,B):pass #可以继承多个父类 #查看继承的父类 print(A_son.__bases__) #(<class '__main__.A'>,) print(AB_son.__bases__) #(<class '__main__.A'>, <class '__main__.B'>)
-
新式类:python3里所有的类都有父类,如果没有标识继承的父类,那它就是 object 的子类
-
继承示例:
# 把Dog和Person类中的同样的变量提取至Animal类中 class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp # 继承Animal类,可以使用父类中的变量 class Dog(Animal): def bite(self,person): person.hp -= self.aggr class Person(Animal): pass #正常传值和调用 jin = Dog('史努比',200,500) print(jin.name)
-
面试题:
class Animal: def __init__(self): print('执行Animal.__init__') self.func() def eat(self): print('%s eating'%(self.name,)) def drink(self): print('%s drink' % (self.name,)) def func(self): print('Animal.func') class Dog(Animal): def guard(self): print('guard') def func(self): print('Dog.func') dog = Dog() #结果为: # 执行Animal.__init__ # Dog.func
1.2 派生属性
-
派生属性:继承父类中的变量,然后自己也创建了一些特有属性
class Animal: def __init__(self,name,blood,aggr): self.name = name self.blood = blood self.aggr = aggr class Dog(Animal): def __init__(self,name,blood,aggr,kind): Animal.__init__(self,name,blood,aggr) #调用了父类的属性 self.kind = kind #自己创建的,属派生属性
-
派生方法:父类中没有的方法,在子类中出现,叫做派生方法
- 只要是子类的对象调用,子类中有的方法一定用子类的,子类中没有才能去找父类的,都没有则报错
- 如果既想实现新功能也想适用父类的功能,还需在子类中调用父类的方法
class Animal: def __init__(self,name,blood,aggr): self.name = name self.blood = blood self.aggr = aggr def eat(self): print('生命值增加100点') self.blood += 100 class Dog(Animal): def __init__(self,name,blood,aggr,kind): Animal.__init__(self,name,blood,aggr) self.kind = kind def eat(self): Animal.eat(self) #自己有并还想用父类的,则调用父类方法 self.aggr += 10 def bite(self,person): person.blood -= self.aggr print('狗咬人,人剩了%s血'%(person.blood)) jin = Dog('金老板',100,20,'teddy') jin.eat() print(jin.blood,jin.aggr)
总结:
- 父类中没有的属性,在子类中出现,叫做派生属性
- 父类中没有的方法,在子类中出现,叫做派生方法
- 只要是子类的对象调用,子类中有的方法一定用子类的,子类中没有才能去找父类的,都没有则报错
- 如果子类调用的方法自己有并还想用父类的,单独调用父类的,需要自己传self方法
1.3 关键字super的用法:只能在新式类中使用
-
super的内部用法,相等于调用父类的init方法
-
super的外部用法,只调用父类的方法: super(子类名,实例化对象).父类中的方法
class Animal: def __init__(self,name,blood,aggr): self.name = name self.blood = blood self.aggr = aggr def eat(self): print('生命值增加100点') self.blood += 100 class Dog(Animal): def __init__(self,name,blood,aggr,kind): super().__init__(name,blood,aggr) #内部使用super方法,相等于Animal.__init__(self,name,blood,aggr) self.kind = kind def eat(self): self.aggr += 10 def bite(self,person): person.blood -= self.aggr print('狗咬人,人剩了%s血'%(person.blood)) jin = Dog('金老板',100,20,'teddy') jin.eat() #只调用自己的方法 super(Dog,jin).eat() #super用法:只调用父类的方法 print(jin.blood,jin.aggr)
1.4 多继承
-
多继承中,我们子类的对象调用一个方法,默认是就近原则
class A: def func(self):print('A') class B: def func(self):print('B') class C(A,B): #继承父类时,先找A,再找B,顺序查找 # def func(self):print('C') pass c = C() c.func() #结果为A
-
查看继承关系: 对象.mor()
#接上面列子 print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
-
钻石继承
- py2中经典类中遵循深度优先,py3中新式类遵循广度优先
-
多继承
2.多态
-
接口类和抽象类 在python当中的应用点并不是非常必要的
- 使用abc模块来规范子类,必须有父类中的方法
import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class People(Animal): #动物的形态之一:人 def talk(self): print('say hello') class Dog(Animal): #动物的形态之二:狗 def talk(self): print('say wangwang') class Pig(Animal): #动物的形态之三:猪 def talk(self): print('say aoao')
-
因为python中不崇尚用父类约束子类的方法,因为python当中有鸭子类型
3.封装
3.1 类中私有
-
所有的私有,都是在变量的左边加上双下划线
- 对象的私有属性
- 类中的私有方法
- 类中的静态私有属性
-
所有的私有的,都不能在类的外部使用
class Person: __key = 123 # 私有静态属性 def __init__(self,name,passwd): self.name = name self.__passwd = passwd # 私有属性 def __get_pwd(self): # 私有方法 # print(self.__dict__) return self.__passwd def login(self): return self.__get_pwd() alec = Person('alec','123456') print(alec.__dict__) # 查看类内部的所有属性,然后可以强制调用私有属性 pwd =alec.login() print(pwd)
-
应用场景:
- 隐藏起一个属性,不想让类的外部调用
- 保护这个属性,不想让属性随意被改变
- 保护这个属性不被子类继承