1.26 Python知识进阶 - 继承
继承
继承(Inheritance)是面向对象的程序设计中代码重要的主要方法。继承是允许使用现有类的功能,并在无需重新改写原来的类的情况下,对这些功能进行扩展。继承可以避免代码复制和相关的代码维护等问题。
被继承的类称为“基类(Base Class)”、“父类” 或 “超类(Super Class)”,通过继承创建的新类称为“子类(Subclass)” 或 “派生类(Derived Class)”。
声明格式:
class 派生类(基类1,[基类2,...]):
类体
其中,派生类名后为所有基类的名称元组。如果在类定义中没有指定基类,则默认其基类为objec。object是所有对象的根基类。
多个类的继承可以形成层次关系,通过类的方法mro()或类的属性__mro__可以输出其继承的层次关系。例如:
class A(object): pass class B(A): pass class C(B): pass class D(A): pass class E(B, D): pass print(D.mro()) print(E.__mro__)
------------------line----------------------
[<class '__main__.D'>, <class '__main__.A'>, <class 'object'>] (<class '__main__.E'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>)
声明派生类时,必须在其构造函数中调用基类的构造函数。调用格式:
基类名.__init__(self,参数列表)
定义一个Car类,再定义一个ElectricCar类,让其继承Car类属性和方法,示例代码:
class Car(object): def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): long_name = str(self.year) + ' ' + self.make + ' ' + self.model return long_name.title() def read_odometer(self): print("This car has " + str(self.odometer_reading) + "miles on it.") def update_odometer(self, mileage): if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("You can't roll back an odometer!") def increment_odometer(self, miles): self.odometer_reading += miles class ElectricCar(Car): def __init__(self, make, model, year): Car.__init__(self, make, model, year) my_tesla = ElectricCar('tesla', 'model s', 2016) print(my_tesla.get_descriptive_name())
------------------line----------------------
2016 Tesla Model S
这里Car就是ElectricCar的“父类” 或 “超类”, ElectricCar就是Car的“子类” 或 “派生类”。
代码“Car.__init__(self, make, model, year)”,让Python通过调用Car类中的__init__(),让ElectricCar实例包含父类的所有属性。
让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法,为电动汽车添加特有的属性(电瓶)。示例代码:
class Car(object): -- snip -- class ElectricCar(Car): def __init__(self, make, model, year): Car.__init__(self, make, model, year) self.battery_size = 70 def describe_battery(self): print("This car has a " + str(self.battery_size) + "-kWH battery.") my_tesla = ElectricCar('tesla', 'model s', 2016) print(my_tesla.get_descriptive_name()) my_tesla.describe_battery()
------------------line----------------------
2016 Tesla Model S This car has a 70-kWH battery.
有的时候父类的一些方法可能不子类的一些特性,我们需要对父类的方法重新构造,我们可在子类中重新定义一个这样的方法,即与要重写的父类的方法同名。假如Car类中有fill_gas_tank()方法,我们在ElectricCar中重构。示例代码:
class ElectricCar(Car): -- snip -- def fill_gas_tank(self): print("This car does't need a gas tank!")
记住,先继承,再重构。
Python支持多重继承,即一个派生类可以继承多个基类。
多个类的继承可以形成层次关系,通过类的方法mro()或类的属性__mro__可以输出其继承的层次关系。例如:
class A(object): pass
class B(A): pass
class C(B): pass
class D(A): pass
class E(B, D): pass
print(D.mro())
print(E.__mro__)
------------------line----------------------
[<class '__main__.D'>, <class '__main__.A'>, <class 'object'>]
(<class '__main__.E'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>)
附1,练习代码:
class SchoolMember(object): members = 0 def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex self.enroll() def enroll(self): print("just enrolled a school member [%s] ." % self.name) SchoolMember.members += 1 def tell(self): print("------%s info------" % self.name) for k,v in self.__dict__.items(): print("\t",k,v) def __del__(self): print("开除了[%s]..." % self.name) SchoolMember.members += 1 class Teacher(SchoolMember): def __init__(self, name, age, sex, salary, course): SchoolMember.__init__(self, name, age, sex) self.salary = salary self.course = course def teaching(self): print("Teacher [%s] is teaching [%s]." % (self.name, self.course)) class Student(SchoolMember): def __init__(self, name, age, sex, course, tuition): SchoolMember.__init__(self, name, age, sex) self.course = course self.tuition = tuition self.amount = 0 def pay_tuition(self, amount): print("Student [%s] has just paied [%s]." % (self.name, amount)) self.amount += amount t1 = Teacher("Alex", 33, "M", 2000, "Python") s1 = Student("John", 20, "M", "Python", 30000)
附2,关于新旧类的问题:
写法1,又称经典类写法:
基类名.__init__(self,基类中的属性)
写法2,又称新式类写法:
Python 2.7中:
super(子类名,self).__init__(基类中的属性)
Python 3.x中:
super().__init__(基类中的属性)
注:在Python 2.7中使用继承时,务必在定义父类时在括号内指定object。