面对对象初识

【一】人狗大战小游戏引入

【1】游戏规则分析

  • 人可以打狗,狗掉血,狗可以咬人,人掉血

  • 人的属性

    • 姓名

    • 类型

    • 年龄

    • 攻击力

    • 生命值

  • 狗的属性

    • 姓名

    • 类型

    • 年龄

    • 攻击力

    • 生命值

【二】封装成函数,减少代码冗余

def get_person(name, gender, age, t_type, attack_val, life_val):
    # 将人的攻击动作放在产生人的函数内
    def person_attack(person_obj, dog_obj):
        """
        :param person_obj: 接收一个人
        :param dog_obj: 接收一条狗
        """
        print('当前狗的血量是:%s' % dog_obj.get('life_val'))
        dog_obj['life_val'] -= person_obj.get('attack_val')
        print("""人:%s 锤了狗:%s 一下 狗掉血:%s 剩余血量:%s""" % (
            person_obj.get('name'), dog_obj.get('name'), person_obj.get('attack_val'), dog_obj['life_val']))
​
    data_dict = {
        'name': name,
        'gender': gender,
        'age': age,
        't_type': t_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'person_attack': person_attack
    }
    return data_dict
​
​
def get_dog(name, t_type, attack_val, life_val):
    def dog_attack(dog_obj, person_obj):
        """
        :param dog_obj: 接收一条狗
        :param person_obj: 接收一个人
        """
        # 使用最简答的掉血逻辑  血量减去对方攻击力
        print('当前人的血量是:%s' % person_obj.get('life_val'))
        person_obj['life_val'] -= dog_obj.get('attack_val')
        print("""狗:%s 咬了人:%s 一口 人掉血:%s 剩余血量:%s""" % (
            dog_obj.get('name'), person_obj.get('name'), dog_obj.get('attack_val'), person_obj['life_val']))
​
    data_dict = {
        'name': name,
        't_type': t_type,
        'attack_val': attack_val,
        'life_val': life_val,
        'dog_attack': dog_attack
    }
    return data_dict
​
​
p1 = get_person('knight', 'male', 22, '猛男', 50, 1000)
p2 = get_person('ddt', 'female', 24, '淑女', 10, 100)
dog1 = get_dog('小黑', '松狮犬', 30, 500)
dog2 = get_dog('小白', '泰迪犬', 10, 200)
p1['person_attack'](p1, dog1)
dog1['dog_attack'](dog1, p2)

(二)什么是面对对象

【1】面向对象理解

  • 面向对象就相当于上帝,在上帝的视角,人是对象,动物是对象,石头是对象,水是对象,山是对象.....存在的可以扩充,不存在的可以创造。

【2】面向对象的优缺点

(1)面对对象的优点
  • 解决程序的延展性

  • 对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

(2)面向对象的缺点
  • 编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题。

    • 一些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的shell脚本就不适合用面向对象去设计,面向过程反而更加适合。

  • 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法准确地预测最终结果。

    • 于是我们经常看到对战类游戏,新增一个游戏人物,在对战的过程中极容易出现阴霸的技能,一刀砍死3个人,这种情况是无法准确预知的,只有对象之间交互才能准确地知道最终的结果。

【3】什么是程序

  • 程序=数据+功能

  • 编写程序的本质就是定义一系列的数据,然后写出一些功能对数据进行操作

【三】类与对象

【1】什么是类

  • 类即类别、种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体

  • 所以,先有鸡和先有蛋的问题就出来了

    • 先有的一个个具体存在的对象(比如一个具体存在的人)

    • 还是先有的人类这个概念,这个问题需要分两种情况去看

(1)现实中
  • 在现实世界中:先有对象,再有类

  • 世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念

  • 也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在

(2)程序中
  • 在程序中:务必保证先定义类,后产生对象

  • 这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类

  • 不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象

【四】面对对象编程

  • 关键字 class 声明一个类

  • 在类程序中,特征用变量名标识,功能用函数标识

  • 因而在类中 函数名和变量名

【1】定义类

(1)类名 建议是驼峰体,例如:Student
  • 方式一:class Student(object)

  • 方式二:class Student()

  • 方式三:class Student

class Student(object):
    # 类名后面的()参数不写的话默认就是object
    # object:父类
    # 直接定义数据属性
    school_name = "清华"
    
    
    # 函数属性
    def read(self):
        age = 18
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
        
​
# 通过实例化得到一个对象
student = Student()
print(student)      # <__main__.Student object at 0x000001399554FFD0>
# 想用类里面的属性和方法
print(student.school_name)
print(student.read())

【2】类的调用

