面向对象
提醒:本文依据 b 站黑马 python 课整顿
链接指引 => 2022 新版黑马程序员 python 教程
一、初识对象
应用对象组织数据
在程序中是能够做到和生存中那样,设计表格、生产表格、填写表格的组织模式的。
-
在程序中
设计表格
,咱们称之为:设计类(class)
class Student: name = None
-
在程序中
打印生产表格
,咱们称之为:创建对象
# 基于类创建对象 stu1 = Student() stu2 = Student()
-
在程序中
填写表格
,咱们称之为:对象属性赋值
stu1.name = '111' stu2.name = '111'
二、成员办法
2.1 类的定义和应用
类的应用语法:
- class 是关键字,示意要定义类了
- 类的属性,即定义在类中的变量(成员变量)
- 类的行为,即定义在类中的函数(成员办法)
class 类名称:
类的属性
类的行为
创立类对象的语法:
对象 = 类名称()
2.2 成员变量和成员办法
类中定义的属性(变量),咱们称之为:成员变量
类中定义的行为(函数),咱们称之为:成员办法
2.2.1 成员办法的定义语法
def 办法名(self, 行参 1, ..., 行参 n):
办法体
能够看到,在办法定义的参数列表中,有一个:self
关键字
self 关键字是成员办法定义的时候, 必须填写
的。
- 它用来示意类对象本身的意思
- 当咱们应用类对象调用办法的是,self 会主动被 python 传入
在办法外部,想要拜访类的成员变量,必须应用 self
def say_hi(self):
print(f"hi 大家好,我是{self.name}")
注意事项:self 关键字,只管在参数列表中,然而传参的时候能够疏忽它。
三、类和对象
基于类创建对象的语法: 对象名 = 类名称()
四、构造方法
Python 类能够应用:__init__()
办法,称之为构造方法。
能够实现:
- 在创立类对象(结构类)的时候,
会主动执行。
- 在创立类对象(结构类)的时候,
将传入参数主动传递给__init__办法应用。
在构造方法内定义成员变量,须要应用
self
关键字
class Student:
def __init__(self, name, age, address):
self.name = name
self.age = age
self.address = address
stu = Student('天天', 30, '1111')
案例:
学生信息录入
# 学生信息录入
class Student:
id = None
name = None
age = None
address = None
def insert (self, id, name, age, address):
self.id = id
self.name = name
self.age = age
self.address = address
print(f'学生 {id} 信息录入实现,信息为:【学生姓名:{name},年龄:{age},地址:{address}】')
idx = 10
for i in range(0, idx):
print(f'以后录入第 {i+1} 位学生信息,总共需录入 10 位学生信息')
name = input('请输出学生姓名:')
age = input('请输出学生年龄:')
address = input('请输出学生地址:')
stu = Student()
stu.insert(i+1, name, age, address)
if i+1 == 10:
print('10 位学生信息录入结束!')
五、其它内置办法(魔术办法)
上文学习的__init__ 构造方法,是 Python 类内置的办法之一。
这些内置的类办法,各自有各自非凡的性能,这些内置办法咱们称之为:魔术办法
办法 | 性能 |
---|---|
__init__ |
构造方法,可用于创立类对象的时候设置初始化行为 |
__str__ |
用于实现类对象转字符串的行为 |
__lt__ |
用于 2 个类对象进行小于或大于比拟 |
__le__ |
用于 2 个类对象进行小于等于或大于等于比拟 |
__eq__ |
用于 2 个类对象进行相等比拟 |
5.1 __str__
字符串办法
内存地址没有多大作用,咱们能够通过 __str__
办法,管制类转换为字符串的行为。
- 办法名:
__str__
- 返回值:字符串
- 内容:自行定义
class Record:
def __init__(self, date,order_id,money,province):
self.date = date # 订单日期
self.order_id = order_id # 订单 ID
self.money = money # 订单金额
self.province = province # 销售省份
def __str__(self):
return f"{self.date}, {self.order_id}, {self.money}, {self.province}"
5.2 __lt__
小于符号比拟办法 (__gt__
大于符号比拟办法)
间接对 2 个对象进行比拟是不能够的,然而在类中实现 __lt__
办法,即可同时实现:小于符号 和 大于符号 2 种比拟 比拟大于符号的魔术办法是:__gt__
不过,实现了 __lt__
,__gt__
就没必要实现了
- 办法名:
__lt__
- 传入参数:other,另一个类对象
- 返回值:True 或 False
- 内容:自行定义
5.3 __le__
小于等于比拟符号办法
魔术办法:__le__
可用于:<=、>= 两种比拟运算符上。
- 办法名:
__le__
- 传入参数:
other
,另一个类对象- 返回值:
True
或False
- 内容:自行定义
>=
符号实现的魔术办法是:__ge__
不过,实现了 __le__
,__ge__
就没必要实现了
5.4 __eq__
,比拟运算符实现办法
不实现 __eq__
办法,对象之间能够比拟,然而是比拟内存地址,也即是:不同对象 == 比拟肯定是 False 后果
。
实现了 __eq__
办法,就能够依照本人的想法来决定 2 个对象是否相等了。
- 办法名:
__eq__
- 传入参数:
other
,另一个类对象- 返回值:
True
或False
- 内容:自行定义
六、封装
面向对象的三大个性
- 封装
- 继承
- 多态
封装示意的是,将事实世界事物的:
- 属性
- 行为
封装到类中,形容为:
- 成员变量
- 成员办法
6.1 公有成员
既然事实事物有不公开的属性和行为,那么作为事实事物在程序中映射的类,也应该反对。
类中提供了公有成员的模式来反对。
- 公有成员变量
- 公有成员办法
定义公有成员的形式非常简单,只须要:
- 公有成员变量:变量名以__结尾(2 个下划线)
- 公有成员办法:办法名以__结尾(2 个下划线)
即可实现公有成员的设置
class Phone:
__is_5g_enable = False # 公有成员变量
def __check_5g(self): # 公有成员办法
print('5g 开启')
练习:
设计带有公有成员的手机
# 设计带有公有成员的手机
import random
class Phone:
__is_5g_enable = False
def __check_5g(self):
if self.__is_5g_enable:
print('5g 开启')
else:
print('5g 敞开,应用 4g 网络')
def call_by_5g(self):
self.__check_5g()
print('正在通话中...')
phone: Phone = Phone()
phone.call_by_5g()
a = random.randint(1,2)
七、继承
- 什么是继承?
继承就是一个类,继承另外一个类的成员变量和成员办法 -
语法:
- 子类构建的类对象,能够
- 有本人的成员变量和成员办法
- 应用父类的成员变量和成员办法
- 单继承和多继承
单继承:一个类继承另一个类
多继承:一个类继承多个类,依照程序从左向右顺次继承
多继承中,如果父类有同名办法或属性,先继承的优先级高于后继承 pass 关键字
的作用是什么pass
是占位语句,用来保障函数(办法)或类定义的完整性,示意无内容,空的意思
7.1 继承的根底语法
7.1.1 单继承
class 类名(父类名):
类内容体
继承分为:单继承和多继承
应用如图语法,能够实现类的单继承。
继承示意:将从父类那里继承(复制)来成员变量和成员办法(不含公有
7.1.2 多继承
一个类,能够继承多个父
class 类名(父类 1,父类 2,...., 父类 n):
类内容体
多继承注意事项:
多个父类中,如果有同名的成员,那么默认以继承程序(从左到右)为优先级。
即:先继承的保留,后继承的被笼罩
7.2 复写和应用父类成员
7.2.1 复写
复写:子类继承父类的成员属性和成员办法后,如果对其“不称心”,那么能够进行复写。
即:在子类中从新定义同名的属性或办法即可。
class FileReader:
def read_file(self):
"""读取文件的数据,读到的每一条数据都转换为 Record 对象,将他们封装到 list"""
pass
# 文本文件的读取
class TextFileRead(FileReader):
def __init__(self, path):
self.path = path # 定义文件门路
# 复写父类的办法
def read_file(self):
print('11111')
7.2.2 调用父类同名成员
一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员
如果须要应用被复写的父类的成员,须要非凡的调用形式:
形式 1:
- 调用父类成员
- 应用成员变量:
父类名. 成员变量
- 应用成员办法:
父类名. 成员办法(self)
形式 2:
- 应用
super()
调用父类成员 - 应用成员变量:
super(). 成员变量
- 应用成员办法:
super(). 成员办法()
只能在子类内调用父类的同名成员。
子类的类对象间接调用会调用子类复写的成员
八、类型注解
8.1 变量的类型注解
- 为变量设置类型注解
根底语法:变量: 类型
留神:
元组类型设置类型具体注解,须要将每一个元素都标记进去
字典类型设置类型具体注解,须要 2 个类型,第一个是 key 第二个是 value
- 除了应用 变量: 类型,这种语法做注解外,也能够在正文中进行类型注解。
语法:# type: 类型
8.2 函数(办法)的类型注解
函数和办法的形参类型注解语法:
def 函数办法名(形参名:类型,形参名:类型,.....):
pass
同时,函数(办法)的返回值也是能够增加类型注解的。
语法如下:
def 函数办法名(形参名:类型,形参名:类型,.....) -> 返回值类型:
pass
def read_file(x: int, y: int) -> list[int]:
pass
8.3 Union 类型
Union 的应用形式:
- 导包:from typing import Union
- 应用:Union[类型, ……, 类型]
九、多态
多态,指的是:多种状态,即实现某个行为时,应用不同的对象会失去不同的状态。
9.1 抽象类(接口)
这种设计的含意是:
- 父类用来确定有哪些办法
- 具体的办法实现,由子类自行决定
抽象类:含有形象办法的类称之为抽象类
形象办法:办法体是空实现的(pass)称之为形象办法
抽象类的作用
- 多用于做顶层设计(设计标准),以便子类做具体实现。
- 也是对子类的一种软性束缚,要求子类必须复写(实现)父类的一些办法
- 并配合多态应用,取得不同的工作状态。
十、案例
数据分析案例
main.py
"""面向对象,数据案例剖析"""
from pyecharts.charts import Line, Bar
from pyecharts.options import *
from pyecharts.globals import ThemeType
from file_define import TextFileRead, JsonFileReader, FileReader
from data_define import Record
text_file_reader = TextFileRead('./data/2011 年 1 月销售数据.txt')
json_file_reader = JsonFileReader('./data/2011 年 2 月销售数据 JSON.txt')
jan_data: list[Record] = text_file_reader.read_file()
feb_data: list[Record] = json_file_reader.read_file()
# 将两个月份的数据合并为一个 list
all_data: list[Record] = jan_data + feb_data
# 数据计算
data_dict = {}
for record in all_data:
if record.date in data_dict.keys():
# 以后日期有记录,做累加
data_dict[record.date] += record.money
else:
data_dict[record.date] = record.money
# print(data_dict)
# 可视化图表开发
bar = Bar(init_opts=InitOpts(theme=ThemeType.LIGHT))
bar.add_xaxis(list(data_dict.keys()))
bar.add_yaxis('销售额', list(data_dict.values()), label_opts=LabelOpts(is_show=False))
bar.set_global_opts(title_opts=TitleOpts(title='每日销售额')
)
bar.render('每日销售额 echarts.html')
file_defined.py
"""和文件相干的类定义"""
import json
from data_define import Record
class FileReader:
def read_file(self) -> list[Record]:
"""读取文件的数据,读到的每一条数据都转换为 Record 对象,将他们封装到 list"""
pass
# 文本文件的读取
class TextFileRead(FileReader):
def __init__(self, path):
self.path = path # 定义文件门路
# 复写父类的办法
def read_file(self) -> list[Record]:
f = open(self.path, 'r', encoding="UTF-8")
record_list: list[Record] = []
for line in f.readlines():
line = line.strip() # 打消空格和换行
data_list = line.split(',')
record = Record(data_list[0], data_list[1], int(data_list[2]), data_list[3])
record_list.append(record)
# print(record_list)
f.close()
return record_list
# Json 文件的读取
class JsonFileReader(FileReader):
def __init__(self, path):
self.path = path # 定义文件门路
def read_file(self) -> list[Record]:
f = open(self.path, 'r', encoding="UTF-8")
record_list: list[Record] = []
for line in f.readlines():
data_dict = json.loads(line)
record = Record(data_dict['date'], data_dict['order_id'], int(data_dict['money']), data_dict['province'])
record_list.append(record)
f.close()
return record_list
if __name__ == "__main__" :
text_file = TextFileRead('./data/2011 年 1 月销售数据.txt')
text_json = JsonFileReader('./data/2011 年 2 月销售数据 JSON.txt')
list1 = text_file.read_file()
list2 = text_json.read_file()
for l in list1:
print(l)
for l in list2:
print(l)
data_defined.py
"""数据定义的类"""
class Record:
def __init__(self, date,order_id,money,province):
self.date = date # 订单日期
self.order_id = order_id # 订单 ID
self.money = money # 订单金额
self.province = province # 销售省份
def __str__(self):
return f"{self.date}, {self.order_id}, {self.money}, {self.province}"
总结
以上就是 python 向对象,之后会继续更新,欢送大家点赞关注呀~~