【python基础之面向对象介绍】--- 面向对象

发布时间 2024-01-04 15:21:07作者: Unfool
title:  【python基础之面向对象介绍】--- 面向对象
date:  2024-01-04  14:54:06 
updated: 2024-01-04 15:20:00
description:  python的面向对象介绍
cover: 
       https://home.cnblogs.com/u/dream-ze/
	   https://zhuanlan.zhihu.com/p/365265818

【一】面向对象导读/前言

用当前的知识点写一个有关人狗大战的小游戏

# 【一】角色信息
# 我们可以选一个角色 : 角色的名字,年龄,性别,攻击值,生命值
# 我们可以选一个角色 : 角色的名字,角色的类型,攻击值,生命值

# 【二】功能
# 功能 : 人打狗,狗肯定会疼,会掉血
# 功能 : 狗咬人,人肯定会疼,会掉血

# 【三】开发功能

# 【1】定义参数
dog_dict_one = {
    'dog_name': "旺财",
    'dog_type': "田园犬",
    'attack': 10,
    'health': 100
}

dog_dict_two = {
    'dog_name': "小獒",
    'dog_type': "藏獒",
    'attack': 20,
    'health': 100
}

person_dict = {
    'person_name': "lolo",
    'person_gender': "male",
    'person_age': 28,
    'attack': 30,
    'health': 100
}


# 【2】狗咬人 / 人打狗
# 定义成函数
def dog_attack_person(dog: dict, person: dict):
    '''
    :param dog: 狗
    :param person: 人
    :return:
    '''
    # 狗咬人 ---> 人会掉血
    person['health'] -= dog['attack']
    print(f'{dog["dog_name"]} 咬了 {person["person_name"]} 掉了 {dog["attack"]}血')


def person_attack_dog(dog: dict, person: dict):
    '''
    :param dog: 狗
    :param person: 人
    :return:
    '''
    # 狗咬人 ---> 人会掉血
    dog['attack'] -= person['health']
    print(f'{person["person_name"]} 打了 {dog["dog_name"]}  掉了 {dog["attack"]}血')


# 调用函数传递参数
dog_attack_person(dog=dog_dict_one, person=person_dict)
print(person_dict)
# 【三】开发功能

# 【1】定义参数
def create_dog(dog_name, dog_type, attack, health):
    dog_dict = {
        'dog_name': dog_name,
        'dog_type': dog_type,
        'attack': attack,
        'health': health
    }
    return dog_dict


def create_person(person_name, person_gender, person_age, attack, health):
    person_dict = {
        'person_name': person_name,
        'person_gender': person_gender,
        'person_age': person_age,
        'attack': attack,
        'health': health
    }
    return person_dict


# 【2】狗咬人 / 人打狗
# 定义成函数
def dog_attack_person(dog: dict, person: dict):
    '''
    :param dog: 狗
    :param person: 人
    :return:
    '''
    # 狗咬人 ---> 人会掉血
    person['health'] -= dog['attack']
    print(f'{dog["dog_name"]} 咬了 {person["person_name"]} 掉了 {dog["attack"]}血')


def person_attack_dog(dog: dict, person: dict):
    '''
    :param dog: 狗
    :param person: 人
    :return:
    '''
    # 狗咬人 ---> 人会掉血
    dog['attack'] -= person['health']
    print(f'{person["person_name"]} 打了 {dog["dog_name"]}  掉了 {dog["attack"]}血')


# 获取人和狗的参数
dog_dict_one = create_dog(dog_name="旺财", dog_type="田园犬", attack=10, health=100)
dog_dict_two = create_dog(dog_name="小獒", dog_type="藏獒", attack=20, health=100)
person_dict = create_person(person_name='lolo', person_gender='male', person_age=28, attack=30, health=100)
# 调用函数传递参数
dog_attack_person(dog=dog_dict_one, person=person_dict)
print(person_dict)

【二】面向过程与面向对象

# 【零】面条版
# 一条线穿到底
# 缺点:不容易维护和开发

# 【一】面向过程 (函数)
#    核心在于:过程
#    过程其实就是将程序流程化
#    可以说是一条流水线,分步骤的解决问题,先干什么再干什么,分的很清楚

# 【二】面向对象 (类)
#    面向对象核心在于对象二字
#    对象就是相当于一个整合体 ,把数据和功能整合到一起


# 比如我们有一个酒厂
# 面条班:这个酒厂每个厂子 生产出来酒。如果有人买酒,就从厂子里开始给人家送酒
# 函数版:我们得厂子,不是上面那样直接从生产线送出去了,而是酒厂里面会有一个仓库,如果有客户下单,就会从仓库里面拿东西送出去
# 对象版:我们变成了经销商模式,开分店,分店里面有自己的库存,酒,如果有客户买,直接从经销商手中买酒


