• 首页

  • 分类&标签

  • 归档

  • 手册

  • 项目池

  • 友链

  • 关于
伯 乐 讲 堂
伯 乐 讲 堂

查看「系列思维导图」

侠客 · Mr.潘

获取中...

08
23
小Python 起步

第 8 节 小Python 的对象上

发表于 2020-08-23 • Python • 被 361 人看爆

如果说人生的某一刻会遇到瓶颈,那么在 小Python 的世界里,你也将遇到一个瓶颈期,那就是从 面向函数编程 转变为 面向对象编程。相信很多刚开始接触编程的小伙伴,对于什么是面向对象,什么是面向过程都是一脸懵逼的。

1. 对象为何物

1.1 从对象说开去

如果你还是单身狗大军中的一员,又到了谈婚论嫁之时,我相信你考虑的最多的问题,应该是 找对象 这件头等大事。如果你不是众多程序员中的一员,初看 对象 ,你可能会觉得这是再搞相亲大会呢。这么解读,也是未尝不可,只是我们这次是在给 小Python 找对象呢。

现实生活,人可以找对象,动物也可以找对象,植物也会有雄雌,再扩展出去,万物其实都能找对象,万物也都是对象了。

在 小Python 的世界里,它模拟了现实,也就需要有一种类似对象的东西来对应,干脆也叫对象吧。那如何模拟数不尽的对象呢,还是先分个类,然后从种类中具体出一个个对象,比较靠谱。即使是种类,现实世界的种类也是举不胜举,怎么办呢?这个时候我又想起老子的《道德经》有云“一生二,二生三,三生万物”,抓住本质的几个种类,再任由人类去扩展吧,所以 小Python 里也只是提供了部分的种类(类型),但你也能自由扩展(自定义类型),至于怎么个定义法,后文再续。

各位博客可以思考思考,是不是这么个道道呢。如果你作为编程语言的设计者,会怎么考虑呢?

这下好办了吧,我们截至目前也学了一些种类(数据类型)了,如:数值类型、布尔类型、序列类型、映射类型、集合类型,那么像 1024, 512, 3.14, True, ["apple", "banana"], {"name":"《小Python 之路》", "author":"Mr.潘"} 等等,这些就都是对象喽。

1.2 一切皆为对象

小Python 的官方定义为:

对象 是 Python 中对数据的抽象。Python 程序中的所有数据都是由对象或对象间关系来表示的。(从某种意义上说,按照冯·诺依曼的 “存储程序计算机” 模型,代码本身也是由对象来表示的。)

在 小Python 中,所有对象都有如下特点:

一个唯一的ID (ID是一个整型数字,通过id(x)获得)
一个类型 (通过type(x)获得)
数据内容
对象的ID不能修改。

对象的类型不能修改。

有些对象允许修改其内容(ID和类型永远不能被修改),这类对象称为可变对象(Mutable)。有些对象不允许修改其内容,这类对象称为不可变对象(Immutable)。

对象类型被一个类型对象(type object)所表示,该类型对象掌握更多该类型对象的信息,如对象占用了多少内存,对象拥有哪些方法。

1.3 type、object 和 class 的关系

int_a = 2019
string_b = "一切皆对象"
list_c = [1, 3, 5, 7, 9]
def function_d():
    pass

print(type(int_a))		# <class 'int'>, int_a 是由int这个类创建的实例
print(type(int))		# <class 'type'>,int 这个类是由 type 这个类创建的实例

print(type(string_b))		# <class 'str'>,string_b 这个类是由 type 这个类创建的实例
print(type(str))		# <class 'str'>,str 这个类是由 type 这个类创建的实例

print(type(list_c))		# <class 'list'>,同上
print(type(list))		# <class 'list'>,同上

print(type(function_d))		# <class 'function'>,同上

print(type(type))		# <class 'type'>,type 是由 type 类自身创建的实例

print(str.__bases__)		# (<class 'object'>,),类 str 的基类是 object 这个类
print(type.__bases__)		# (<class 'object'>,),类 type 的基类也是 object 这个基类
print(object.__bases__)		# (),类object没有基类

