{ "cells": [ { "cell_type": "markdown", "id": "d9cb6bfb", "metadata": {}, "source": [ "# 继承与复用" ] }, { "attachments": {}, "cell_type": "markdown", "id": "231a0b83", "metadata": {}, "source": [ "在自定义类型的基本形式中:\n", "\n", "```python\n", "class ClassName(ParentClass):\n", " \"\"\"class docstring\"\"\"\n", " def some_method(self, ...):\n", " return ...\n", "```\n", "\n", "ParentClass是用来进行继承的,被继承的ParentClass是父类,定义的ClassName是子类。可以认为子类是一种特殊的父类。\n", "\n", "例如,假设父类是哺乳动物,人作为一个子类可以继承这个父类,因为人是哺乳动物的一种;狮子也可以继承哺乳动物,因为狮子也是哺乳动物的一种。" ] }, { "attachments": {}, "cell_type": "markdown", "id": "4610fc79", "metadata": {}, "source": [ "## 类的继承" ] }, { "cell_type": "markdown", "id": "635c7cab", "metadata": {}, "source": [ "考虑这样一个表示树叶的类:" ] }, { "cell_type": "code", "execution_count": 1, "id": "a36e7da9", "metadata": {}, "outputs": [], "source": [ "class Leaf(object):\n", " def __init__(self, color='green'):\n", " self.color = color\n", "\n", " def fall(self, season=\"autumn\"):\n", " print(f\"A leaf falls in {season}!\")" ] }, { "cell_type": "markdown", "id": "b3a7c490", "metadata": {}, "source": [ "继承这个类,生成一个枫树叶类:" ] }, { "cell_type": "code", "execution_count": 2, "id": "8fd3dae4", "metadata": {}, "outputs": [], "source": [ "class MapleLeaf(Leaf):\n", " def change_color(self):\n", " if self.color == \"green\":\n", " self.color = \"red\"" ] }, { "cell_type": "markdown", "id": "013464f5", "metadata": {}, "source": [ "构造一个子类对象:" ] }, { "cell_type": "code", "execution_count": 3, "id": "c2ce6df7", "metadata": {}, "outputs": [], "source": [ "mleaf = MapleLeaf()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "9c71f8cb", "metadata": {}, "source": [ "子类会继承父类的属性和方法,父类的属性和方法可以直接调用:" ] }, { "cell_type": "code", "execution_count": 4, "id": "29d73263", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A leaf falls in autumn!\n" ] } ], "source": [ "mleaf.fall()" ] }, { "cell_type": "code", "execution_count": 5, "id": "426c68dd", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'green'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mleaf.color" ] }, { "cell_type": "markdown", "id": "c33456b6", "metadata": {}, "source": [ "子类虽然没有定义构造函数,但是会直接继承父类的构造函数:" ] }, { "cell_type": "code", "execution_count": 6, "id": "c2b42098", "metadata": {}, "outputs": [], "source": [ "mleaf2 = MapleLeaf(\"orange\")" ] }, { "cell_type": "code", "execution_count": 7, "id": "e40ef349", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'orange'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mleaf2.color" ] }, { "cell_type": "markdown", "id": "ec403e0f", "metadata": {}, "source": [ "子类额外定义的方法:" ] }, { "cell_type": "code", "execution_count": 8, "id": "2d213cb8", "metadata": {}, "outputs": [], "source": [ "mleaf.change_color()" ] }, { "cell_type": "code", "execution_count": 9, "id": "3bb2fa10", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'red'" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mleaf.color" ] }, { "cell_type": "markdown", "id": "44289e50", "metadata": {}, "source": [ "## 方法的重载" ] }, { "cell_type": "markdown", "id": "2ee37ba6", "metadata": {}, "source": [ "子类可以对父类中已有的方法进行重载。例如,在枫树叶类中对`.fall()`方法进行重载,即重新定义:" ] }, { "cell_type": "code", "execution_count": 10, "id": "9686c9a2", "metadata": {}, "outputs": [], "source": [ "class MapleLeaf(Leaf):\n", " def change_color(self):\n", " if self.color == \"green\":\n", " self.color = \"red\"\n", " \n", " def fall(self, season=\"autumn\"):\n", " self.change_color()\n", " print(f\"A leaf falls in {season}!\")" ] }, { "cell_type": "markdown", "id": "927dded2", "metadata": {}, "source": [ "在这个例子中,`.fall()`方法被重载,并调用了自定义类中的已有方法。方法定义中的第一个参数`self`表示的就是对象自身,所以可以用`self.change_color()`实现对已有方法的调用:" ] }, { "cell_type": "code", "execution_count": 11, "id": "7061f8cb", "metadata": {}, "outputs": [], "source": [ "mleaf = MapleLeaf()" ] }, { "cell_type": "code", "execution_count": 12, "id": "364a7a02", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'green'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mleaf.color" ] }, { "cell_type": "code", "execution_count": 13, "id": "153090d1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A leaf falls in autumn!\n" ] } ], "source": [ "mleaf.fall()" ] }, { "cell_type": "code", "execution_count": 14, "id": "865ab7c1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'red'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mleaf.color" ] }, { "cell_type": "markdown", "id": "d9fe2191", "metadata": {}, "source": [ "## super()函数" ] }, { "attachments": {}, "cell_type": "markdown", "id": "12781a14", "metadata": {}, "source": [ "与父类的.fall()方法相比,子类的方法只增加了.change_color()的调用,之后的操作与父类的.fall()方法一致,代码其实有冗余和浪费。Python提供了`super()`函数,在子类中调用父类的方法。具体定义如下:" ] }, { "cell_type": "code", "execution_count": 15, "id": "b99f05d4", "metadata": {}, "outputs": [], "source": [ "class MapleLeaf(Leaf):\n", " def change_color(self):\n", " if self.color == \"green\":\n", " self.color = \"red\"\n", " \n", " def fall(self, season=\"autumn\"):\n", " self.change_color()\n", " super(MapleLeaf, self).fall(season)\n", " # print(f\"A leaf falls in {season}!\")" ] }, { "cell_type": "markdown", "id": "13439014", "metadata": {}, "source": [ "能实现与上面一样的结果:" ] }, { "cell_type": "code", "execution_count": 16, "id": "131799e9", "metadata": {}, "outputs": [], "source": [ "mleaf = MapleLeaf()" ] }, { "cell_type": "code", "execution_count": 17, "id": "ed6d7d2a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'green'" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mleaf.color" ] }, { "cell_type": "code", "execution_count": 18, "id": "aed3c77a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A leaf falls in autumn!\n" ] } ], "source": [ "mleaf.fall()" ] }, { "cell_type": "code", "execution_count": 19, "id": "45fe2072", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'red'" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mleaf.color" ] }, { "attachments": {}, "cell_type": "markdown", "id": "a6be393a", "metadata": {}, "source": [ "## 鸭子类型:一切都是为了复用\n", "\n", "鸭子类型(Duck Type)的概念来源于美国诗人詹姆斯·惠特科姆·莱利的诗句:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”在Python中,这个概念被衍生为:在使用对象时,可以不关注对象的类型,而关注对象具有的方法或属性;只要对象的属性和方法满足条件,就认为该对象是合法的。\n", "\n", "例如,定义这样的一个函数:" ] }, { "cell_type": "code", "execution_count": 20, "id": "bb2de45c", "metadata": {}, "outputs": [], "source": [ "def something_fall(leaf):\n", " leaf.fall()" ] }, { "cell_type": "markdown", "id": "d1e0ef0c", "metadata": {}, "source": [ "这个函数接受一个参数leaf,并调用它的.fall()方法。Leaf类支持.fall()方法,因此该类型的对象是合法的:" ] }, { "cell_type": "code", "execution_count": 21, "id": "f22b737c", "metadata": {}, "outputs": [], "source": [ "leaf = Leaf()" ] }, { "cell_type": "code", "execution_count": 22, "id": "e097ca26", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A leaf falls in autumn!\n" ] } ], "source": [ "something_fall(leaf)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "2ec867a8", "metadata": {}, "source": [ "子类MapleLeaf也支持.fall()方法,所以也是合法的对象:" ] }, { "cell_type": "code", "execution_count": 23, "id": "1ac9d7aa", "metadata": {}, "outputs": [], "source": [ "mleaf = MapleLeaf()" ] }, { "cell_type": "code", "execution_count": 24, "id": "6603faac", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A leaf falls in autumn!\n" ] } ], "source": [ "something_fall(mleaf)" ] }, { "cell_type": "markdown", "id": "c1e85d42", "metadata": {}, "source": [ "再定义一个类苹果:" ] }, { "cell_type": "code", "execution_count": 25, "id": "0e90ed20", "metadata": {}, "outputs": [], "source": [ "class Apple(object):\n", " def fall(self):\n", " print(\"An apple falls!\")" ] }, { "cell_type": "code", "execution_count": 26, "id": "62d3a582", "metadata": {}, "outputs": [], "source": [ "apple = Apple()" ] }, { "cell_type": "code", "execution_count": 27, "id": "f61690f0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "An apple falls!\n" ] } ], "source": [ "something_fall(apple)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "244ac641", "metadata": {}, "source": [ "在鸭子类型机制下,Python将函数和方法中的类型检查,变成了接口检查的模式,即something_fall()函数不会检查传入的参数leaf是什么类型,而是检查leaf有没有实现.fall()接口。" ] }, { "cell_type": "code", "execution_count": null, "id": "69b6fbe9", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.10" } }, "nbformat": 4, "nbformat_minor": 5 }