面向对象
类
定义格式
class 类名:
方法列表
备注:
定义方法时,在形参列表的第一个必须是self
self参数
对象不存储方法。方法中的self表示,正在调用方法的对象,哪个对象正在调用方法,self就表示哪个对象。
python解释器能够根据self的值确定哪个对象正在调用方法
相关函数
__init__
方法:魔法方法,Python解释器会在对象刚创建后立即调用这个方法。
初始化对象:给对象添加属性并赋值
通过self给对象添加属性:
self.属性名 = 属性值
属性是存储在对象里面的。
属性是属于对象的。
访问 属性:对象名.属性名
在对象的其他方法中,也能添加属性。但最好不要这么做,因为必须调用那个方法后,才有那个属性。
也能通过对象直接创建,但弊端跟在其他方法中创建属性一样。不要这么做。
综上,最好还是把属性全部加载init方法里
__str__
方法:跟java里面的tostring方法差不多,必须返回一个字符串。
默认返回对象的地址
__del__
方法:当删除对象时,python解释器也会默认调用一个方法,这个方法为
__del__()
方法
私有属性
这样的属性只能在类的里面访问,不能在类外面访问
定义格式
self.__属性名 = 属性值
访问格式
self.__属性名
私有方法
这种方法只能在类中调用。
Python中的私有属性和私有方法是伪的。当你在将属性或者方法命名成私有之后。解释器会对其做特殊的命名处理。
处理格式:
在名称前面加上_类名
,即变成_类名__名称
即通过这样就可以在外界访问私有属性和私有方法
继承:
子类继承父类,就拥有父类中非私有的属性和方法
格式:
class A(object):
object即为父类。
object类
所有类的父类,默认所有类都继承了object类
重写父类的方法
在子类中定义一个同名的方法,一旦重写了这个方法,就不会在调用父类的方法了。
在子类中调用父类中被重写的方法
怎么调用已经被重写的方法呢?
- 父类名.方法名(self,实参1,实参2)
- super().方法名(实参1,实参2, ...)
在子类中调用没被重写的方法
- self.方法名
多层继承:
一层一层的继承
多继承:
一个子类同时继承多个父类,继承顺序从括号里从左向右继承,已经继承的方法就不会再继承
格式:
class 子类名(父类1,父类2,...)
实例属性和实例方法
实例属性指给实例对象添加的属性,实例属性是存储在实例对象里
实例方法指第一个参数是self的方法是实例方法,因为self指实例对象
类对象和类属性
类对象:一个类就是一个类对象,类的名字就类对象的名字
类属性:所有实例对象共享的属性,且可以定义为私有属性
类属性的定义格式:
- 在类的地面,方法的外面定义
类属性的访问格式:
- 实例对象名.属性名
- 类名.属性名(推荐)
修改类属性:
- 只能通过类对象(类名)修改。
类方法
定义方法时,在括号里写(cls),并且用装饰器@classmethod
@classmethod
def study(cls):
pass
在类方法中,只能访问类属性和类方法,不能访问实例属性和实例方法
使用方式:
实例对象.类方法名(实参列表)
类名对象.类方法名(实参列表)
多态
在需要使用父类对象的地方,也可以使用子类对象, 这种情况就叫多态.
比如, 在函数中,我需要调用 某一个父类对象的方法, 那么我们也可以在这个地方调用子类对象的方法.
跟C++中,参数列表是父类指针一样,因为父类的指针可以用来指向子类对象或者父类对象,所以在子类中重写了的父类方法可以被调用,同样,父类中那个同名的函数也能被调用。因为在Python中,指针这个概念被弱化了,所以参数列表中的那个形参可以指任意对象,所以这里的多态,指参数传的是有继承关系的对象。
静态方法
定义方法:
使用@staticmethod
装饰器
异常
概念
- 程序在运行时,如果Python解释器遇到 到一个错误,会停止程序的执行,并且提示一些错误信息,这就是 异常
- 程序停止执行并且提示错误信息 这个动作,我们通常称之为:抛出(raise)异常
捕获异常
简单的捕获
- 在程序开发中,如果 对某些代码的执行不能确定是否正确,可以增加
try(尝试)
来 捕获异常 - 捕获异常最简单的语法格式:
try:
尝试执行的代码
except:
出现错误的处理
错误类型捕获
- 在程序执行时,可能会遇到 不同类型的异常,并且需要 针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型了
- 语法如下:
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except (错误类型2, 错误类型3):
# 针对错误类型2 和 3,对应的代码处理
pass
except Exception as result:
print("未知错误 %s" % result)
- 当Python解释器 抛出异常 时,最后一行错误信息的第一个单词,就是错误类型
捕获未知错误
- 在实际开发中,为了能够处理复杂的异常情况,完整的异常语法如下:
提示:
- 有关完整语法的应用场景,在后续学习中,结合实际的案例会更好理解
- 现在先对这个语法结构有个印象即可
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except 错误类型2:
# 针对错误类型2,对应的代码处理
pass
except (错误类型3, 错误类型4):
# 针对错误类型3 和 4,对应的代码处理
pass
except Exception as result:
# 打印错误信息
print(result)
else:
# 没有异常才会执行的代码
pass
finally:
# 无论是否有异常,都会执行的代码
print("无论是否有异常,都会执行的代码")
else
只有在没有异常时才会执行的代码finally
无论是否有异常,都会执行的代码
try:
num = int(input("请输入整数:"))
result = 8 / num
print(result)
except ValueError:
print("请输入正确的整数")
except ZeroDivisionError:
print("除 0 错误")
except Exception as result:
print("未知错误 %s" % result)
else:
print("正常执行")
finally:
print("执行完成,但是不保证正确")
异常的传递
- 异常的传递 —— 当 函数/方法 执行 出现异常,会 将异常传递 给 函数/方法 的 调用一方
- 如果 传递到主程序,仍然 没有异常处理,程序才会被终止
提示
- 在开发中,可以在主函数中增加 异常捕获
- 而在主函数中调用的其他函数,只要出现异常,都会传递到主函数的 异常捕获 中
- 这样就不需要在代码中,增加大量的 异常捕获,能够保证代码的整洁
抛出异常(raise)
Python中提供了一个Exception
异常类
抛出异常步骤
- 创建一个异常对象
- 使用raise关键字抛出异常对象
例如
def input_password():
# 1. 提示用户输入密码
pwd = input("请输入密码:")
# 2. 判断密码长度,如果长度 >= 8,返回用户输入的密码
if len(pwd) >= 8:
return pwd
# 3. 密码长度不够,需要抛出异常
# 1> 创建异常对象 - 使用异常的错误信息字符串作为参数
ex = Exception("密码长度不够")
# 2> 抛出异常对象
raise ex
try:
user_pwd = input_password()
print(user_pwd)
except Exception as result:
print("发现错误:%s" % result)
模块
概念
- 每一份源文件就是一个模块
- 模块名 同样也是一个 标识符,需要符合标识符的命名规则
- 在模块中定义的 全局变量 、函数、类 都是提供给外界直接使用的 工具
- 模块 就好比是 工具包,要想使用这个工具包中的工具,就需要先 导入 这个模块
导入模块方式
import导入
import 模块名1
如果模块的名字太长,可以使用
as
指定模块的名称,以方便在代码中的使用import 模块名1 as 模块别名
from...import导入
# 从 模块 导入 某一个工具 from 模块名1 import 工具名
注意
如果 两个模块,存在 同名的函数,那么 后导入模块的函数,会 覆盖掉先导入的函数
导入之后,不需要通过
模块名.
,可以直接使用模块提供的工具(全局变量,函数,类)
模块的搜索顺序:
- 搜索 当前目录 指定模块名的文件,如果有就直接导入
- 如果没有,再搜索 系统目录
注意:给文件起名,不要和系统的模块文件重名
Python中每一个模块都有一个内置属性
__file__
可以查看模块的完整路径
原则
- 一个独立的Python文件就是一个模块,在导入文件时,文件中所有没有任何缩进的代码都会被执行一遍。
- 所以如果我们需要测试代码,就需要使用
__name__
属性
__name__
是Python的一个内置属性,记录一个字符串
- 如果是被其他文件导入,这个属性就是模块名
- 如果是执行当前文件,
__name__
是__main__
所以在很多文件中就会看到以下格式的代码:
# 导入模块
# 定义全局变量
# 定义类
# 定义函数
# 在代码的最下方
def main():
# ...
pass
# 根据 __name__ 判断是否执行下方代码
if __name__ == "__main__":
main()