对于上面的代码,我们可以得出以下结论:

  1. 类type产生int实例,类int又有了 2019 这样的实例
  2. 类object是最顶层的基类
  3. type也是一个类,同时也是一个对象

想必有些道友,看到上面的代码,已经有点懵逼了。请看下图:

82.png

对于上面图片的解读如下:

  1. object 是一切对象:list、str、dict、tuple的基类,同时 object 是 type 的实例
  2. 类 type 是自身的实例,同时 type 也继承自 object 类
  3. 由结论1和结论2,得出一切皆对象,同时一切皆继承自 object 类

2. 编程方法论

2.1 望文生义

先抛出两个编程界跳不过去的 坎 —— 面向过程 与 面向对象。

面向过程(Procedure Oriented 简称PO):

面向过程 = 面向(Verb) + 过程(Noun) = 找(Verb) + 步骤(Noun)

从名字可以看出它是注重过程的。当解决一个问题的时候,面向过程会把事情拆分成: 一个个函数和数据。然后按照一定的顺序,执行完这些函数,等函数执行完了,事情就搞定了,杰出的代表语言:C。

面向对象(Object Oriented简称OO):

面向对象 = 面向(Verb) + 对象(Noun) = 找(Verb) + 对象(Noun)

看名字它是注重对象的。当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决,杰出的代表语言:C++,Java,Python。

2.2 源于生活

问题: 洗衣机里面放有脏衣服,怎么洗干净?

面向过程的解决方法:

  1. 执行加洗衣粉方法;
  2. 执行加水方法;
  3. 执行洗衣服方法;
  4. 执行清洗方法;
  5. 执行烘干方法;

以上就是将解决这个问题的过程拆成一个个方法(是没有对象去调用的),通过一个个方法的执行来解决问题。

面向对象的解决方法:

  1. 我先弄出两个对象:“洗衣机”对象和“人”对象
  2. 针对对象“洗衣机”加入一些属性和方法:“洗衣服方法”“清洗方法”、“烘干方法”
  3. 针对对象“人”加入属性和方法:“加洗衣粉方法”、“加水方法”
  4. 然后执行
    1. 人.加洗衣粉
    2. 人.加水
    3. 洗衣机.洗衣服
    4. 洗衣机.清洗
    5. 洗衣机.烘干

解决同一个问题 ,面向对象编程就是先抽象出对象,然后用对象执行方法的方式解决问题。

2.3 孰优孰劣

面向过程

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

缺点:没有面向对象易维护、易复用、易扩展。

面向对象

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护。

缺点:性能比面向过程低。

3. 归于编程

3.1 类 和 对象

通常为了便于我们去识别、记忆多个事物,我们首选的方案是应该根据相同特征、行为归归类,然后再对号入座,这样可能更加高效。正如“人是人他妈生的,妖是妖他妈生的”。下面先看个示例:

请将以下信息归类:李白、徐悲鸿、张大千、杜甫、陶渊明、齐白石。

诗人:李白、杜甫、陶渊明

画家:徐悲鸿、张大千、齐白石

我们归类的标准应该是:“李白、杜甫、陶渊明”都是会写诗的历史名人,“徐悲鸿、张大千、齐白石”都是会画画的历史名人。

所以我们可以用 小Python 的话术说“诗人”和“画家”就是“类”,“李白、杜甫、陶渊明”和“徐悲鸿、张大千、齐白石”就是“对象”(也叫 类的实例化 )。

专业解释:

对象:一个具体化事物,更多的称之为一个实例,如:李白、齐白石

类:一批具有相同属性和行为的对象的抽象表示,如:诗人、画家

3.2 小Python 造物

"""
    文件名:Poet.py
    用途:根据“李白、杜甫、陶渊明”几个人的共有特性,抽象出一个名词“诗人”
    作者:Mr.潘
"""

# class:定义 类 型关键字
# Poet:类 的名称,遵从标识符的命名规范,推荐使用 大驼峰命名法
class Poet:
    def __init__(self, name, dynasty, genre):
        """初始化实例对象的方法.
            self: 指向每一个实例的固有参数,通过其访问实例属性和对象方法
            name: 姓名
            dynasty: 朝代
            genre: 诗派
        """
        self.name = name            # 实例属性,将实参 name 赋值给实例的一个属性
        self.dynasty = dynasty
        self.genre = genre


