1. 面向对象的继承
-
定义:继承是一种创建新类的方式
-
种类:新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
-
方式:
-
单继承:所有的类默认都会继承'object'
-
多继承:继承多个类时,使用逗号分割,默认继承最左边的父类
-
__base__:只查看从左到右继承的第一个子类;如果没有继承,默认返回:<class 'object'>
class Biology:
pass
class Animal:
pass
class Cat(Biology):
pass
class Dog(Animal):
pass
class Monkey(Biology, Animal):
pass
print(Biology.__base__)
print(Animal.__base__)
print(Cat.__base__)
print(Dog.__base__)
print(Monkey.__base__)
>>>
<class 'object'>
<class 'object'>
<class '__main__.Biology'>
<class '__main__.Animal'>
<class '__main__.Biology'>
-
__bases__:查看所有继承的父类,返回元组格式;如果没有继承,默认返回:(<class 'object'>,)
class Biology:
pass
class Animal:
pass
class Cat(Biology):
pass
class Dog(Animal):
pass
class Monkey(Biology, Animal):
pass
print(Biology.__bases__)
print(Animal.__bases__)
print(Cat.__bases__)
print(Dog.__bases__)
print(Monkey.__bases__)
>>>
(<class 'object'>,)
(<class 'object'>,)
(<class '__main__.Biology'>,)
(<class '__main__.Animal'>,)
(<class '__main__.Biology'>, <class '__main__.Animal'>)
2. 类的说明
-
查看类的属性:
-
dir(类名):查出的是一个名字列表,里面包含这个类的所有方法
-
类名.__dict__:查出的是一个字典,key为属性名,value为属性值
-
特殊的类属性:
-
类名.__name__:类的名字,字符串类型
-
类名.__doc__:类的文档,字符串类型
-
类名.__base__:类的第一个父类
-
类名.__bases__:以元组的形式返回类的所有父类
-
类名.__dict__: 以字典的形式返回类的所有属性
-
类名.__module__:类所在的模块名,字符串类型
-
实例名.__class__:返回实例名所属的类名
3. 继承与抽象(先抽象后继承)
+ ##### 抽象(从具体到模糊的过程):即抽取类似或者说比较像的部分;抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类
+ ##### 继承(从模糊到具体的过程):是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构
4. 继承的派生
-
派生:子类在父类方法和属性的基础上产生了新的方法和属性
-
派生属性:在子类的__init__中使用父类的__init__的属性。调用父类的属性时,可以使用父类名.__init__;也可以使用super()方法,super()方法中的参数在类中使用可以省略
-
派生方法:在子类中增加父类中没有的方法
-
子类中有的方法,就使用子类的
-
父类中没有的方法,子类中有,会使用子类的
-
父类中有的方法,子类也有,会使用子类的
-
父类中有的方法,子类中没有,会使用父类的
-
父类中有的方法,子类也有,如果想坚持使用父类中的或父类子类都想用,需要使用:父类名.父类的方法名(子类的对象)
-
经典类(python2默认的面向对象类型):类名.方法名(子类对象名),类内类外调用方式一样
-
新式类(python3默认的面向对象类型):super(子类, 子类对象名).方法名(),如果在类中调用可以省略super()方法中的参数
class Life:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('吃...')
def drink(self):
print('喝...')
class Person(Life):
def __init__(self, name, age, nation):
Life.__init__(self, name, age)
self.nation = nation
def get_money(self):
print('挣钱。。。')
def eat(self):
print('人吃饭。。。')
class Dog(Life):
def __init__(self, name, age, breed):
super(Dog, self).__init__(name, age)
self.breed = breed
def watch_door(self):
print('看门。。。')
def drink(self):
print('狗喝水。。。')
yan = Person('岩哥', 25, '汉族')
king = Dog('斑马', 2, '金毛')
print(yan.name)
print(king.age)
print('-' * 20)
print(yan.nation)
print(king.breed)
print('-' * 20)
yan.get_money()
king.watch_door()
print('-' * 20)
yan.eat()
super(Person, yan).eat()
king.eat()
print('-' * 20)
yan.drink()
king.drink()
super(Dog, king).drink()
>>>
岩哥
2
--------------------
汉族
金毛
--------------------
挣钱。。。
看门。。。
--------------------
人吃饭。。。
吃...
吃...
--------------------
喝...
狗喝水。。。
喝...
5. 钻石继承
# 经典类(三层)的继承顺序
class D:
pass
class C(D):
pass
class B(D):
pass
class A(B, C):
pass
print(A.mro())
>>>
print(A.mro())
AttributeError: class A has no attribute 'mro'
# python2不支持mro()方法,正确的顺序是:A-->B-->D-->C
# 经典类(四层)的继承顺序
class F:
pass
class E(F):
pass
class D(F):
pass
class C(E):
pass
class B(D):
pass
class A(B, C):
pass
print(A.mro())
>>>
print(A.mro())
AttributeError: class A has no attribute 'mro'
# python2不支持mro()方法,正确的顺序是:A-->B-->D-->F-->C-->E
# 新式类(三层)的继承顺序
class D(object):
pass
class C(D):
pass
class B(D):
pass
class A(B, C):
pass
print(A.mro())
>>>
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <type 'object'>]
# 新式类(四层)的继承顺序
class F(object):
pass
class E(F):
pass
class D(F):
pass
class C(E):
pass
class B(D):
pass
class A(B, C):
pass
print(A.mro())
>>>
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <type 'object'>]
6. 抽象类与接口类
-
继承有两种用途:
-
继承基类的方法,并且做出自己的改变或者扩展(代码重用)
-
声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
-
抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
-
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性
-
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性
-
抽象类是一个介于类和接口之间的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计
-
多继承问题:
-
在继承抽象类的过程中,应该尽量避免多继承
-
在继承接口的时候,应该多继承接口
-
方法的实现:
-
在抽象类中,可以对一些抽象方法做出基础实现
-
在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
-
依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程
-
接口隔离原则:使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口
7. 多态
-
多态:多态指的是一类事物有多种形态;python自带多态功能
-
多态性:多态性是指在不考虑实例类型的情况下使用实例
-
鸭子类型:python崇尚鸭子类型