# 先有学校还是先有学生?
#       先有学生,再有学校


# 学生:自己的名字,自己的年龄,自己的性别
# 比如一个学生可以上课、写作业、运动;
def student():
    def sport():
        ...

    student_dict = {
        'name': 'name',
        'sport': sport
    }
# 比如一个老师可以教课、批改作业;
# 比如一个运动员可以训练、参加比赛

# 学校 :
# 学校有名字
# 学校有地址

# 先有酒厂再有经销商
# 面向对象去写上述的学校的这个类
# 类:其实就是相当于我们的酒厂
# 对象:相当于我们的经销商,经销商有自己的位置,有自己的存酒

# 类即类别/种类,
# 是面向对象分析和设计的基石,如果多个对象有相似的数据与功能,那么该多个对象就属于同一种类。

# 经销商有自己的位置,有自己的酒,有自己的定价 -- 对象
# 他们都有共有的属性 : 位置,酒,定价 -- 类

# 学生 : 运动员,老师,上课学生 -- 对象
# 同属于一个学校,都有各自的名字,年龄,职责  -- 类

【三】类导读

  • 类即类别/种类,是面向对象分析和设计的基石,如果多个对象有相似的数据与功能,那么该多个对象就属于同一种类。
  • 有了类的好处是:
    • 我们可以把同一类对象相同的数据与功能存放到类里,而无需每个对象都重复存一份,这样每个对象里只需存自己独有的数据即可,极大地节省了空间。
  • 所以,如果说对象是用来存放数据与功能的容器,那么类则是用来存放多个对象相同的数据与功能的容器。

img

  • 综上所述,虽然我们是先介绍对象后介绍类,但是需要强调的是:
    • 在程序中,必须要事先定义类,然后再调用类产生对象(调用类拿到的返回值就是对象)。
    • 产生对象的类与对象之间存在关联,这种关联指的是:对象可以访问到类中共有的数据与功能
    • 所以类中的内容仍然是属于对象的,类只不过是一种节省空间、减少代码冗余的机制
  • 面向对象编程最终的核心仍然是去使用对象。

【四】什么是类

  • 类即类别、种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体
  • 所以,先有鸡和先有蛋的问题就出来了
    • 先有的一个个具体存在的对象(比如一个具体存在的人)
    • 还是先有的人类这个概念,这个问题需要分两种情况去看

(1)现实中

  • 在现实世界中:先有对象,再有类
  • 世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念
  • 也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在

(2)程序中

  • 在程序中:务必保证先定义类,后产生对象
  • 这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类
  • 不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象

【五】类的定义

# 我们有学校 ,我们有学生

# 学校有学校的属性
# 学生有学生的属性

# 可以有不同的学校 -- 对象
# 学校都有共同的属性 -- 学校名字,学校位置

# 学生有不同的角色,自己的名字,年龄,职业 -- 对象
# 学生都共有的属性 -- 角色名字,名字,年龄,职业 -- 对象
'''
# 学生类
    相同的特征:
        学校=实验一中
    相同的功能:
        读书
        写作
        跑步
'''

# def DreamStudent():
#     school = '实验一中'
#     def read():
#         print(f'可以读书')
#
#     def write():
#         print(f'可以写作')
#
#     def running():
#         print(f'可以跑步')
#     return {
#         'school':school,
#         'read':read,
#         'write':write,
#         'running':running,
#     }
# print(DreamStudent())
'''
# 定义类
class(关键字) 类名():
    # 定义参数
    # 定义函数
# 调用类 ---> 得有一个具体的对象才能调用类
'''


# 定义学生类
# class DreamStudent():
#     school = '实验一中'
#
#     def read(self):
#         print(f'可以读书')
#
#     def write(self):
#         print(f'可以写作')
#
#     def running(self):
#         print(f'可以跑步')



(1)类的创建语法格式:

class ClassName:
 '''变量'''
 '''方法'''
 pass

class 是关键字,表示类。例如 class Student 即创建了一个 Student 类。

(2)类的数据成员

数据成员包括:变量和方法。

(2.1)变量

类变量 :定义在类中且在函数体之外,在实例化对象中是公有的。

course_count = 4 # 类变量

实例变量:在类的内部,但是在类的其他成员方法之外声明,在实例化对象中是私有的。

def __init__(self, name, number):
 self.name = name # 实例变量
 self.number = number # 实例变量

本例是通过构造函数来声明,类变量和实例变量的区别很大,访问方式也也不一样。

(2.2)方法

类中定义的函数:

# 定义方法
def show(self):
    print(f'姓名: {self.name},学号: {self.number}')

初始化时的构造函数也是一种方法。

