1.继承的简介
发现每个类的共同属性?
单独搞一个类,存共性,让各类产生关系? 这个关系就是继承
好处:
1.让类之间产生了关系,有了这关系,才有了多态的特性。
2.提高了代码的复用性。
**继承 是 面向对象的三大特性之一,我们使用继承可以获取另一个类的属性和方法
**@@@ 在定义类的时候,可以在类名的括号中指定当前类的父类(或超类、基类)
创建对象后,类就具体了,
继承的使用
#定义一个动物类
class Animal:
def run(self):
print('动物会跑...')
def sleep(self):
print('动物睡觉...')
a=Animal()
a.run()
#定义一个狗类
#@方案一、直接修改动物类,在动物类中添加我们需要的功能;但是动物类中有几十种方法呢,都改? 另外,OCP原则不要忘记。别去随意修改别人。
故:修改麻烦,且会违反OCP原则,这个方案不能用。
#@方案二、
#定义狗类
class Dog:
def run(self):
print('狗会跑...')
def sleep(self):
print('狗睡觉...')
def speak(self):
print('汪汪叫...')
a=Dog()
a.run()
#定义一个狗类
#@方案一、直接修改动物类,在动物类中添加我们需要的功能;但是动物类中有几十种方法呢,都改? 另外,OCP原则不要忘记。别去随意修改别人。
故:修改麻烦,且会违反OCP原则,这个方案不能用。
#创建一个新的类比骄傲麻烦,会出现大量重复性代码。
#@方案三、直接从animal类中继承它的属性和方法。
class Dog(Animal):#Animal 是Dog的父类
pass
def speak(self):
print('我会看家...')
d=Dog()
d.run() #动物会跑
d.sleep() #动物睡觉
d.speak() #我会看家
r=isinstance(d,Dog)
#检查d是否是Dog的实例, 结果是True
r=isinstance(d,Animal) #当然也是父类的实例对象, 结果是True
创建类的时候,如果省略了父类,默认父类为Object,以下可以看出 object是所有类的父类,所有类都继承于object。连内置int 也是object子类
class Person():
pass
issubclass() #检查一个类是否是另一个类的子类, 返回T或F
print(issubclass(Dog,Animal)) #TRUE
print(issubclass(Dog,object)) #TRUE
print(issubclass(Animal,object)) #TRUE
print(issubclass(Person,object)) #TRUE
print(issubclass(INT,object)) #TRUE
思考:父类和子类里都有相同方法,执行谁??
这叫方法的重写
2. 方法重写
#定义一个动物类
class Animal:
def run(self):
print('动物会跑...')
def sleep(self):
print('动物睡觉...')
a=Animal()
class Dog:
def run(self):
print('狗会跑...')
def sleep(self):
print('狗睡觉...')
def speak(self):
print('汪汪叫...')
a=Dog()
a.run()
例子: 结果为 A…
以下特别的是指:优先调用自己方法,如果没有向上父类找,继续直至找到object中有没有,没有才报错。
流程总结:
当我们调用一个对象的方法时,首先优先去当前对象寻找是否有该方法,如果有直接调用,如果没有则去当前对象的父类寻找该方法,如果父类中找到该方法,则直接调用父类中该方法,如果父类中没有,继续向上父类寻找该方法,直至到object
3.super
父类中的所有方法都会被子类继承,包括特殊方法,如property等如下:运行下,肯定报错。所以实例化时,注意要传递参数才可以。
#定义一个动物类
class Animal:
def_init_(self,name):
self._name=name
def run(self):
print('动物会跑...')
def sleep(self):
print('动物睡觉...')
@property
def name (self):
return self._name
@name.setter
def name(self,name):
self._name=name
class Dog:
def run(self):
print('狗会跑...')
def sleep(self):
print('狗睡觉...')
def speak(self):
print('汪汪叫...')
a=Dog()
a.run()
继承了特殊方法,注意参数要传递哦。如下,就可以了。但是要想有具体化结果,可以再print(d.name),结果就是打印了“藏獒”
#####################################
在Dog类中,重写了方法__init_
希望可以直接调用父类的__init_方法来初始化父类中定义的属性
思想:首先要知道父类是谁?
以下还是静态写死父类
那么动态获取当前类的父类,要用到 super了。
@@super()可以用来获取当前类的父类,通过super()调用父类方法时,不需要传递self
4.多重继承
__bases__*** 是双下划线哦
可以获取当前类所有的父类。
Python中支持多重继承,也就是我们可以为一个类同时指定多个父类。
下方运行结果看出是一个元组, 有逗号至少一个元素
可以在类名后的()中添加多个类,实现多重继承,
会使子类同时拥有多个父类,并获取到所有父类的方法。
如果一个类有多个父类,多个父类中有重名的方法,则会先去第一个父类中寻找,然后第二个,再然后…类推,找不到就报错。
如果下图这种不清不楚的关系,怎么找?
D找父类顺序是,A B object C
5.多态
多态是面向对象三大特性之一;
一个对象可以以不同的形态来呈现
如A 类和B 类有共同的
b不是检查类型,执行后无结果显示。
speak2()做了一个类型检查,只有A类型才能使用,其他类型无法使用该函数***,这个函数违反了多态。*** 只适用于一种类型的对象,无法处理其他类型对象,导致函数适用性很差。
#len() 的例子就是一个典型的多态, 你看它能管lst长度,能管’python‘长度。 所以呢,我们从一开始接触python,就接触了很多多态, 因为这些被处理的对象内部封装了特殊方法 叫做 “len”(注意是双下划线)
,换句话说只要有__len__就可以使用。
lst=[1,2,3,4,5,6]
s='python'
print(len(s))
面向对象三大特性:
- 封装 属性藏内部,想让你看才可以看到。_@确保数据安全
- 继承 对一个类进行扩展,子类和父类、多重父类 @保证了对象的可拓展性。
- 多态 让方法定义得更加灵活,并不拘泥于类型,只要满足条件,就可以使用。 @保证了程序的灵活性
今日回顾: