跟老齐学Python之编写类之三子类


Posted in Python onOctober 11, 2014

关于类,看官想必已经有了感觉,看下面的代码,请仔细阅读,并看看是否能够发现点什么问题呢?

#!/usr/bin/env python

#coding:utf-8
class Person:

    def __init__(self, name, lang, email):

        self.name = name

        self.lang = lang

        self.email = email
    def author(self):

        return self.name
class Programmer:

    def __init__(self, name, lang, email, system, website):

        self.name = name

        self.lang = lang

        self.email = email

        self.system = system

        self.website = website
    def pythoner(self):

        pythoner_list = [ self.name, self.lang, self.email, self.system, self.website ]

        return pythoner_list
if __name__=="__main__":

    writer = Person("qiwsir","Chinese","qiwsir@gmail.com")

    python = Programmer("qiwsir","Python","qiwsir@gmail.com","Ubutun","qiwsir.github.io")

    print "My name is:%s"%writer.author()

    print "I write program by:%s"%python.pythoner()[1]

 上面这段代码,运行起来没有什么问题,但是,仔细看,发现有两个类,一个名字叫做Person,另外一个叫做Programmer,这还不是问题所在,问题所在是这两个类的构造函数中,存在这相同的地方:self.name=name,self.lang=lang,self.email=email,这对于追求代码质量的程序员,一般是不允许的。最好不要有重复代码或者冗余代码。可是,在两个类中都要有这些参数,应该怎么办呢?

子类、父类和继承

看下面的代码,里面有两个类A,B。这段程序能够正确运行,每个类的功能是仅仅打印指定的内容。

#!/usr/bin/env python

#coding:utf-8
class A:

    def __init__(self):

        print "aaa"
class B:

    def __init__(self):

        print "bbb"
if __name__=="__main__":

    a = A()

    b = B()
#运行结果

aaa

bbb

 上面的两个类彼此之间没有所谓的父子关系。现在稍加改变,将类B改写,注意观察与上面的差异。

#!/usr/bin/env python

#coding:utf-8
class A:

    def __init__(self):

        print "aaa"
class B(A):         #这里和上面程序不同。B继承了A

    def __init__(self):

        print "bbb"
if __name__=="__main__":

    a = A()

    b = B()
#运行结果

aaa

bbb

 这段程序中,类B跟前面的那段有一点不同,class B(A):,这样写就表明了B相对A的关系:B是A的子类,B从A继承A的所有东西(子承父业)。

但是,看官发现了没有,运行结果一样。是的,那是以为在B中尽管继承了A,但是没有调用任何A的东西,就好比儿子从老爸那里继承了财富,但是儿子一个子也没动,外界看到的和没有继承一样。

#!/usr/bin/env python

#coding:utf-8
class A:

    def __init__(self):

        print "aaa"
class B(A):

    def __init__(self):

        #print "bbb"

        A.__init__(self)    #运行继承的父类
if __name__=="__main__":

    a = A()

    b = B()
#运行结果

aaa

aaa

 这回运行结果有了变化,本来b=B()是运行类B,但是B继承了A,并且在初始化的构造函数中,引入A的构造函数,所以,就运行A的结果相应结果了。

下面把最开头的那端程序用子类继承的方式重写,可以是这样的:

#!/usr/bin/env python

#coding:utf-8
class Person:

    def __init__(self, name, lang, email):

        self.name = name

        self.lang = lang

        self.email = email
    def author(self):

        return self.name

"""

class Programmer:

    def __init__(self, name, lang, email, system, website):

        self.name = name

        self.lang = lang

        self.email = email

        self.system = system

        self.website = website
    def pythoner(self):

        pythoner_list = [ self.name, self.lang, self.email, self.system, self.website ]

        return pythoner_list

"""
class Programmer(Person):       #继承父类Person

    def __init__(self, name, lang, email, system, website):

        Person.__init__(self,name,lang,email)   #将Person.__init__()的功能继承到这里

        #self.name = name                       #这三句是Person中已经搞定的,就不用重复

        #self.lang = lang                       #通过继承已经实现了这三句的功能

        #self.email = email

        self.system = system                    #子类中不同于Person父类部分

        self.website = website
    def pythoner(self):

        pythoner_list = [ self.name, self.lang, self.email, self.system, self.website ]

        return pythoner_list
if __name__=="__main__":

    writer = Person("qiwsir","Chinese","qiwsir@gmail.com")

    python = Programmer("qiwsir","Python","qiwsir@gmail.com","Ubutun","qiwsir.github.io")

    print "My name is:%s"%writer.author()

    print "I write program by:%s"%python.pythoner()[1]

 代码运行结果与前面一样。

列位是否理解了子类和父类、继承的特点。如果你有一个老爹,是一个高官或者富豪,那么你就官二代或者富二代了,你就从他们那里继承了很多财富,所以生活就不用太劳累了。这就是继承的作用。在代码中,也类似,继承能够让写代码的少劳累一些。

对于为什么要用继承,好友@令狐虫 大侠给了以非常精彩的解释:

