面向对象

提示:本文根据b站黑马python课整理

链接指引 => 2022新版黑马程序员python教程

一、初识对象

使用对象组织数据

在程序中是可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的。

  1. 在程序中设计表格,我们称之为:设计类(class)

    class Student:
     name = None
  2. 在程序中打印生产表格,我们称之为:创建对象

    # 基于类创建对象
    stu1 = Student()
    stu2 = Student()
  3. 在程序中填写表格,我们称之为:对象属性赋值

    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,另一个类对象
  • 返回值:TrueFalse
  • 内容:自行定义

>=符号实现的魔术方法是:__ge__
不过,实现了__le____ge__就没必要实现了

le

5.4 __eq__,比较运算符实现方法

不实现 __eq__方法,对象之间可以比较,但是是比较内存地址,也即是:不同对象==比较一定是False结果

实现了__eq__方法,就可以按照自己的想法来决定2个对象是否相等了。

  • 方法名:__eq__
  • 传入参数:other,另一个类对象
  • 返回值:TrueFalse
  • 内容:自行定义

eq

六、封装

面向对象的三大特性

  • 封装
  • 继承
  • 多态

封装表示的是,将现实世界事物的:

  • 属性
  • 行为

封装到类中,描述为:

  • 成员变量
  • 成员方法

对象

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)

七、继承

  1. 什么是继承?
    继承就是一个类,继承另外一个类的成员变量和成员方法
  2. 语法:

    • 子类构建的类对象,可以
    • 有自己的成员变量和成员方法
    • 使用父类的成员变量和成员方法
  3. 单继承和多继承
    单继承:一个类继承另一个类
    多继承:一个类继承多个类,按照顺序从左向右依次继承
    多继承中,如果父类有同名方法或属性,先继承的优先级高于后继承
  4. pass关键字的作用是什么
    pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思

7.1 继承的基础语法

7.1.1 单继承

class 类名(父类名):
    类内容体

继承分为:单继承和多继承
使用如图语法,可以完成类的单继承。
继承表示:将从父类那里继承(复制)来成员变量和成员方法(不含私有

单继承

7.1.2 多继承

一个类,可以继承多个父

class 类名(父类1,父类2,...., 父类n):
    类内容体
多继承注意事项:
    多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。
&nbsp;&nbsp;&nbsp;&nbsp;即:先继承的保留,后继承的被覆盖

多继承

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 变量的类型注解

  1. 为变量设置类型注解
    基础语法: 变量: 类型

zhijie

注意:
元组类型设置类型详细注解,需要将每一个元素都标记出来
字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value

zhijie2

  1. 除了使用 变量: 类型, 这种语法做注解外,也可以在注释中进行类型注解。
    语法:
    # type: 类型

zhujie3

8.2 函数(方法)的类型注解

函数和方法的形参类型注解语法:

def 函数方法名(形参名:类型,形参名:类型,.....):
    pass

zhujie44

同时,函数(方法)的返回值也是可以添加类型注解的。

语法如下:

def 函数方法名(形参名:类型,形参名:类型,.....) -> 返回值类型:
    pass
def read_file(x: int, y: int) -> list[int]:
    pass

8.3 Union类型

Union的使用方式:

  • 导包:from typing import Union
  • 使用: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向对象,之后会持续更新,欢迎大家点赞关注呀~~


玲小叮当
91 声望12 粉丝

一名前端人儿的笔记,欢迎来到这里,希望这里的文章对你有所帮助!