(1)实例化类,得到对象
student_one = Student()
student_two = Student()
​
# 每一次得到的对象都是新的
print(id(student_one))
# 2274496937888
print(id(student_two))
# 2274496937696
(2)如何修改对象的属性
# 【1】通过类的名称空间修改属性
# 类的名称空间不允许修改属性
space_class = Student.__dict__
print(space_class, type(space_class))  # <class 'mappingproxy'>
​
# 这两种方式都可以获取
print(space_class['school_name'])
print(space_class.get('school_name'))
​
​
# 【2】修改对象的属性
class Student(object):
    # 数据属性
    school_name = '清华'
​
    # 函数属性
    def read(self):
        age = 18
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
​
​
student = Student()
student_one= Student()
# 添加一个student字典,赋给obj_space
obj_space = student.__dict__
# 添加一个键为name,值为knight的键值对
obj_space['name'] = 'knight'
print(obj_space,type(obj_space))    # {'name': 'knight'} <class 'dict'>
print(obj_space['name'])        # knight
​
# 输出里面定义过的学校名
print(student.school_name)      # 清华
# 输出添加后的name值
print(student.name)             # knight
# student_one是复制的student
print(student_one.school_name)  # 清华
​
​
# 【3】批量修改属性
class Student(object):
    # 数据属性
    school_name = '清华'
​
    # 函数属性
    def read(self):
        age = 18
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
​
​
student_one = Student()
student_two = Student()
# 方式一:通过名称空间字典替换
student_one.__dict__['name'] = 'knight'
# 方式二:通过  对象.属性名=属性值替换
# (1)逐个添加
student_one.name = 'knight'
student_one.age = 18
student_one.gender = 'male'
student_two.name = 'opp'
student_two.age = 19
student_two.gender = 'female'
print(student_one.name)     # knight
print(student_one.age)      # 18
print(student_one.gender)   # male
# (2)批量向对象中添加各自独有的属性值和属性名
def init_obj(obj,name,age,gender):
    obj.name = name
    obj.age = age
    obj.gender = gender
student_one = Student()
student_two = Student()
init_obj(obj=student_one,name='knight',age=18,gender='male')
print(student_one.name)
(3)在类内部初始化自己的参数
class Student(object):
    # 数据属性
    school_name = '清华'
​
    def init_obj(self, name, age, gender):  # 这个self就是类的对象本身
        self.name = name
        self.age = age
        self.gender = gender
​
    # 函数属性
    def read(self):
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
        print(f"当前姓名是{self.name}")
        print(f"当前年龄是{self.age}")
        print(f"当前性别是{self.gender}")
student = Student()
# 给值,初始化
student.init_obj(name='knight',age=20,gender='male')
student.read()
(4)魔法方法值初始化方法 __init__
class Student(object):
    # 数据属性
    school_name = '清华'
​
    def __init__(self, name, age, gend  er):  # 这个self就是类的对象本身
        self.name = name
        self.age = age
        self.gender = gender
​
    # 函数属性
    def read(self):
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
        print(f"当前姓名是{self.name}")
        print(f"当前年龄是{self.age}")
        print(f"当前性别是{self.gender}")
​
​
# 给值,初始化
student = Student(name='knight',age=20,gender='male')
student.read()
# 需要再添加学生的信息
student_one = Student(name='hyt',age=22,gender='female')
student_one.read()
# 查看类的名称空间
print(student.__dict__) # {'name': 'knight', 'age': 20, 'gender': 'male'}
(5)属性查找顺序
class Student(object):
    # 数据属性
    school_name = '清华'
​
    def __init__(self, name, age, gender):  # 这个self就是类的对象本身
        self.name = name
        self.age = age
        self.gender = gender
​
    # 函数属性
    def read(self):
        # self:表示对象自己本身
        print(f"当前学校是{self.school_name}")
        print(f"当前姓名是{self.name}")
        print(f"当前年龄是{self.age}")
        print(f"当前性别是{self.gender}")
​
​
# 给值,初始化
student = Student(name='knight',age=20,gender='male')
print(student.name)
# 可以通过.覆盖原来的值
student.name = 'hyt'    # student.__dict__['name'] = 'hyt'
print(student.name)
​
# 属性查找顺序
print(student.name)
print(student.school_name)
# 查找顺序
# 首先在自己的对象中查找
# 自己找不到就去父类里面找
# 父类没找到就去基类中找
# 如果基类里面也没有,就去object中找
# 否则报错
(6)列表特性回顾
num_one_list = [1, 2, 3, 4]
num_two_list = [5, 6, 7, 8]
num_one_list.append(9)
# 每一个列表都是一个单独的对象
print(num_one_list)
print(num_two_list)
​
​
class Student:
    def __init__(self, name):
        self.name = name
