一、对象的魔力
对象可以看成数据(特性)以及一系列可以存取、操作这些数据的方法所组成的集合。
1、多态
多态意味着可以对不同类的对象使用同样的操作。
1.1 多态和方法
绑定到对象特性上面的函数称为方法:
>>> 'abc'.count('a')
1
>>> [1,2,'a'].count('a')
1
对于变量x来说,不需要知道它是字符串还是列表,就可以调用它的count方法,不需要管它是什么类型。
>>> from random import choice
>>> x=choice(['Hello,world!',[1,2,'e','e',4]])
>>> x
[1, 2, 'e', 'e', 4]
>>> x.count('e')
2
标准库random中包含choice函数,该函数从序列中随机选出元素。
上面的例子也验证了多态的定义,不同的对象可是使用同样的操作。
1.2 多态的多种形式
很多函数和运算符都是多态的:
>>> 1+2
3
>>> 'Fish'+'license'
'Fishlicense'
>>> def add(x,y):
return x+y
>>> add(1,2)
3
>>> add('Fish','licence')
'Fishlicence'
>>> def length_message('Fnord')
SyntaxError: invalid syntax
>>> def length_message(x):
print "The length of",repr(x),"is",len(x)
>>> length_message('Fnord')
The length of 'Fnord' is 5
>>> length_message([1,2,3])
The length of [1, 2, 3] is 3
上述代码中repr函数是多态特性之一,可以对任何东西使用。事实上,只有使用函数显式检查类型才会破坏多态,比如type、isinstance、issubclass函数等。所以应该尽量避免使用这些可以毁掉多态的函数。
2、封装
封装是指向程序中的其他部分隐藏对象的具体实现细节的原则。和多态的区别在于:多态可以让用户对于不知道什么类的对象进行方法调用,而封装是可以不用关心对象是如何构建的而直接进行使用。
二、类和类型
1、创建自己的类
__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
>>> foo=Person()
>>> bar=Person()
>>> foo.setName('Luke Skywalker')
>>> bar.setName('Anakin Skywalker')
>>> foo.greet()
Hello,world! I'm Luke Skywalker.
>>> bar.greet()
Hello,world! I'm Anakin Skywalker.
新式类的语法中需要在模块或者脚本开始的地方放置赋值语句__metaclass__=type
self是对于对象自身的引用。在调用foo的setName和greet函数时,foo自动将自己作为第一个参数传入函数中,如果没有self,成员方法就没法访问他们要对其特性进行操作的对象本身了。
2、私有化
为了让方法或者特性变为私有,只要在它的名字前面加上双下划线即可:
>>> class Secretive:
def __inaccessible(self):
print "Bet you can't see me..."
def accessible(self):
print "The secret message is:"
self.__inaccessible()
>>> s=Secretive()
>>> s.__inaccessible()
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
s.__inaccessible()
AttributeError: Secretive instance has no attribute '__inaccessible'
>>> s.accessible()
The secret message is:
Bet you can't see me...
类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式。实际上还可以在类外访问这些私有方法,但是不建议这么做。
>>> s._Secretive.__inaccessible()
3、继承超类
>>> 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):#SPAMFilter是Filter的子类
def init(self):
self.blocked=['SPAM']
使用issubclass函数可以检查一个类是否是另一个类的子类:
>>> issubclass(SPAMFilter,Filter)
True
>>> issubclass(Filter,SPAMFilter)
False
特性 __bases__用于检查已知类的基类:
>>> SPAMFilter.__bases__
(<class __main__.Filter at 0x0129B960>,)
>>> Filter.__bases__
()
使用 __class__特性查看一个对象属于哪个类:
>>> s.__class__
<class __main__.SPAMFilter at 0x01688CE0>
也可以多重继承:
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
注意,在多重继承过程中,如果一个方法从多个超类继承(也就是有两个相同名字的不同方法),先继承的类中的方法会重写后继承的类的方法。
本章学到的函数: