技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解



技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

最近有许多小伙伴问我要入门 Python 的资料 , 还有小伙伴完全没有入门 Python 就直接购买了我的 pandas 专栏 。 因此我决定写几篇 Python 数据处理分析必备的入门知识系列文章 , 以帮助有需要的小伙伴们更好入门 。
不拆分啥初级中级高级 , 一个专栏直接带你入门到高级应用 , 从数据处理到数据分析!!前言
关于 Python 中的类与对象相关知识 , 网络上已经有非常多的教程 。 但对于初学者来说 , 仍然是一个非常难以理解的事情 。 今天我尝试从一个奇怪的角度讲解使用类、对象相关知识 。 本文需要读者已经了解 Python 中关于 列表、字典、自定义函数基本认知物以类聚
每当我学习一个新的工具 , 都会自问:"为什么我需要它?"
假设我需要3位学生的相关数据(姓名、年龄、成绩) , 那么首先想到的可能是用列表表示 。
其中有2种方式 , 第一种如下:
技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

按属性归类 , 如上图 , 姓名单独一个列表
这显然是一种不合理的归类 , 因为需求往往是对一个学生做处理 。
例如 , 打印第2位学生的信息:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

总是要从多个列表中 , 取出某位置上的数据
如果需要定义统一的处理函数 , 那情况更加糟糕:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

任何处理学生的函数都需要传入3个数据列表
一种更好的归类方式是:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

每位学生一个列表
这解决了方式1的缺点 , 但是他仍然不完美 。 毕竟我们要记住姓名是在列表中的第一个位置上 。
这是因为数据结构不合理 , 我们不应该使用列表 。
那么 , 有什么结构能解决这痛点?
没错 , 就是字典:

【技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解】技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

此时字典中的 key 就是属性名字 , 对于的 value 就是值
现在任何处理函数直接传入某学生的信息字典即可:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

但是 , 这还是不够完美 , 想想现在的学生信息字典只是保存了数据 。
如果关于学生的操作也能保存在字典中 , 那么就完美了 。
还真可以!
我们可以把函数保存在字典中:
技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

注意字典中的 show_me 没有执行函数(因为没有在函数名字后写括号) , 只是保存了函数对象
那么当需要执行的时候 , 只需要:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

因为 s2['show_me'] 相当于取出了函数 show_me。 而执行函数需要函数对象后用括号 。
因此 s2['show_me'](s2) 相当于 show_me(s2)
最后 , 把创建学生信息字典的过程统一为一个函数:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

完美!
如果不使用类与对象 , 相信这已经是最好的结果
但此时还是有一个瑕疵 , 当需要输出某学生的信息时 , 需要传入自身给予 show_me 函数:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

这是在有点丑陋更进一步
我们暂且把以上方式称为"字典实现" 。
不管使用什么方式组织代码 , 我们的目的其实是为了更好围绕一个主题管理多个变量(例子中的学生即为主题 , 其中姓名、年龄、分数就是变量) 。
类就是一种管理的手段 , 看看如何定义:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

__init__ 函数是初始化时会执行的函数
现在我们不关注 self 实际是什么 , 但是要知道 self.name = name, 这类似往字典写入了数据
是不是很像之前我们定义的 create_st ?
那么 , 如何得到一个学生(类比字典实现方式中一个学生信息字典)?非常简单:
类名 + 括号, 这种操作称为"实例化" , 因为这会让我们得到一个实体(称之为"实例") , 变量 s1 指向了这个实体
此时变量 s1 指向的对象 , 与字典非常相似 , 只是他访问数据的方式更加简洁:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

对象变量 + 点 + 属性名字, 即可访问对应的数据 。 这类似于 字典对象[属性名字]
别以为我是随意使用字典来类别这些概念:
自定义类型的定义决定了实体的结构 。 比如 __init__ 中执行的代码决定了字典有哪些 key 和 value 。
实例化一个实例 , 相当于生成了一个带数据的字典
其实 , Python 对于实例对象的数据 , 真的用字典保存:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

实例(我们只能通过变量 s1 得到对应的实例) 方法 __dict__ 可以获得对象数据字典
现在 , 示例还缺了函数 show_me, 同样是在 "学生" 类中定义:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

行8-9:注意函数参数 self
行9:此时通过 self.name 获取对象数据字典的 name 对应的数据
行12:实例 + 点 + 函数名字 + 括号, 执行对应的函数
但是 , 为什么 show_me 函数中 , 有一个参数 , 但上面的调用却没有传入任何的东西?
对比一下"字典实现"方式中的定义:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

上方为自定义类中的函数 , 下方是"字典实现" 中的函数
注意其中的 self 参数 与之对应的参数 st
"字典实现"方式中 , 我们已经了解到 , 之所以需要参数 st, 是因为在 show_me 函数执行中 , 需要对应某位学生的信息(数据字典) 。
同理 , 学生类中定义的 show_me 函数的第一个参数 self, 实际就是调用时 , 要传入实例本身 。
这听起来像绕口令一样 , 如果我换一种方式执行 show_me 就很清晰:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

通过 类名 + 点 + 函数名字 + 括号 , 可以调用该函数
实际上 , 这才是调用时的真面目!
因此 , 如下2种方式的调用是一样的:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

前者(行3)只是后者(行5)的快捷方式
你是不是以为 , 这个函数 show_me 也像"字典实现"方式中那样 , 在字典中保存了这个函数呢?
如果你查看某些学生信息字典时 , 会发现并不是这样子:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

其实这想法已经很接近答案 , 因为这个函数不需要在每个学生信息字典中保存 , 只需要在类的信息字典中保存一份就可以:

技术编程|我是这样学会了Python中类与对象知识,网上没有看到的见解
本文插图

实际上 自定义类 St, 也是一个对象 , 因此他也有 __dict__ 等各种常规对象的函数 。 这超出本文主题 , 请参考其他相关文章总结类是模板 , 对象是按照模板生成的物体
这是很多教程使用的比喻方式 。
自定义类 , 决定了 每位学生的信息字典中需要哪些数据(姓名、年龄等)与操作(show_me) 。 这类似于一个模板 。
从自定义类中生成实例 , 相当于按模板构造出带实际数据的信息字典 。
可以看出来 , 每次构造出的学生实例 , 他们都是独立的信息字典 , 大家互不影响 , 各自为政 。
当然 , 类还具备很多面向对象的特性 , 能让我们创建更多通用工具 , 以后有机会再分享吧


    推荐阅读