​
​
s1 = Student(name='knight')
print(id(s1))
s1.name = 'hyt'
print(id(s1))

【3】类的属性扩展

class Duck(Animal,object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
​
    def speak(self):
        print(f"这是一一只鸭子叫{self.name}已经{self.age}岁了")
​
​
duck = Duck(name='tang', age=1)
# 属性介绍
# 【1】获取当前类的名字
print(Duck.__name__)
# 【2】获取类中文档字符串(只能获取三引号中的)
print(Duck.__doc__)
# 【3】获取类的父类
print(Duck.__base__)    # <class '__main__.Animal'>
# 【4】获取类的所有父类
print(Duck.__bases__)   # (<class '__main__.Animal'>, <class 'object'>)
# 【5】获取当前类的名称空间(字典)
print(Duck.__dict__)
# 【6】获取类定义所在的模块名
print(Duck.__module__)  # __main__
# 【7】实例化得到对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/596085.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

创新指南|非凡时代的变革型领导力——五个领导力差异化优势将使高管能够重塑他们的组织

大多数商界领袖现在都明白&#xff0c;我们正在经历一场“伟大的重构”&#xff0c;整个行业、经济和社会都在重塑的时期。然而&#xff0c;考虑到他们面临的短期压力&#xff0c;很少有高管发现自己能够真正应对这些变化&#xff0c;这些变化对他们的组织所需的转型意味着什么…

【Mac】 DSync for mac(文件比较同步工具) v2.7安装教程

软件介绍 DSync是一款文件比较同步工具&#xff0c;通过简便的三步即可完成繁琐的比较、同步操作&#xff0c;您甚至可以通过跳过、删除或反转您选择的文件的复制方向来微调您的同步。这是在Mac上同步文件的最简单方法。 安装教程 1.打开安装包&#xff0c;将「DSync」拖到右…

Merck:mPAGE® Lux SDS-PAGE制胶系统

相对于传统SDS-PAGE制胶工艺&#xff0c;Merck公司的mPAGE Lux制胶系统是一种更快速、简单、安全的替代方法&#xff0c;可实现更具可重现性的结果。mPAGE Lux制胶系统可在90秒内完成小型凝胶固化&#xff0c;而传统方法则需要90分钟以上。该系统采用紫外线照射快速制胶工作流程…

打破 AI 算力天花板,Meta超大规模AI基础设施架构解读

Meta超大规模AI智算基础设施架构设计 摘要 双重 GPU 集群&#xff0c;每群配备 2.4 万个 H100 芯片&#xff0c;分别采用 RoCE 和 InfiniBand 网络连接。LLaMA3 就是在这两个集群上训练出来的&#xff1b;Meta AI 将部署庞大算力集群&#xff0c;拥有 35 万张 H100 GPU&#x…

【字符串】Leetcode 43. 字符串相乘

题目讲解 43. 字符串相乘 算法讲解 class Solution { public:void AddZero(string& temp, int cnt) {while (cnt--) {temp 0;} }string Add(string num1, string num2) {string result;int carry 0;int i num1.size() - 1;int j num2.size() - 1;while (i > 0 ||…

Python学习笔记------处理数据和生成折线图

给定数据&#xff1a; jsonp_1629344292311_69436({"status":0,"msg":"success","data":[{"name":"美国","trend":{"updateDate":["2.22","2.23","2.24",&qu…

select,poll,epoll

在 Linux Socket 服务器短编程时&#xff0c;为了处理大量客户的连接请求&#xff0c;需要使用非阻塞I/O和复用&#xff0c;select&#xff0c;poll 和 epoll 是 Linux API 提供的I/O复用方式。 \selectpollepoll操作方式遍历遍历回调底层实现数组链表哈希表IO效率每次调用都进…

Vue-router使用(配置路径、路由跳转、相关API、多级路由、路由守卫,两种工作模式)

Vue-router使用(配置路径、路由跳转、相关API、多级路由、路由守卫&#xff0c;两种工作模式) 目录 Vue-router使用(配置路径、路由跳转、相关API、多级路由、路由守卫&#xff0c;两种工作模式)安装配置路径路由跳转不携带参数跳转携带参数跳转?形式携带参数地址中直接携带参…

如何设置ddns动态域名服务实现外网访问

在本地搭建好服务器&#xff0c;部署好web网站或其他应用后&#xff0c;需要在外网访问内网时&#xff0c;如何设置动态域名服务ddns&#xff0c;将主机的内网IP端口映射到外网访问&#xff0c;是我们需要面对的一个重要步骤。 内网发布外网&#xff0c;常见的有两种方案&…

KAN:Kolmogorov–Arnold Networks

KAN: Kolmogorov–Arnold Networks 论文链接&#xff1a;https://arxiv.org/abs/2404.19756 代码链接&#xff1a;https://github.com/KindXiaoming/pykan 项目链接&#xff1a;https://kindxiaoming.github.io/pykan/intro.html Abstract 受Kolmogorov-Arnold表示定理的启…

FX95GT FX505GT windows 11 触摸板安装

FX95GT FX505GT windows 11 触摸板驱动安装 如果正常使用 exe 文件安装不上&#xff0c;请在 ‘设置’ 》 ‘系统信息 ’》 驱动下载地址 如果正常使用 exe 文件安装不上&#xff0c;请在 ‘设置’ 》 ‘系统信息 ’》 高级系统设置 设备管理 在电脑上点右键&#xff0c;选择…

光端机(2)——光纤通信学习笔记九

学习笔记里面只关注基本原理和概念&#xff0c;复杂的公式和推导都没有涉及 光端机 光发射机 作用&#xff1a;实现电光转换。将来自电端机的电信号对光源发出的光波进行调制&#xff0c;然后将调制好的光信号耦合到光线中传输。 基本性能要求 1.合适的发光波长&#xff08;光…

SCI一区 | WOA-BiTCN-BiGRU-Attention多输入单输出回归预测(Matlab)

SCI一区 | WOA-BiTCN-BiGRU-Attention多输入单输出回归预测&#xff08;Matlab&#xff09; 目录 SCI一区 | WOA-BiTCN-BiGRU-Attention多输入单输出回归预测&#xff08;Matlab&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现WOA-BiTCN-BiGRU-A…

Transformer - 编码器和解码器中的QKV分别来自哪

Transformer - 编码器和解码器中的QKV分别来自哪 flyfish Transformer - 注意⼒机制 Scaled Dot-Product Attention 计算过程 Transformer - 注意⼒机制 代码实现 Transformer - 注意⼒机制 Scaled Dot-Product Attention不同的代码比较 Transformer - 注意⼒机制 代码解释 Tr…

论文架构介绍

论文架构 背景&#xff1a;建议2段左右完成&#xff0c;字数控制在500左右为佳&#xff0c;对应子题目1过渡段&#xff1a;写150字左右的过渡段&#xff0c;承上启下&#xff0c;回答部分子题目2、3的要求正文实践部分&#xff1a;一般3-7个论点&#xff0c;根据题目的要求来看…

电机控制器电路板布局布线参考指导(七)电流检测模块布局布线

电机控制器电路板布局布线参考指导&#xff08;七&#xff09;电流检测模块布局布线 1.高侧电流检测2.低侧电流监测3.两相和三相电流检测4.关键元器件选型要求5.布局6.布线7.工具设置8.输入和输出滤波9.注意事项 很多电机驱动器产品系列包括内置了电流感测功能的器件&#xff0…

【3D基础】坐标转换——地理坐标投影到平面

汤国安GIS原理第二章重点 1.常见投影方式 https://download.csdn.net/blog/column/9283203/83387473 Web Mercator投影&#xff08;Web Mercator Projection&#xff09;&#xff1a; 优点&#xff1a; 在 Web 地图中广泛使用&#xff0c;易于显示并与在线地图服务集成。在较…

设计模式Java实现-工厂模式

✨这里是第七人格的博客✨小七&#xff0c;欢迎您的到来~✨ &#x1f345;系列专栏&#xff1a;设计模式&#x1f345; ✈️本篇内容: 工厂模式✈️ &#x1f371;本篇收录完整代码地址&#xff1a;https://gitee.com/diqirenge/design-pattern &#x1f371; 楔子 记得刚…

详解xml-java语言

1.XML在线学习手册 XML 教程 2.XML可以做什么 1.给两个程序之间进行数据通信。现在用的最多的是JSON。 2.给服务器做配置文件。 3.存储复杂的数据关系。 4.还可以充当小型的数据库。 3.书写格式 <?xml version"1.0" encoding"UTF-8" ?> <…

一键安装Halo DB

说明 这里说的一键其实分了好几步&#xff0c;是我将安装步骤分解。你可以把它们放在一个shell中或者串起来就是一键了。 易景科技的数据库 羲和 &#xff08;Halo DB&#xff09; 我之前的一位朋友&#xff08;章晨曦&#xff09;创立的数据库公司。以前看他朋友圈说他做数…
最新文章