一、面向对象
-
思想:当需要实现一个功能的时候,看重的并不是过程和步骤,而是关心谁帮我做这件事(偷懒,找人帮我做),面向对象是关注结果的,通过调用来实现某件事
-
三大特性:
- 封装性:
- 将属性和方法放到一起做为一个整体,然后通过实例化对象来处理;
- 隐藏内部实现细节,只需要和对象及其属性和方法交互就可以了;
- 对类的属性和方法增加 访问权限控制。
- 继承性:子类能够调用父类的属性和方法
- 多态性:调用父类方法时可以使用子类对象,增加了功能,提高了延展性
- 封装性:
二、类和对象
- 类:抽象的,模拟现实事物。(通过两个方面:属性和行为)
- 类的构成:类名、属性、方法
- 对象:具体的某个事物,可以由类创建。
1.类的定义和创建对象
- 一个类可以创建多个对象
class 类名(object):
方法列表
对象名1 = 类名()
对象名2 = 类名()
2.添加和获取属性
1)类外
对象名.属性名 = 属性值
2)类内获取属性
- 在类的实例方法中,通过self获取该对象的属性
- 其中,self指代当前调用方法的实例对象
def info(self):
print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
print("英雄 %s 的攻击力 :%d" % (self.name, self.atk))
print("英雄 %s 的护甲值 :%d" % (self.name, self.armor))
三、魔法方法
1.__init__
方法
- 当实例化对象被创建时,会自动调用该方法,用来做变量的初始化或赋值
- 默认参数self指对象本身,其他参数需要在创建时传参
class Student(object):
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel
stu = Student(1, 2, 3)
2.__str__
方法
- 使用print打印对象的时候,默认打印的是对象的地址,当使用
__str__
方法后,打印的是这个方法中return的值 - 注:必须有返回值且为字符串
def __str__(self):
return f"{self.name}"
print(stu)
3.__del__
方法
- 当对象的引用计数为0时,自动调用该方法
- 当有变量保存一个对象的引用时,引用计数加1;当删除一个指向该对象的变量时,该对象的引用计数减1;当引用计数为0时才真正被删除(内存回收)
def __del__(self):
print(f"{self.name}被删除")
del(stu)
四、继承
- 在程序中,继承描述的是多个类之间的所属关系。
- 如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。
- 那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。
1.单继承
- 一个子类继承一个父类的属性和方法
- ()中为父类名
class Prentice(Master):
pass
2.多继承
- 一个子类继承多个父类
- 如果在父类中存在同名的属性或方法,则默认使用第一个父类的属性或方法
- 使用
__mro__
属性来查看类的继承顺序
class Prentice(Master1, Master2):
pass
3.子类重写父类同名属性和方法
-
在子类中定义与父类同名的属性或方法就是对其的重写
-
当子类中存在与父类同名的属性或方法,默认使用子类的
4.子类调用父类同名属性和方法
1)使用属性初始化的方法
- 调用父类方法格式:
父类类名.父类方法(self)
- 执行本类的同名方法,要做属性初始化:
self.__init__()
class Master(object):
def __init__(self):
self.kongfu = "古法煎饼果子配方" # 实例变量,属性
def make_cake(self): # 实例方法,方法
print("[古法] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
class School(object):
def __init__(self):
self.kongfu = "现代煎饼果子配方"
def make_cake(self):
print("[现代] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
class Prentice(School, Master): # 多继承,继承了多个父类
def __init__(self):
self.kongfu = "猫氏煎饼果子配方"
def make_cake(self):
self.__init__() # 执行本类的__init__方法,做属性初始化 self.kongfu = "猫氏...."
print("[猫氏] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
# 调用父类方法格式:父类类名.父类方法(self)
def make_old_cake(self):
# 可以通过执行Master类的__init__方法,来修改self的属性值
Master.__init__(self) # 调用了父类Master的__init__方法 self.kongfu = "古法...."
Master.make_cake(self) # 调用父类Master的实例方法
def make_new_cake(self):
# 可以通过执行School类的__init__方法,来修改self的属性值
School.__init__(self) # 调用了父类School的__init__方法 self.kongfu = "现代...."
School.make_cake(self) # 调用父类School的实例方法
2)使用super()
方法调用父类属性和方法
- 可以逐一调用所有的父类方法,并且只执行一次
- 同名方法只执行一次,目前super()不支持执行多个父类的同名方法
class Master(object):
def __init__(self):
self.kongfu = "古法煎饼果子配方" # 实例变量,属性
def make_cake(self): # 实例方法,方法
print("[古法] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
class School(object):
def __init__(self):
self.kongfu = "现代煎饼果子配方"
def make_cake(self):
print("[现代] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
super().__init__() # 执行父类的构造方法
super().make_cake() # 执行父类的实例方法
class Prentice(School, Master): # 多继承,继承了多个父类
def __init__(self):
self.kongfu = "猫氏煎饼果子配方"
def make_cake(self):
self.__init__() # 执行本类的__init__方法,做属性初始化 self.kongfu = "猫氏...."
print("[猫氏] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
def make_all_cake(self):
super().__init__() # 执行父类的 __init__方法
super().make_cake() # 执行父类的 实例方法
self.make_cake() # 执行本类的实例方法
五、私有属性及私有方法
- 私有权限:在属性或方法名前面加两个下划线
__
-
类的 私有属性 和 私有方法 ,只能在类中访问,而不能被实例对象直接访问
-
类的 私有属性 和 私有方法,子类无法继承,也无法访问
-
私有权限是用来处理类内事物的,不能通过对象出来,起到安全作用
-
修改私有属性
- 私有属性无法通过对象修改,只能通过类中定义公有方法来修改私有属性的方式
class Person(object):
def __init__(self):
self.__name = 'lzq'
def set_name(self, name):
self.__name = name
lzq = Person()
lzq.set_name('liangzhiqiang')
六、多态
- 子类继承父类
- 子类重写父类中的方法
- 通过对象调用方法
# 定义父类
class Father:
def cure(self):
print("父亲给病人治病...")
# 定义子类继承父类
class Son(Father):
# 重写父类中的方法
def cure(self):
print("儿子给病人治病...")
# 定义函数,在里面 调用 医生的cure函数
def call_cure(doctor):
# 调用医生治病的方法
doctor.cure()
# 创建父类对象
father = Father()
# 调用函数,把父类对象传递函数
call_cure(father)
# 创建子类对象
son = Son()
# 调用函数,把子类对象传递函数
call_cure(son)
- 通过传入不同的对象,函数都执行了cure()方法,对于其他子类同理
- 可以使函数变得更灵活,额外增加了它的功能,提高了函数的扩展性
七、类属性及类方法
1.类属性
- 类属性直接定义在类中的属性,定义在
__init__
中的属性为实例属性 - 类属性可以被类对象、实例对象访问
class People(object):
name = 'Tom' # 公有的类属性
__age = 12 # 私有的类属性
p = People()
print(p.name) # 正确
print(People.name) # 正确
print(p.__age) # 错误,不能在类外通过实例对象访问私有的类属性
print(People.__age) # 错误,不能在类外通过类对象访问私有的类属性
2.类方法
-
以**
@classmethod
装饰**的方法被称为类方法 -
类方法可以通过类对象和实例对象访问
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def get_country(cls):
return cls.country
p = People()
print(p.get_country()) #可以用过实例对象引用
print(People.get_country()) #可以通过类对象引用
- 通过类方法修改类属性
@classmethod
def set_country(cls,country):
cls.country = country
八、静态方法
-
以**
@staticmethod
装饰**的方法 -
静态方法不用多定义参数
-
可以通过类对象和实例对象来访问
class People(object):
country = 'china'
@staticmethod
"""静态方法"""
def get_country():
return People.country
p = People()
# 通过对象访问静态方法
print(p.get_country())
# 通过类访问静态方法
print(People.get_country())
九、异常
1.异常的定义
try:
print('可能发生错误的代码')
except Exception as e:
print('发生异常执行的代码')
else:
print('没有发生异常执行的代码')
finally:
print('无论是否产生异常都至少执行一次')
2.异常的传递
- 异常嵌套
try:
可能异常的代码
try:
可能异常的代码
except:
pass
finally:
pass
except:
pass
- 实现步骤
1、尝试打开只读文件(第一个异常捕获)
2、循环读取内容(while True)
3、内容的读取方式,一行一行的读(readlines)
4、循环需要终止,终止条件break(读取的内容为空)
5、读的过程中也有可能出现异常(第二个异常捕获) - 核心思想
先执行第一个try里的代码,如果没有异常。再去执行第二个try中的代码 - 使用时机
在一个代码块中,一部分代码异常直接会影响到另一部分的代码,需要分别进行异常捕获。
3.自定义异常
- 自定义异常类
- 抛出异常
- 捕获该异常
# 1. 自定义异常类, 继承Exception, 魔法方法有init和str(设置异常描述信息)
class ShortInputError(Exception):
def __init__(self, length, min_len):
# 用户输入的密码长度
self.length = length
# 系统要求的最少长度
self.min_len = min_len
# 设置异常描述信息
def __str__(self):
return f'您输入的密码长度是{self.length}, 密码不能少于{self.min_len}'
def main():
# 2. 抛出异常: 尝试执行:用户输入密码,如果长度小于3,抛出异常
try:
password = input('请输入密码:')
if len(password) < 3:
# 抛出异常类创建的对象
raise ShortInputError(len(password), 3)
# 3. 捕获该异常
except Exception as result:
print(result)
else:
print('没有异常,密码输入完成')
main()
十、模块
1.自定义模块
- 模块名.py
2.概念
一个python文件。能够定义函数,模块能够包含类,函数和变量,也能包含可执行的代码。
3.作用
减少代码冗余
降低代码的耦合度
4.引用
- 导入:import 模块名
引用:模块名.函数名() - 导入:from 模块名 import 功能1,功能2,…
引用:功能() - 导入:from 模块名 import ** 该模块导入所有功能**
- as:起别名
- 模块起别名:import 模块名 as 别名
- 函数起别名:from 模块名 import 函数名 as 别名
注:起别名后无法使用原名
5.制作模块
定义模块:1、创建一个py文件
2、测试: if name == “main” :
测试代码
调用自己定义的模块
6.模块的定位顺序
1、当前目录
2、python path
3、/usr/local/lib/python unix
注:1、自己的文件不能和已有模块名字重复,如果重复会导致已有模块无法使用
2、当使用【from 模块名 import 功能】调用时,如果功能名重复,后面的会覆盖前面的功能,导入的是后面的功能。
7.__all__
列表
- 当模块中存在**
__all__
列表时,【from 模块名 import 】的导入方法只能导入__all__
列表中的功能*
8.导包
-
包的创建
- 将所有有联系的模块组织在一起,放在同一个文件夹中,同时在文件夹中有一个**【
__init__.py
】文件**,这个文件控制包的导入行为
- 将所有有联系的模块组织在一起,放在同一个文件夹中,同时在文件夹中有一个**【
-
导入:import 包名.模块名
调用:包名.模块名.功能( ) -
导入:from 包名 import ***
调用:模块名.功能( )
注意:必须在【__init__.py
】文件中添加__all__
列表**,控制允许导入的模块列表,否则无法正常导入。