Python的学习之旅---开始篇(五)
2015-01-29 16:36
211 查看
面向对象
在面向对象程序设计中,术语对象(object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。使用对象替代全局变量和函数的原因可能有很多。其中对象最重要的优点包括以下几个方面。
多态:意味着可以对不同类的对象使用同样的操作,他们会像被"施了魔法一般"工作。
封装:对外部世界隐藏对象的工作细节。
继承:以通用的类为基础建立专门的类对象。
多态意味着就算不知道变量所引用的对象类型是什么,还是能对它进行操作,而它也会根据对象(或类)类型的不同而表现出不同的行为。
关键点在于:不需要检测类型,只需要知道x有个叫做count的方法,带有一个字符作为参数,并且返回整数值就够了。如果其他人创建的对象也有Count方法,那也无所谓,你只需要像用字符串和列表一样使用该对象就行了。
在Python里面,很多内建运算符和函数都有多态的性质------你写的绝大多数程序可能都是,即使你并非有意这样。
事实上,唯一能够毁掉多态的就是使用函数显示地检查类型,比如type、isinstance、以及issubclass函数等。如果可能的话,应该尽力避免使用这些毁掉多态的方法。真正重要的是如何让对象按照你所希望的方式工作,不管它是否是正确的类型。
封装,指的是向程序中的其他部分隐藏对象的具体实现细节的原则,它会帮助处理程序组件而不用过多关心多余细节,就像函数做的一样。对象的状态由它的特性(比如名称)来描述。对象的方法可以改变它的特性。所以就像是将一大堆函数(方法)捆在一起,并且给予它们访问变量(特性)的权力,它们可以在函数调用之间保持保存的值。
(Python 中,习惯上都使用单数名词,并且首字母大写,比如Bird和Lark)
类和类型
定义子类只是个定义更多方法的过程。
(在旧版本的Python中,类和类型之间有很明显的区别。内建的对象是基于类型的,自定义的对象是基于类的。可以创建类但是不能创建类型。但是在最近的版本的Python中,事情有了些变化。基本类型和类之间的界限开始模糊了。可以创建内建类型的子类(或子类型),而这些类型的行为更类似于类。)
为了让方法或者特性变为私有(从外部无法访问),只要在它的名字墙面加上双下划线即可。但是在类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式。所以在类外还是能够访问这些私有方法,尽管不应该这么做:
module import *) 导入。
接口
接口的概念与多态有关。在处理多态对象时,只要关心它的接口(或称为协议)即可,也就是公开的方法和特性。在Python中,不用显式地指定对象必须包含哪些方法才能作为参数接收。
除了调用方法,然后期待一切顺利之外,还可检查所需方法是否已经存在。如果不存在,就需要做些其他事情:
1、将属于一类的对象放在一起。如果一个函数操纵一个全局变量,那么两者最好都在类内作为特性和方法出现。
2、不要让对象过于亲密。方法应该只关心自己实例的特性。让其他实例管理自己的状态。
注:以上代码和笔记来自《Python基础编程 第二版》
4000
在面向对象程序设计中,术语对象(object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。使用对象替代全局变量和函数的原因可能有很多。其中对象最重要的优点包括以下几个方面。
多态:意味着可以对不同类的对象使用同样的操作,他们会像被"施了魔法一般"工作。
封装:对外部世界隐藏对象的工作细节。
继承:以通用的类为基础建立专门的类对象。
多态意味着就算不知道变量所引用的对象类型是什么,还是能对它进行操作,而它也会根据对象(或类)类型的不同而表现出不同的行为。
>>> 'abc'.count('a') 1 >>> [1,2,'a'].count('a') 1 >>> from random import choice >>> x = choice(['Hello,world',[1,2,'e','e',4]]) >>> x.count('e') 1 >>> x = choice(['Hello,world',[1,2,'e','e',4]]) >>> x.count('e') 2(标准库random中包含choice函数,可以从序列中随机选出元素,给变量赋值)
关键点在于:不需要检测类型,只需要知道x有个叫做count的方法,带有一个字符作为参数,并且返回整数值就够了。如果其他人创建的对象也有Count方法,那也无所谓,你只需要像用字符串和列表一样使用该对象就行了。
在Python里面,很多内建运算符和函数都有多态的性质------你写的绝大多数程序可能都是,即使你并非有意这样。
事实上,唯一能够毁掉多态的就是使用函数显示地检查类型,比如type、isinstance、以及issubclass函数等。如果可能的话,应该尽力避免使用这些毁掉多态的方法。真正重要的是如何让对象按照你所希望的方式工作,不管它是否是正确的类型。
封装,指的是向程序中的其他部分隐藏对象的具体实现细节的原则,它会帮助处理程序组件而不用过多关心多余细节,就像函数做的一样。对象的状态由它的特性(比如名称)来描述。对象的方法可以改变它的特性。所以就像是将一大堆函数(方法)捆在一起,并且给予它们访问变量(特性)的权力,它们可以在函数调用之间保持保存的值。
(Python 中,习惯上都使用单数名词,并且首字母大写,比如Bird和Lark)
类和类型
定义子类只是个定义更多方法的过程。
(在旧版本的Python中,类和类型之间有很明显的区别。内建的对象是基于类型的,自定义的对象是基于类的。可以创建类但是不能创建类型。但是在最近的版本的Python中,事情有了些变化。基本类型和类之间的界限开始模糊了。可以创建内建类型的子类(或子类型),而这些类型的行为更类似于类。)
__metaclass__ = type class Person: def setName(self,name): self.name = name def getName(self): return self.name def greet(self): print ("Hello, world! I'm %s." % self.name)self 参数实际上正是方法和函数的区别。方法(更专业一点可以称为绑定方法)将它们的第一个参数绑定到所属的实例上,因此你无需显示地提供该参数。当然也可以将特性绑定到一个普通函数上,这样就不会有特殊的self参数了:
>>> class Class: def method(self): print ("i have a self") >>> def function(): print ("I don't...") >>> instance = Class() >>> instance.method() i have a self >>> instance.method = function >>> instance.method() I don't... >>>(注意,self 参数并不依赖于调用方法的方式,前面我们使用的是instance.method(实例.方法)的形式,可以随意使用其他变量引用同一个方法)
>>> class Bird: song = 'Squaawk' def sing(self): print (self.song) >>> bird = Bird() >>> bird.sing() Squaawk >>> birdsong = bird.sing >>> birdsong() SquaawkPython并不直接支持私有方式,而是靠程序员自己把握在外部进行特性修改的时机。毕竟在使用对象前应该知道如何使用。但是,可以使用一些小技巧达到私有特性的效果。
为了让方法或者特性变为私有(从外部无法访问),只要在它的名字墙面加上双下划线即可。但是在类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式。所以在类外还是能够访问这些私有方法,尽管不应该这么做:
>>> s._Secretive__inaccessible()简而言之,确保其他人不会访问对象的方法和特性是不可能的,但是这类“名称变化术”就是他们不应该访问这些函数或者特性的强有力信号。如果不需要使用这种方法但是又想让其他对象不要访问内部数据,那么可以使用单下划线。这个的确有实际效果。例如前面有下划线的名字都不会被带星号的Import语句(from
module import *) 导入。
>>> class MemberCounter: members = 0 def init(self): MemberCounter.members +=1 >>> m1 = MemberCounter() >>> m1.init() >>> MemberCounter.members 1 >>> m2 = MemberCounter() >>> m2.init() >>> MemberCounter.members 2 >>> m1.members 2 >>> m2.members 2 >>> m1.members = 3 >>> m1.members 3 >>> m2.members 2 >>> MemberCounter.members=5 >>> m1.members 3 >>> m2.members 5新numbers值被写到m1的特性中,屏蔽了类范围内的变量。这跟函数内的局部和全局变量的行为十分类似。
>>> class Filter: def init(self): self.blocked = [] def filters(self,sequence): return [x for x in sequence if x not in self.blocked] >>> class SPAMFilter(Filter): # SPAMFilter 是Filter的子类 def init(self): # 重写Filter超类中的init方法 self.blocked = ['SPAM']测试一:
>>> f = Filter() >>> f.init() >>> f.filters([1,2,3]) [1, 2, 3]测试二:
>>> s.filters(['SPAM','SPAM','SPAM','SPAM','eggs','bacon','SPAM']) ['eggs', 'bacon'] >>>Python支持多重继承,是个非常有用的工具,但是当使用多重继承的时候,有个特别需要注意的地方。如果一个方法从多个超类继承(也就是说你有两个相同名字的不同方法),那么必须要注意下超类的顺序(在class语句中):先继承的类中方法会重用后继承的方法。
接口
接口的概念与多态有关。在处理多态对象时,只要关心它的接口(或称为协议)即可,也就是公开的方法和特性。在Python中,不用显式地指定对象必须包含哪些方法才能作为参数接收。
除了调用方法,然后期待一切顺利之外,还可检查所需方法是否已经存在。如果不存在,就需要做些其他事情:
>>> hasattr(tc, 'talk') True >>> hasattr(tc,'fnord') False一些与面向对象设计有关的思考:
1、将属于一类的对象放在一起。如果一个函数操纵一个全局变量,那么两者最好都在类内作为特性和方法出现。
2、不要让对象过于亲密。方法应该只关心自己实例的特性。让其他实例管理自己的状态。
注:以上代码和笔记来自《Python基础编程 第二版》
4000
相关文章推荐
- 新的学习:从Python开始[转]
- 从现在开始要学习Python了
- 开始学习python
- python学习笔记,以此开始记录自己的python学习过程
- 开始学习python
- 今天开始在这里写学习Python、应用Python的学习笔记
- 正式开始学习Python!
- 今天开始学习Python
- 开始学习Python
- Learn Python The Hard Way学习(52) - 开始你的web游戏
- 今天开始学习python
- 开始学习python了,第一个程序是一个逆波兰式的表达式分析器
- 开始学习Python
- 开始学习Python了
- 开始学习Python了
- 开始学习python
- 开始学习PYTHON,希望能在短期内掌握应用
- 开始学习python
- 开始学习Python
- 新的学习:从Python开始