# 类的实例化过程 --- 小Python 造人
libai = Poet("李白", "唐朝", "浪漫主义")		# 基于 诗人 创建了一个具体的对象 李白,自动执行 Poet 的 __init__() 方法
print(libai.name)		# 李白的姓名
print(libai.dynasty)		# 李白所属朝代
print(libai.genre)		# 李白的诗派

dufu = Poet("杜甫", "唐朝", "现实主义")
print(dufu.name)		# 杜甫的姓名
print(dufu.dynasty)		# 杜甫所属朝代
print(dufu.genre)		# 杜甫的诗派

3.3 为你写诗

"""
    文件名:write_poems_for_you.py
    用途:给诗人添加写诗能力,并拓展类的其它特性
    作者:Mr.潘
"""

class Poet:
    count = 0        # 类属性,记录基于该类创建的实例数量,类的一个属性,记录类的一个特性

    def __init__(self, name, dynasty, genre):
        """初始化实例对象的方法.
            self: 指向每一个实例的固有参数,通过其访问实例属性和对象方法
            name: 姓名
            dynasty: 朝代
            genre: 诗派
        """
        self.name = name
        self.dynasty = dynasty
        self.genre = genre
        Poet.count += 1             # 每执行一次该方法,就将 count + 1

    def description(self):
        """实例的一个自我介绍的方法.
        """
        print("大家好,我是{},是{}的一位{}诗人。".format(self.name, self.dynasty, self.genre))
  
    def write_poet(self, title, content):
        """实例的一个写诗的方法.
           title: 诗的主题
           content: 诗的内容
        """
        print("\t{}\t".format(title))
        for line in content.split("。"):
            print(line)

    @classmethod
    def show_count(cls):
        """类方法,针对于类定义的方法,需要 @classmethod 标识.
           cls: 由 哪一个类 调用的方法,方法内的 cls 就是哪一个类的引用
        """
        print("当前诗人的数量为{}".format(cls.count))

    @staticmethod
    def show_title():
        """静态方法,仅仅是为了封装在类中,不需要访问类信息,也不需要访问实例信息."""
        print("********************** 为你写诗 **********************")


# 类的实例化过程 --- 小Python 造人
Poet.show_title()        # 通过类名访问静态方法

libai = Poet("李白", "唐朝", "浪漫主义")
libai.description()        # 李白做自我介绍
libai.write_poet("静夜思", "床前明月光,疑是地上霜。举头望明月,低头思故乡。")   # 李白赋诗一首

dufu = Poet("杜甫", "唐朝", "现实主义")
dufu.description()         # 杜甫做自我介绍
dufu.write_poet("绝句", "两个黄鹂鸣翠柳,一行白鹭上青天。窗含西岭千秋雪,门泊东吴万里船。")    # 杜甫赋诗一首

Poet.show_count()         # 通过类名访问类方法
标题:第 8 节 小Python 的对象上
作者:侠客 · Mr.潘

读后有收获可以支付宝请作者喝咖啡,读后有疑问请加在下微信(pansfy)讨论:

第 9 节 小Python 的对象下
第 7 节 小Python 之函数
侠客 · Mr.潘

侠客 · Mr.潘

未来的你,会感谢今天仍正在奋斗的你

Github QQ Email RSS
看爆 Top10
  • 助力项目池 3,538次看爆
  • 第 4 节 yum 版的 LAMP 环境部署 2,535次看爆
  • 你的生产力工具集成就高效人士 1,880次看爆
  • 第 5 节 yum 版的 LNMP 环境部署 1,676次看爆
  • 第 3 节 企业级系统环境之上云篇 1,387次看爆
  • 服务端的架构的演进之路 1,285次看爆
  • 第 1 节 Docker 实践 1,191次看爆
  • 镜像仓库一文打尽 982次看爆
  • Docker本地私有镜像仓库Harbor搭建及配置 980次看爆
  • 第 6 节 源码版的LAMP环境部署 945次看爆

Copyright © 2023 侠客 · Mr.潘 · 苏ICP备19067937号

Proudly published with Halo · Theme by fyang · 站点地图