从技术上说,OOP里,继承最主要的用途是实现多 态。对于多态而言,重要的是接口继承性,属性和行为是否存在继承性,这是不一定的。事实上,大量工程实践表明,重度的行为继承会导致系统过度复杂和臃肿, 反而会降低灵活性。因此现在比较提倡的是基于接口的轻度继承理念。这种模型里因为父类(接口类)完全没有代码,因此根本谈不上什么代码复用了。
在Python里,因为存在Duck Type,接口定义的重要性大大的降低,继承的作用也进一步的被削弱了。

另外,从逻辑上说,继承的目的也不是为了复用代码,而是为了理顺关系。
 
我表示完全赞同上述解释。不过看官如果不理解,也没有关系,上述解释中的精神,的确需要在编程实践中感悟才能领会到的。
Python 相关文章推荐
Python中的__SLOTS__属性使用示例
Feb 18 Python
Python打印斐波拉契数列实例
Jul 07 Python
Python实现的维尼吉亚密码算法示例
Apr 12 Python
Python爬虫将爬取的图片写入world文档的方法
Nov 07 Python
Python从文件中读取数据的方法讲解
Feb 14 Python
浅析Python3中的对象垃圾收集机制
Jun 06 Python
python之yield和Generator深入解析
Sep 18 Python
Python API自动化框架总结
Nov 12 Python
python matplotlib:plt.scatter() 大小和颜色参数详解
Apr 14 Python
使用OpenCV对车道进行实时检测的实现示例代码
Jun 19 Python
pycharm远程连接服务器并配置python interpreter的方法
Dec 23 Python
教你怎么用python爬取爱奇艺热门电影
May 20 Python
跟老齐学Python之编写类之二方法
Oct 11 #Python
Python中MYSQLdb出现乱码的解决方法
Oct 11 #Python
python操作mysql中文显示乱码的解决方法
Oct 11 #Python
wxPython窗口中文乱码解决方法
Oct 11 #Python
跟老齐学Python之编写类之一创建实例
Oct 11 #Python
跟老齐学Python之关于类的初步认识
Oct 11 #Python
跟老齐学Python之传说中的函数编写条规
Oct 11 #Python
You might like
PHP 一个比较完善的简单文件上传
2010/03/25 PHP
php数组函数序列之array_unique() - 去除数组中重复的元素值
2011/10/29 PHP
php数组索引的Key加引号和不加引号的区别
2014/08/19 PHP
PHP 使用位运算实现四则运算的代码
2021/03/09 PHP
js获取图片长和宽度的代码
2009/11/24 Javascript
千分位数字格式化(用逗号隔开 代码已做了修改 支持0-9位逗号隔开)的JS代码
2013/12/05 Javascript
关于jquery中全局函数each使用介绍
2013/12/10 Javascript
javascript框架设计读书笔记之种子模块
2014/12/02 Javascript
jquery实现简洁文件上传表单样式
2015/11/02 Javascript
Bootstrap实现响应式导航栏效果
2015/12/28 Javascript
深入解析AngularJS框架中$scope的作用与生命周期
2016/03/05 Javascript
JS锚点的设置与使用方法
2016/09/05 Javascript
浅谈jQuery中的eq()与DOM中element.[]的区别
2016/10/28 Javascript
jQuery对table表格进行增删改查
2020/12/22 Javascript
Ajax实现不刷新取最新商品
2017/03/01 Javascript
Angular4实现动态添加删除表单输入框功能
2017/08/11 Javascript
在create-react-app中使用css modules的示例代码
2018/07/31 Javascript
webpack4.0 入门实践教程
2018/10/08 Javascript
cocos2dx+lua实现橡皮擦功能
2018/12/20 Javascript
基于node+websocket+html实现腾讯课堂聊天室聊天功能
2020/03/04 Javascript
js实现无缝轮播图效果
2020/03/09 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
jquery实现抽奖功能
2020/10/22 jQuery
JavaScript中条件语句的优化技巧总结
2020/12/04 Javascript
[03:48]DOTA2完美大师赛主赛事第二日精彩集锦
2017/11/24 DOTA
下载安装setuptool和pip linux安装pip    
2014/01/24 Python
python与sqlite3实现解密chrome cookie实例代码
2018/01/20 Python
python matplotlib实现双Y轴的实例
2019/02/12 Python
Python+OpenCV实现实时眼动追踪的示例代码
2019/11/11 Python
TensorBoard 计算图的可视化实现
2020/02/15 Python
Python Opencv 通过轨迹(跟踪)栏实现更改整张图像的背景颜色
2020/03/09 Python
tensorflow从ckpt和从.pb文件读取变量的值方式
2020/05/26 Python
matplotlib基础绘图命令之bar的使用方法
2020/08/13 Python
Jeep牧马人、切诺基和自由人零配件:4 Wheel Drive Hardware
2017/07/02 全球购物
新加坡第一的杂货零售商:NTUC FairPrice
2020/12/05 全球购物
假如给我三天光明:舟逆水而行,人遇挫而达 
2019/10/29 职场文书