多态
多态意味着不知道变量所引用的对象类型是什么,还是能对它进行操作,而它也会根据对象(或类)类型的不同而表现出不同的行为。
封装
封装是指向程序中的其他部分隐藏对象的具体实现细节的原则。
创建自己的类
>>> _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('Alice')
>>> bar.setName('Bobby')
>>> foo.greet()
Hello , world ! I'm Alice.
>>> bar.greet()
Hello , world ! I'm Bobby.
注: metaclass = type,在新式类的语法中才需要加。这里self参数是对于对象自身的引用。其中setName等叫做类的方法。
特性、函数和方法
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 Class:
... def method(self):
... print 'I have a self'
...
>>> cls = Class()
>>> cls.method()
I have a self
>>> method = cls.method
>>> method()
I have a self
注:尽管最后一个方法调用看起来于函数调用十分相似,但是变量method引用绑定方法cls.method上,也就意味着这还是会对self参数进行访问(也就是说,它仍旧绑定到类的相同实例上)。
私有化
为了让方法或者特性变为私有(从外部无法访问),只要在它的名字前面加上双下划线即可。例:
>>> 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.accessible()
The secret message is :
Bet you can't see me ...
>>> s.__inaccessible()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Secretive instance has no attribute '__inaccessible'
类的内部定义中,所有的双下划线开始的名字都被‘翻译’成前面加上单下划线和类名的形式。如:
>>> Secretive._Secretive__inaccessible
<unbound method Secretive.__inaccessible>
因此上例中的私有化方法可以如下所示进行访问:
>>> s._Secretive__inaccessible()
Bet you can't see me ...
如果不需要使用这种方法但是又想让其他对象不要访问内部数据,那么可以使用单下划线。例:
>>> class Secretive:
... def _inaccessible(self):
... print "Bet you can't see me ..."
...
>>> s = Secretive()
>>> s._Secretive__inaccessible()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Secretive instance has no attribute '_Secretive__inaccessible'
>>> s._Secretive_inaccessible()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Secretive instance has no attribute '_Secretive_inaccessible'
类的命名空间
例:
>>> class MemberCounter:
... members = 0
... def init(self):
... MemberCounter.members+=1
...
>>> m1 = MemberCounter()
>>> m1.init()
>>> MemberCounter.members
1
>>> m2 = MemberCounter()
>>> m2.init()
>>> MemberCounter.members
2
>>> m2.members
2
>>> m1.members = 'two'
>>> m1.members
'two'
>>> m2.members
2
分析说明:类中定义了一个可供所有成员(实例)访问的变量members,用来计算类的成员数量(我们可以把它理解为全局变量),然后又在实例m1中重新绑定了members的值(此时相当于是局部变量,所以屏蔽了类范围内的变量)。
指定超类
例:
>>> 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): #重写Filter超类中的init方法
... self.blocked = ['SPAM']
...
>>> f = Filter()
>>> f.init()
>>> f.filter([1,2,3])
[1, 2, 3]
>>> s = SPAMFilter()
>>> s.init()
>>> s.filter(['SPAM', 'SPAM', 'SPAM', 'SPAM', 'eggs', 'bacon', 'SPAM'])
['eggs', 'bacon']
检查继承
如果要查看一个类是否是另一个类的子类,可以使用内建函数的issubclass函数。例:
>>> issubclass(SPAMFilter, Filter)
True
>>> issubclass(Filter, SPAMFilter)
False
如果想要知道已知类的基类(们),可以直接使用它的特殊特性_bases_。例:
>>> SPAMFilter.__bases__
(<class __main__.Filter at 0x02324D18>,)
>>> Filter.__bases__
()
使用isinstance方法检查一个对象是否是一个类的实例。例:
>>> isinstance(s, SPAMFilter)
True
>>> isinstance(s, Filter)
True
>>> isinstance(f, SPAMFilter)
False
可以使用_class_特性知道一个对象属于哪个类。例:
>>> s.__class__
<class __main__.SPAMFilter at 0x02324C38>
>>> f.__class__
<class __main__.Filter at 0x02324D18>
多个超类
Python中支持多重继承,即一个类可以有多个超类。当使用多重继承时,如果一个方法从多个超类继承(也就是说有两个具有相同名字的不同方法),那么必须要注意一下超类的顺序(在class语句中):先继承的类中的方法会重写后继承的类中的方法,这种访问超类的顺序为MRO(Method Resolution Order,方法判定顺序)。例:
>>> class Calculator:
... def calculator(self, expression):
... self.value = eval(expression)
... def talk(self):
... print 'Hi, my value is : ', self.value
...
>>> class Talker:
... def talk(self):
... print 'Hi, now you can get my value is : ', self.value
...
>>> class TalkingCalculator(Calculator, Talker):
... pass
...
>>> tc = TalkingCalculator()
>>> tc.calculator('1+2*3')
>>> tc.talk()
Hi, my value is : 7
>>> class TalkingCalculator(Talker, Calculator):
... pass
...
>>> tc1 = TalkingCalculator()
>>> tc1.calculator('1+2*3')
>>> tc1.talk()
Hi, now you can get my value is : 7
接口和内省
可以使用hasattr方法检查所需方法是否已经存在。例:
>>> hasattr(tc, 'talk')
True
>>> hasattr(tc, 'finder')
False
可以使用callable方法检查所需的方法是否可调用。例:
>>> callable(getattr(tc, 'tall', None))
False
>>> callable(getattr(tc, 'talk', None))
True
本章新函数
callable(object): 确定对象是否可调用(比如函数或者方法)
getattr(object,name[, default]): 确定特性的值,可选择提供默认值
hasattr(object,name):确定对象是否有给定的特性
isinstance(object,class):确定对象是否是类的实例
issubclass(A,B):确定A是否为B的子类
random.choice(sequence):从非空徐磊中随机选择元素
setattr(object,name,value):设定对象的给定特性为value
type(object):返回对象的类型