文章目录
面向对象的三个特征:封装 继承 多态
1 继承
1.1 继承的概念
什么是继承?
继承是指一个对象直接使用另一个对象的属性和方法。也指按照法律或遵照遗嘱接受死者的财产、职务、头衔、地位等
继承:
程序来说:指的是子类继承父类的属性和方法。
- 单继承:指的是子类只有一个父类
- 多继承:指的是子类有多个父类
1.2 单继承
如果在子类中没有定义__init__方法,但是父类中定义了此方法,那么子类继承父类的时候这个方法也被继承了,所以只要创建子类的对象,就默认执行了__init__这个方法
定义子类的格式:
class 子类名(父类名)
#所有子类都有一个父类,父类是object
子类会继承父类的属性、方法
子类拥有父类的属性和方法,因此在子类中只需要定义自己的方法
- 子类不能直接访问父类的私有属性和私有方法,但是我们可以在父类中通过父类 中的公有方法调用父类中的私有方法或父类中的私有属性。
- 当子类和父类中同时存在某个方法的时候,优先调用子类中的方法
- 如果子类中没有此方法,那么就调用父类中的方法
- 查看子类调用顺序:类名.mro
- 如果在子类中写了一个和父类中方法同名的方法,那么称之为重写父类中的方法
class Animal(object):
def __init__(self):
self.name='动物'
self.age=0
self.color=''
self.__flag='独家'
def run(self):
print('动物会奔跑')
def eat(self):
print('动物吃食物')
def __talk(self):
print(self.__flag)
print('特有的叫声')
def A(self):
self.__talk()
print('A')
def test(self):
print('父类中的test方法')
class Cat(Animal):
def test(self):
print('cat的方法')
cat=Cat()
print(cat.name)
cat.run()
# cat.test()
# print(cat.__flag)
# cat.__talk()
cat.A()
cat.test()
print(Cat.__mro__)
结果:
1.3 多继承
多继承:
- 就是子类有多个父类,并且具有他们的特征
书写格式:
class 子类名(父类1,父类2,...):
子类继承父类的属性和方法
当子类中的属性或方法没有被定义的时候,去父类中查看,查看的顺序按照括
号里面的顺序进行搜索
重写父类方法
重写就是在子类中,有一个和父类同名的方法,在子类中的方法会覆盖父类中同名的方法
class Horse:
def __init__(self):
self.name='小马'
self.__age=0
self.color=''
def run(self):
print('这是马的奔跑方式')
def test(self):
print(self.color)
class Donkey:
def __init__(self):
self.name='xiaolv'
self.__age=0
self.color='棕'
def run(self):
print('驴的奔跑方式')
def drank(self):
print('驴喝水')
class Mule(Horse,Donkey):
def X(self):
print('骡子的方法')
mule=Mule()
mule.X()
mule.test()
mule.drank()
mule.run()
print(Mule.__mro__)
结果:
2 多态
2.1 多态的概念
多态:
- 多态也是继承中的特点
- 定义时的类型和运行时的类型不一样
- 在定义的时候不明确使用的是谁的方法,只有在调用的时候才明确是哪一个
类中的某个方法
class S1:
def test(self):
print('这是S1的test方法')
class S2:
def test(self):
print('这是S2的test方法')
def fun(a):
a.test()
s1=S1()
fun(s1)
结果:
2.2 类属性和实例属性
- 实例属性就是对象属性。
- 类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本。
- 对于公有的类属性,在类外可以通过类对象和实例对象访问。
- 类属性是在类中直接声明的,类似于全局变量。
类属性的调用:
可以被实例化对象调用和类本身调用。
私有类属性:
和私有属性一样,在属性名前面加上两个下划线,不能直接在类的外部进行访问,但是可以在类的内部进行访问。
类属性的修改
1 类名.类属性名=值
- 当通过类名和实例化对象访问这个类属性的时候,这个类属性的值是改变之后的值
2 对象名.类属性名=值
- 本质上是给这个对象增加了一个实例属性,因为通过这种方法修改的属性的值,其实还是实例对象的属性的值,并没有修改类属性的值,因此通过类.类属性名的属性值没有被改变。
class Cat:
name='小花'
__color='蓝色'
def __init__(self):
self.age=12
def test(self):
print(Cat.__color)
print(self.__color)
print(self.age)
print(self.name)
cat=Cat()
# cat.test()
Cat.name='肖类'
# print(Cat.name)
# print(Cat.__color)
# cat.name='晓晓'
print(cat.name)
print(Cat.name)
结果:
总结
- 如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。
- 如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
2.3 类方法和静态方法
类方法
-
类方法时类对象所拥有的方法,需要用修饰器@classmethod标识为类方法。
-
类方法第一个参数必须是类对象,一般以cls作为第一个参数,能够通过实例对象和类对象去访问。
-
类方法可以对类属性进行修改。
类方法的访问: -
可以被类本身访问和实例化对象访问
静态方法
-
通过@staticmethod修饰,静态方法不需要多定义参数
类方法的调用
公有类方法:实例化对象 类 实例方法
私有类方法:不能在类的外部直接访问,但是可以在类内部进行访问
在类的内部可以被实例方法 和 类方法访问
注释:
在同一个类中,方法名不要相同
class A:
name='小花'
__age=0
def __init__(self):
print('init')
def test(self):
self.__test2()
print('a')
@classmethod
def test1(cls):
cls.__test2()
cls.name='小蓝'
print('test')
print(cls.name)
@classmethod
def __test2(cls):
cls.__age=3
print(cls.__age)
a=A()
# a.test()
# a.test1()
# A.test1()
a.test()
结果:
3 异常
3.1 异常介绍
异常:
python解释器检测到错误的时候,无法继续运行程序
常见异常:
ZeroDivisionError:除数不能为0
IndexError:索引异常,超出索引的范围
NameError:变量没有定义
FileNotFoundError:文件没有找到
classnotfound:没有找到类
3.2 捕获异常(处理方式)
try-except
把那些可能出现异常的代码放入到try代码块中
except代码块中的代码会在try代码块中出现问题的时候运行
try-except-except
except可以有多个子句
顺序:需要把最大的那个异常放到最后,因为当程序直接捕捉到最大的异常的时候
,不会执行后面的except子句。
try:
print(b)
#错误示范,Exception最大异常,需要放到最后
except(Exception):
print('程序出错')
except(FileNotFoundError):
print('文件没有找到')
except(NameError):
print('变量没有定义')
结果:(先经过最大异常检测,所以直接出来结果)
程序出错
try-except(多个)
如果把except多个子句写成一个except子句的时候,在括号里面写入异常的类型,
用逗号隔开,同样也是把最大的异常写在最后
try:
print(b)
a=10/0
print(a)
except(ZeroDivisionError,IndexError,NameError):
print('程序出错')
try-except-finally
finally子句中,无论上面的代码是否需要捕捉异常,那么都会执行的代码
try:
f=open('k.txt')
content=f.read()
print(content)
except(FileNotFoundError):
print('文件没有找到')
finally:
try:
f.close()
except:
print('aaa')
结果:
try-except-else
当try中的代码没有错的时候,那么执行else里面的,如果在try中有异常的时候,
执行except子句中的代码
try:
a=10/1
except:
print('-----------')
else:
print('end')
结果:
自定义异常类:
如何定义异常类:
需要继承存在的异常类,通常我们继承的是Exception
class MyExceptin(Exception)
有时候,python给我们提供的异常不满足
比如:从键盘上接收数字,如果长度>3,抛出异常,长度不能大于3
所以需要自己定义异常类
class MyLengthException(Exception):
def __init__(self,length):
super().__init__()
self.length=length
def __str__(self):
return 'Error[1023] num length not gt 3'
def main():
try:
s=input('请输入一个字符串:')
if len(s)>3:
raise MyLengthException(len(s))
else:
print(s)
except MyLengthException as result:
print('有异常发生,这个异常是:%s'%result)
main()
结果:
4 单继承和圆柱
计算圆柱的表面积和体积:
class Circle:
def __init__(self,r):
self.r=r
def getArea(self):
self.area=3.14*self.r*self.r
return self.area
def getPerimeter(self):
self.perimeter=2*3.14*self.r
return self.perimeter
def __str__(self):
return str(self.getPerimeter())+'\t'+str(self.getArea())
class CircleRect(Circle):
def __init__(self,r,h):
# Circle.__init__(self,r) # 第一种调用父类中的初始化方法
super().__init__(r) # 第二种调用父类中的初始化方法
self.h=h
def getSFA(self):
self.sfa=2*self.getArea()+self.getPerimeter()*self.h
return self.sfa
def getV(self):
self.v=self.getArea()*self.h
return self.v
def printInfo(self):
print('圆柱的表面积是'+str(self.getSFA())+'\n'+'圆柱的体积是'+str(self.getV()))
ct=CircleRect(3,2)
ct.printInfo()
结果: