再看继承
真正的大餐来之前, 还是来点儿开胃菜! 回顾一下关于类的继承的知识:
我们先看上面的代码, 这是一个简单的类继承, 我们可以看到父类 Base 和子类 Son, 它们中各有一个 Testfunc 方法, 当我们实例化子类的对象 sonobj 时, 可以看到初始化方法中黄色框框调用了 Testfunc, 那么这个时候执行的是哪个类里面的代码呢? 我会告诉你执行的是子类里面的方法, 不信就自己试试吧, 代码在下面~
为什么呢? 其实这里是绕了一个圈, 所以把很多人绕晕了, 包括我! 后来想想其实很容易, 我们看最右边的图:
如果这样看, 我们是不是就明白了? 其实这两段代码表示的是一个意思, 尽管 Son 继承了 Base 类, 父子类中都有同样的方法, 但是由于我们实例化了子类的对象, 所以这个在初始化方法里的 self.Testfunc,self 指的是子类的对象, 当然也就先调用子类中的方法啦. 所以尽管在第一个例子中, 初始化方法在父类执行, 但是还是改变不了它是子类对象的本质, 当我们使用 self 去调用 Testfunc 方法时, 始终是先调用子类的方法. 我们可以这样理解, 尽管儿子继承了父亲的财产, 但是花钱的时候, 还是要先花自己的~~~
- #_*_coding:utf-8_*_
- __author__ = 'Eva_J'
- class Base(object):
- def __init__(self,name):
- self.name = name
- self.Testfunc()
- def Testfunc(self):
- print 'do Base Testfunc'
- class Son(Base):
- def Testfunc(self):
- print 'do Son Testfunc'
- sonobj = Son('sonobj')
- inherit Code
看完刚刚的代码, 我们就知道了对象和 self 的真实意义, 现在再来回忆一下关于继承的顺序问题:
看上面的代码, 我们猜测一下, 执行之后, 控制台会打印什么呢? 先揭晓答案, 会打印 Base2 方法中的内容, 原因很简单: 尽管这三个类中都有同样的 Testfunc 方法, 但是, 由于计算机在找方法的时候, 遵循的顺序是: Base2,Son,Base, 所以它会先找到 Base2 类, 而这个类中刚好有它要找的方法, 它也就欢欢喜喜的拿去执行啦!
- #_*_coding:utf-8_*_
- __author__ = 'Eva_J'
- class Base(object):
- def Testfunc(self):
- print 'do Base Testfunc'
- class Son(Base):
- def __init__(self,name):
- self.name = name
- self.Testfunc()
- def Testfunc(self):
- print 'do Son Testfunc'
- class Base2(object):
- def Testfunc(self):
- print 'do Base2 Testfunc'
- class GrandSon(Base2,Son):
- pass
- #sonobj = Son('sonobj')
- sonobj = GrandSon('sonobj')
- inherit2 Code
画个简易类图
刚刚我们只是写了一个小程序, 来说明类之间的继承和对象调用方法之间的联系, 但是如果我们想要 hold 住一个继承关系复杂的源码逻辑, 就需要类图来帮忙! 如果你觉得我要教你画类图那就大错特错了... 懒人症重症患者是懒得画那种东西的... 嘻, 先看图!
对照类图看源码
根据上面的图, 我们就拿到了 threadingTCPServer 的相关类, 并且搞清楚了它们之间的继承关系和方法, 接下来我们对照这张简易类图来看看代码执行的过程:
初始化相关过程:
执行 serve_forever 的相关代码:
就是这样, 我们一路按照调用轨迹去寻找, 每次看到一个调用都先对照上面的简易类图, 看看有没有重名方法, 如果有, 就要找到最近的方法并查看里面的内容, 以此类推: 按照这种方法, 就会感觉所有代码都在一个文件一样, 妈妈再也不用担心我看不懂源码, 哈!!! 当然啦, 这种方法比较山寨, 自己心里知道就好, 不要告诉别人你其实是这样看懂源码的~~~
来源: http://www.bubuko.com/infodetail-3201578.html