12.1 继承
继承
继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
python中如何继承
在定义类的时候,类名后有个括号,当括号里写着另外一个类的名字时,表示该类继承于另外一个类
#定义animal类
class Person:
def __init__(self,name):
self.name = name
def say(self):
print("My name is"+" "+self.name)
#Actor继承Person
class Actor(Person):
pass
#Student继承Person
class Student(Person):
pass
actor1=Actor("Mew")
actor1.say()
print(actor1.name)
student1=Student("Gulf")
student1.say()
print(student1.name)
- 子类可以有自己的属性与方法
#定义animal类
class Person:
def __init__(self,name):
self.name = name
def watch(self):
print(self.name+" "+"is watching TV")
#Actor继承Person
class Actor(Person):
def study(self):
print(self.name+" "+"is studying")
actor1=Actor("Mew")
actor1.watch()
actor1.study()
- 子类具备父类所有的属性与功能,但是父类并不具备子类的属性与功能
#定义animal类
class Person:
def __init__(self,name):
self.name = name
def watch(self):
print(self.name+" "+"is watching TV")
#Actor继承Person
class Actor(Person):
def study(self):
print(self.name+" "+"is studying")
person=Person("people")
actor=Actor("Mew")
print(isinstance(person,Actor))#验证person是否是Actor的实例 False
print(isinstance(actor,Person))#验证actor是否是Person的实例 True
- 当子类有自己的构造方法时,将会覆盖父类的构造方法
#定义animal类
class Person:
def __init__(self):
print("person")
#Actor继承Person
class Actor(Person):
def __init__(self):
print("Gulf")
actor=Actor()
#输出Gulf
- 子类重写父类方法
#定义animal类
class Person:
def __init__(self):
print("person")
def say(self):
print("a person loves Gulf")
#Actor继承Person
class Actor(Person):
def __init__(self):
print("Mew")
def say(self,name):
print("Mew loves"+" "+name)
actor=Actor()
actor.say("Gulf")
注意: 当且仅当子类方法与父类同名,入参相同,才可称之为重写父类的方法
12.2 super的作用及其用法
#定义animal类
class Person:
def __init__(self,name):
self.name=name
#Actor继承Person
class Actor(Person):
def __init__(self):
print("actor")
actor=Actor()
print(actor.__dict__)
输出:
actor
{}
super() 函数是用于调用父类(超类)的一个方法。一般是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
super函数的基本语法
super(类名,self)
在python3中,可以直接使用super()而无需任何参数来调用父类
#定义animal类
class Person:
def __init__(self,name):
self.name=name
#Actor继承Person
class Actor(Person):
def __init__(self,name):
super(Actor,self).__init__(name)
print("actor")
actor=Actor("Mew")
print(actor.__dict__)
print(actor.name)
输出:
actor
{‘name’: ‘Mew’}
Mew
12.3 抽象方法与多态
抽象方法:
在面向对象编程语言中抽象方法指一些只有方法声明,而没有具体方法体的方法。抽象方法一般存在于抽象类或接口中。抽象类的一个特点是它不能直接被实例化,子类要么是抽象类,要么,必须实现父类抽象类里定义的抽象方法
在python3中可以通过使用abc模块轻松的定义抽象类
定义抽象类
from abc import ABCMeta,abstractmethod
#定义抽象类时,使用metaclass=ABCMeta
class Person(metaclass=ABCMeta):
@abstractmethod
def say(self):
pass
class Actor(Person):
def say(self):
print("I love Gulf")
actor=Actor()
actor.say()
抽象类的子类必须实现抽象类中所定义的所有方法,否则,程序不能正确运行
from abc import ABCMeta,abstractmethod
class Person(metaclass=ABCMeta):
@abstractmethod
def say(self):
pass
class Actor(Person):
pass
actor=Actor()
actor.say()
输出:
TypeError: Can’t instantiate abstract class Actor with abstract methods say
即使是实现部分抽象方法也是不行的
from abc import ABCMeta,abstractmethod
class Person(metaclass=ABCMeta):
@abstractmethod
def say(self):
pass
@abstractmethod
def word(self):
pass
class Actor(Person):
def say(self):
print("I love Gulf")
actor=Actor()
actor.say()
输出:
TypeError: Can’t instantiate abstract class Actor with abstract methods word
多态
不同的子类对象调用相同的父类方法,产生不同的执行结果,可以增加程序的灵活性和可扩展性
from abc import ABCMeta,abstractmethod
class Person(metaclass=ABCMeta):
@abstractmethod
def say(self):
pass
@abstractmethod
def word(self):
pass
def inaword(self):
self.say()
self.word()
class Actor(Person):
def say(self):
print("My name is Mew")
def word(self):
print("And I love Gulf")
class Student(Person):
def say(self):
print("My name is Gulf")
def word(self):
print("And I love Mew")
#不同的子类对象,调用父类的inaword()方法,产生不同的执行结果
actor=Actor()
student=Student()
actor.inaword()
student.inaword()
12.4 多重继承
一个子类可以继承多个父类
class Wife:
def wifesay(self):
print("I am Gulf")
class Husband:
def husband(self):
print("I am Mew")
class Viewer(Wife,Husband):
pass
viewer=Viewer()
viewer.wifesay()
viewer.husband()
如果父类中有相同的方法,子类会按照继承的顺序继承
class Wife:
def wifesay(self):
print("I am Gulf")
def husband(self):
print("And I am Husband")
class Husband:
def husband(self):
print("I am Mew")
#class Viewer(Wife,Husband):
#输出:I am Gulf And I am Husband
class Viewer(Husband,Wife):
#输出:I am Gulf I am Mew
pass
viewer=Viewer()
viewer.wifesay()
viewer.husband()
12.5 多重继承
新式类与旧式类
新式类都从object继承(python3中,默认都继承自object),经典类不需要。
新式类的MRO(method resolution order 基类搜索顺序)算法采用C3算法广度优先搜索,而旧式类的MRO算法是采用深度优先搜索
新式类相同父类只执行一次构造函数,经典类重复执行多次。
class Person:
def say(self):
print("person")
class Actor1(Person):
def say(self):
print("Gulf")
class Actor2(Person):
def say(self):
print("Mew")
class Viewer(Actor1,Actor2):
def say(self):
print("we love them")
v=Viewer()
v.say()
输出:
we love them
菱形继承(钻石继承)
在多重继承中,直接使用父类名字调用构造,会发生问题
class Person:
def __init__(self):
print("this is a person")
def say(self):
print("person")
class Actor1(Person):
def __init__(self):
Person.__init__(self)
def say(self):
print("Gulf")
class Actor2(Person):
def __init__(self):
Person.__init__(self)
def say(self):
print("Mew")
class Viewer(Actor1,Actor2):
def __init__(self):
Actor1.__init__(self)
Actor2.__init__(self)
def say(self):
print("we love them")
v=Viewer()
v.say()
输出:
this is a person
this is a person
we love them
使用**super()**可以解决菱形继承多次调用构造的问题
class Person:
def __init__(self):
print("they are a couple")
def say(self):
print("person")
class Actor1(Person):
def __init__(self):
print("Gulf")
super().__init__()
def say(self):
print("Gulf")
class Actor2(Person):
def __init__(self):
print("Mew")
super().__init__()
def say(self):
print("Mew")
class Viewer(Actor1,Actor2):
def __init__(self):
super().__init__()
def say(self):
print("we love them")
v=Viewer()
v.say()
输出:
Gulf
Mew
they are a couple
we love them
12.6 枚举类
一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。
from enum import Enum, unique
枚举类的特性:
- 定义枚举时,其枚举成员的名称不允许相同
- 默认情况下,不同的成员值允许相同。但是两个相同值的成员,其第二个成员名称是第一个成员名称的别名;因此在访问枚举成员时,只能获取第一个成员。
- 如果要限定枚举里面所有的值必须唯一,可以在定义枚举类时,加上@unique
- 枚举的比较,只能是成员与成员,或者值与值,不能成员与值比较