6.6继承
(1)单继承
子类在继承父类的时候(父类已定义),在定义子类的时候,小括号里面写要继承父类的类名。父类的属性和方法都会被子类继承。
语法:class 子类名(父类名):
xxxxxxxx
(2)多继承
一个子类可以继承多个父类(父类已定义),在定义子类的时候,小括号里面写要继承的父类的类名,多个父类之间用逗号隔开。如果继承了多个父类,如果父类间有同名属性和方法,默认继承第一个父类的属性和方法,不同名属性和方法不受影响。
语法:class 子类名(父类名1,父类名2,父类名3......)
xxxxxxxxx
(3)子类重写父类的同名属性和方法
只要自己有属性和方法,假如和父类相同,这时只执行自己的,不再执行父类的
(4)子类调用父类的同名方法和属性
语法:def 方法名(self):
要调用的父类类名.__init__(self)
要调用的父类类名.要调用的父类方法名:(self)
总结:调用谁的方法,做谁的初始化,然后调用相应的方法就可以了
(5)多层继承
孙类继承子类,孙类将继承子类的所有方法和属性,并且父类的属性和方法也会被继承
6.7私有属性和私有方法
在属性名或方法名前加上__(两个下划线),此时的属性或方法就成了私有属性或私有方法。注意:私有属性和方法受保护,私有属性和方法在类外不能被使用。
如果想访问或者修改私有属性或方法,习惯上用get_私有属性名和set_私有属性名来访问和修改
(不常用)如果想在类外访问私有属性,那么可以用:对象名._类名__私有属性
6.8super
调用父类的同名方法时用,只能实现多层单继承
(1)标准写法
super(自己的类名,self).__init__()
super(自己的类名,self).父类的方法名()
(2)简洁版
super().__init__()
super().父类的方法名
注意:super执行顺序:__mro__
可以用print(自己的类名.__mro__)来查看执行顺序
6.9python多态
在python中,没有严格意义的多态,而python中是“鸭子类型”
6.10类属性、类方法和静态方法
(1)类属性
就是直接写在类里面方法外的变量,类里面可以访问,类外面也可以访问,通常习惯以cls开头
如果实例属性和类属性的名字相同,那么通过对象去获取的时候,会获取实例属性的值
在类外访问类属性的方法:
①对象名.类属性名
②(常用方法)类名.类属性名
注意:通过对象名.类属性名=值,不会修改类属性的值,只是创建了一个新的实例属性,因此只能用类名.类属性名=值,这种方式来修改
(2)类方法
用@classmethod先申明
语法:@classmethod
def 方法名(cls):
xxxx
区别实例方法和类方法:参数是self的都是实例方法
调用类方法也可以用①对象名.类方法名②类名.类方法名
(3)静态方法
用@staticmethod先申明
语法:@staticmethod
def 方法名():
xxxxx
当函数与self和cls形参没有任何关系的时候用
调用静态方法也可以用①对象名.静态方法名②类名.静态方法名
6.11__new__
用来创建对象的,自动调用,魔法方法__new__是一个类方法
__new__工作原理:如果方法里面有返回值且返回值是自己这个类,才会执行__init__
单例模式:☆☆☆☆☆(面试重点考察)
class Person(object):
shuxing = None # 表示的是将来的new的返回值
def __new__(cls):
if cls.shuxing == None:
cls.shuxing = super().__new__(cls)
# 就等价于 cls.shuxing = object().__new__(cls)
# super().__new__(cls)会返回创建对象的地址
return cls.shuxing
def __init__(self):
print('init')
daqiu = Person()
erqiu = Person()
print(daqiu)
print(erqiu)
带参数的__new__()、单例模式以及只做一次初始化::
class Person(object):
shuxing = None # 表示的是将来的new的返回值
is_switch = True #一个开关,控制只做一次初始化
def __new__(cls,*args,**kwargs):
if cls.shuxing == None:
cls.shuxing = super().__new__(cls)
# 就等价于 cls.shuxing = object().__new__(cls)
# super().__new__(cls)会返回创建对象的地址
return cls.shuxing
def __init__(self,name,age,sex,id):
if self.is_switch == True: #控制只做一次初始化
self.name = name
self.age = age
self.sex = sex
self.id = id
self.is_switch = False
def __str__(self):
return '名字是%s,年龄是%s,性别是%s,id是:%s' % (self.name,self.age,self.sex,self.id)
daqiu = Person('大秋',18,'女',id=100)
erqiu = Person('二秋',10,'女',id=101)
print(daqiu)
print(erqiu)
6.12模块
6.12.1模块
在Python中用关键字import来引入某个模块。
一个py文件里面的代码整体就是一个模块。
在一个模块写完之后需要加一个main函数,里面是调用所有的函数,并在最后加一句话:if __name__ == '__main__':
main()
6.12.2导入模块
(1)导入并使用模块
方法一:
语法:import 模块名
模块名.函数名()
方法二:
语法:from 模块名 import 方法名/类名/变量名
方法名()
注意:如果导入了多个模块,有方法名冲突,只能执行最后导入的模块的方法
方法三:
语法:from 模块名 import * #*表示所有
方法名()
注意:如果导入了多个模块,有方法名冲突,只能执行最后导入的模块的方法
(2)__all__
写在被导入模块中,可以用来设置权限,限制用户只能导入该模块的某方法,但__all__仅能在上面的方法三中使用
语法:__all__[方法名1......]
6.13异常
6.13.1捕获异常
(1)捕获单个异常
语法:try:
xxxxxxxxx可能出现异常的程序xxxx
except 异常名称:
处理方式
(2)except捕获多个异常
当捕获多个异常时,可以把要捕获的异常的名字,放到except 后,并使用元组的方式仅进行存储。这种方式是说当出现异常1和异常2时处理的方式一样。
语法:try:
xxxxxxxxx可能出现异常的程序xxxx
except (异常名称1,异常名称2):
处理方式
(3)获取异常的基本信息
如果还想获取系统默认的保存的错误信息,那在异常名称后面加个as xxx即可
如:try:
xxxxxxxxx可能出现异常的程序xxxx
except (异常名称1,异常名称2) as result:
处理方式
print(result)
(4)捕获所有异常
方式一:
try:
xxxxxxxxx可能出现异常的程序xxxx
except:
处理方式
方式二:
try:
xxxxxxxxx可能出现异常的程序xxxx
except Exception as e: #exception是所有异常的父类
处理方式
print(e)
注意:如果方式一和方式二同时出现,那么需将方式一放到最后
(5)else
在try...except...中如果没有捕获到异常,那么就执行else中的事情
(6)try...finally...
在程序中,如果一个段代码必须要执行,即无论异常是否产生都要执行,那么此 时就需要使用finally。
6.13.2异常的传递
(1)如果try嵌套,那么如果里面的try没有捕获到这个异常,那么外面的try会接收到这个异常,然后进行处理,如果外边的try依然没有捕获到,那么再进行传递。。。
(2)如果一个异常是在一个函数中产生的,例如函数A---->函数B---->函数C,而异常是在函数C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常会传递到函数B中,如果函数B有异常处理那么就会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推。。。如果所有的函数都没有处理,那么此时就会进行异常的默认处理,即通常见到的那样
6.13.3自定义的异常
(1)自定义异常
class 异常名(Exception):
xxxxxxxx
(2)抛出自定义的异常——可用于提示用户
可以用“raise 异常类型名”来引发一个异常。异常/错误对象必须有一个名字,且它们应是Error或Exception类的子类