提示:

  • 在对象的方法里面都有一个self参数, 比如__init__(self), show(self)。 这里的self是指对象本身而非类本身。
  • 构造方法__init__(self,....):在生成对象时调用,可以用来进行一些初始化操作,不需要显示去调用,系统会默认去执行。构造方法支持重载,如果用户自己没有重新定义构造方法,系统就自动执行默认的构造方法。

(3) 私有/公有

类里面的私有属性和私有方法以双下划线__开头。私有属性或方法不能在类的外部被使用或直接访问,公有属性和公有方法可以在类的外部被使用或直接访问。

def __init__(self, name, number, score):
 self.name = name # 实例变量
 self.number = number # 实例变量
 self.__score = score # 私有变量

# 实例化
stu1 = Student('当打之年','001',90)
print(stu1.name) # 当打之年
print(stu1.__score) # AttributeError: 'Student' object has no attribute '__score'

【六】查看和修改类的属性/调用

  • 方式一
# 定义学生类
# class DreamStudent():
#     school = '实验一中'
#
#     def read(self):
#         print(f'可以读书')
#
#     def write(self):
#         print(f'可以写作')
#
#     def running(self):
#         print(f'可以跑步')


# 调用:先实例化类得到一个对象
# stu1 = DreamStudent()
# stu2 = DreamStudent()


# print(stu1) # <__main__.DreamStudent object at 0x000001EB964A2CD0>
# dir 方法查看对象具有的功能
# print(dir(stu1))
# print(stu1.school)
# print(stu1.__dict__)
# stu1.__dict__['name'] = 'dream'
# stu1.__dict__['age'] = 18
# stu1.__dict__['gender'] = 'male'
# print(stu1.__dict__)
# print(stu1.name)
# print(stu1.school)
  • 方式二
class DreamStudent():
    school = '实验一中'

    def read(self):
        print(f'可以读书')

    def write(self):
        print(f'可以写作')

    def running(self):
        print(f'可以跑步')

def init(obj, name, age, gender):
    # 【三】向对象中修改对象的独有属性
    obj.__dict__['name'] = name
    obj.__dict__['age'] = age
    obj.__dict__['gender'] = gender

# 【一】先调用类实例化得到一个对象
stu1 = DreamStudent()
stu2 = DreamStudent()
# 【二】调用初始化对象的方法,得到独有的对象属性
init(obj=stu1, name='dream', age=18, gender='male')
init(obj=stu2, name='hope', age=28, gender='female')

print(stu1.__dict__)
print(stu2.__dict__)
  • 方式三
# class DreamStudent():
#     school = '实验一中'
#
#     def read(self):
#         print(f'可以读书')
#
#     def write(self):
#         print(f'可以写作')
#
#     def running(self):
#         print(f'可以跑步')
#
#     def set_info(self, name, age, gender):
#         # self 就是当前类实例化出来的对象
#         # 【三】向对象中修改对象的独有属性
#         self.__dict__['name'] = name
#         self.__dict__['age'] = age
#         self.__dict__['gender'] = gender
#
#
# # 【一】先调用类实例化得到一个对象
# stu1 = DreamStudent()
# stu2 = DreamStudent()
# # print(stu1.__dict__)
# # print(dir(stu1))
# # 【二】调用初始化对象的方法,得到独有的对象属性
# # 对象调用类的方法时,会将对象本身作为参数 self 传进去
# stu1.set_info(name='dream', age=18, gender='male')
# stu2.set_info(name='hope', age=28, gender='female')
#
# print(stu1.__dict__)
# print(stu2.__dict__)
  • 方式四
# class DreamStudent():
#     school = '实验一中'
#
#     # 魔法方法 --- init 初始化方法
#     def __init__(self, name, age, gender):
#         # self 就是当前类实例化出来的对象
#         # 【三】向对象中修改对象的独有属性
#         self.name = name
#         self.age = age
#         self.gender = gender
#
#     def read(self,sex):
#         # print(self,dir(self))
#         # print(self.name)
#         print(f' {sex}可以读书')
#
#     def write(self):
#         print(f'可以写作')
#
#     def running(self):
#         print(f'可以跑步')
#
#
# # 【一】先调用类实例化得到一个对象
# # 和我们的调用函数很像  返回值可以是任意类型 = 函数名(参数名=参数值)
# # 返回值是一个类的对象  = 类名(参数名=参数值)
# stu1 = DreamStudent(name='dream', age=18, gender='male')
# stu2 = DreamStudent(name='hope', age=28, gender='female')
# # print(stu1.__dict__)
# # print(dir(stu1))
# # 【二】调用初始化对象的方法,得到独有的对象属性
# # 对象调用类的方法时,会将对象本身作为参数 self 传进去
# # print(dir(stu1))
# stu1.read(sex='男')