前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Python基础教程》 读书笔记 第七章 更加抽象(下)

《Python基础教程》 读书笔记 第七章 更加抽象(下)

作者头像
统计学家
发布2019-04-10 16:46:51
4780
发布2019-04-10 16:46:51
举报

7.2.4类的命名空间

定义类时,所有位于class语句中的代码都在特殊的命名空间中执行——类命名空间(class namespace)。这个命名空间可由类内所有成员访问。类的定义其实就是执行代码块,这一点非常有用,比如,在类的定义区并不只限使用def语句:

>>> class C: ... print 'Class C being defined...' ... Class C being defined...

再看:

Class C being defined... >>> class MemberCounter: ... members=0 ... def init(self): ... MemberCounter.members+=1 ... >>> m1=MemberCounter() >>> m1.init() >>> MemberCounter.members 1 >>> m2=MemberCounter() >>> m2.init() >>> MemberCounter.members 2

上面的代码中,在类作用域内定义了一个可供所有成员(实例)访问的变量,用来计算类的成员数量。init用来初始化所有实例。就像方法一样,类作用域内的变量也可以被所有实例访问:

>>> m1.members 2 >>> m2.members 2

在实例中重绑定members特性:

>>>m1.members='Two' >>>m1.members 'Two' >>>m2.members 2

新numbers值被写到了m1的特性中,屏蔽了类范围内的变量。这跟函数内的局部和全局变量的行为十分类似。

7.2.5指定超类

子类可以扩展超类的定义,将其他类名写在C1dSS语句后的圆括号内可以指定超类:

>>> class Filter: ... def init(self): ... self.blocked=[] ... def filter(self,sequence): ... return [x for x in sequence if x not in self.blocked] ... >>> class SPAMFilter(Filter): ... def init(self): ... self.blocked=['SPAM'] ...

Filter是个用于过滤序列的通用类,事实上它不能过滤任何东西:

>>> f=Filter() >>> f.init() >>> f.filter([1,2,3]) [1, 2, 3]

Filter类的用处在于它可以用作其他类的基类(超类),比如SPAMFilter类,可以将序列中的

"SPAM”过滤出去。

>>> s=SPAMFilter() >>> s.init() >>>s.filter(['SPAM','SPAM','eggs','SPAM','bacon','SPAM']) ['eggs', 'bacon']

filter方法的定义是从Filter类中拿过来(继承)的,所以不用重写它的定义。

7.2.6调查继承

如果想要查看一个类是否是另一个的子类,可以使用内建的issubclass函数:

>>> issubclass(SPAMFilter,Filter) True >>> issubclass(Filter,SPAMFilter) False

如果想要知道已知类的基类(们),可以直接使用它的特殊特性__bases__

>>> SPAMFilter.__bases__ (<class __builtin__.Filter at0x00E61880>,) >>> Filter.__bases__ ()

还能用使用isinstance方法检查一个对象是否是一个类的实例:

>>> isinstance(s,SPAMFilter) True >>> isinstance(s,Filter) True >>> isinstance(s,str) False

如果只想知道一个对象属于哪个类,可以使用_class一特性:

>>> s.__class__ <class __builtin__.SPAMFilter at0x00E61EA0>

7.2.7多个超类

>>> class Calculator: ... def calculate(self,expression): ... self.value=eval(expression) ... >>> class Talker: ... def talk(self): ... print 'hi my value is ' ,self.value ... >>> class TalkingCalculator(Calculator,Talker): ... pass ...

子类(TalkingCalculator)自己不做任何事,它从自己的超类继承所有的行为。它从Calculator类那里继承calculate方法,从Talker类那里继承talk方法,这样它就成会说话的计算器(talking calculator)。

>>> tc=TalkingCalculator() >>> tc.calculate('1+2*3') >>> tc.talk() hi my value is 7

这种行为称为多重继承(multiple inheritance )

7.2.8接口和内省

“接口”的概念与多态有关。在处理多态对象时,只要关心它的口(或称“协议”)即可——也就是公开的方法和特性。在Python中,不用显式地指定对象必须包含哪些方法才能作为参数接收。

一般来说只需要让对象符合当前的接口(换句话说就是实现当前方法),但是还可以更灵活一些。除了调用方法然后期待一切顺利之外,还可检查所需方法是否已经存在—如果不存在,就需要做些其他事情:

>>>hasattr(tc,'talk') True >>>hasattr(tc,'fnord') False

检查talk特性是否可调用:

>>> callable(getattr(tc,'talk',None)) >>> callable(getattr(tc,'fnord',None))

7.3小结

对象:对象包括特性和方法。特性只是作为对象的一部分的变量,方法则是存储在对象内的函数。(绑定)方法和其他函数的区别在于方法总是将对象作为自己的第一个参数,这个参数一般称为self

:类代表对象的集合(或一类对象),每个对象(实例)都有一个类。类的主要任务是定义它的实例会用到的方法。

多态:多态是实现将不同类型和类的对象进行同样对待的特性—不需要知道对象属于哪个类就能调用方法。

封装:对象可以将它们的内部状态隐藏(或封装)起来。在一些语言中,这意味着对象的状态(特性)只对自己的方法可用。在Python中,所有的特性都是公开可用的,但是程序员应该在直接访问对象状态时谨慎行事,因为他们可能无意中使得这些特性在某些方面不一致。

继承:一个类可以是一个或者多个类的子类。子类从超类继承所有方法。可以使用多个超类,这个特性可以用来组成功能的正交部分(没有任何联系)。普通的实现方式是使用核心的超类和一个或者多个混合的超类。

接口和内省:一般来说,对于对象不用探讨过深。程序员可以靠多态调用自己需要的方法。不过如果想要知道对象到底有什么方法和特性,有些函数可以帮助完成这项工作。

面向对象设计:关于如何(或者说是否应该进行)面向对象设计有很多的观点。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2015-05-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器学习与统计学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档