7.1 对象的魔力
多态 不同的类的对象使用同样的操作
封装
继承
7.1.1 多态
1、多态和方法
>>>object.getPrice() >>> '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
python的多态不需要做类型检测,只要有相同的方法就行,python的多态其实有点像java的函数重载
>>> def add(x,y): ... return x + y ... >>> add(1,2) 3 >>> add('Fish','License') 'FishLicense' >>> 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
很多系统函数和运算符都是多态的
唯一能够销毁多态的就是使用函数显示做类型检测,比如type,isinstance、issubclass,但是尽量避免消除
7.1.2 封装
7.1.2 继承
7.2 类和类型
7.2.1 类到底是什么
7.2.2 创建自己的类
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 Skywaler') >>> foo.greet() Hello world! I'm Luke Skywalker >>> bar.greet() Hello world! I'm Anakin Skywaler
self 表示对象本身的引用,对象的属性和方法可以动态的添加
>>> foo.name 'Luke Skywalker' >>> bar.name 'Anakin Skywaler' >>> bar.name='Yoda' >>> bar.greet() Hello world! I'm Yoda
7.2.3 特性、函数和方法
>>> class Class: ... def method(self): ... print 'I hava a self!' ... >>> >>> def function(): ... print "I don't ..." ... >>> instance=Class() >>> instance.method() I hava a self! >>> instance.method=function >>> instance.method() I don't ...
#可以绑定一个不存在的方法
>>> instance.method1=function >>> instance.method1() I don't ...
self参数并不取决于调用方法的方式
>>> class Bird: ... song='Squaawk!' ... def sing(self): ... print self.song ... >>> bird=Bird() >>> bird.sing() Squaawk! >>> birdsong=bird.sing #用另外一个变量调用也可以 >>> birdsong() Squaawk!
再论私有化,前面带有两个__的属性或者方法即为私有方法
>>> class Secretive: ... def __inaccessible(self): ... print "Bet you can't see me..." ... def accessiable(self): ... print "The secret message is :" ... self.__inaccessible() ... >>> s=Secretive() >>> s.__inaccessible() Traceback (most recent call last): File "", line 1, in AttributeError: Secretive instance has no attribute '__inaccessible' >>> s.accessiable() The secret message is : Bet you can't see me...
通过其他方式依然可以访问得到
>>> Secretive._Secretive__inaccessible
>>> s._Secretive__inaccessible()
Bet you can't see me...
前面有下划线的方法,不会被from module import * 导入
7.2.4 类的命令空间
位于class语句中的代码都在类的命名空间,定义类的过程其实就是在执行语句块,这个命令空间可由类内所有成员访问
>>> def foo(x): return x*x ... >>> >>> foo = lambda x:x*x #lambda 用来定义简单的函数
>>> 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
新的numbers值被写到m1的特性中,屏蔽了类范围的变量,新的number属性属于对象的变量了
>>> m1.members='Tow' >>> m1.members 'Tow' >>> m2.members 2 >>> MemberCounter.members 2
7.2.5 指定超类
#!/usr/bin/python #coding:utf-8 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): #重写Filter超类中的init方法 self.blocked=['SPAM']
f=Filter() f.init() print f.filter([1,2,3])
s=SPAMFilter() s.init() print s.filter(['SPAM','SPAM','eggs','bacon','SPAM','SPAM'])
[1, 2, 3] ['eggs', 'bacon']
SPAMFilter两个要点:
1、重写了Filter的init()方法
2、继承了filter方法
7.2.6 调查继承
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']
#判断一个类是否是另一个的子类
>>> issubclass(SPAMFilter,Filter) True >>> issubclass(Filter,SPAMFilter) False
#查看已知类的基类
>>> SPAMFilter.__bases__ (,) >>> Filter.__bases__ ()
#isinstance检查对象是否为一个类的实例
>>> s=SPAMFilter() >>> isinstance(s,SPAMFilter) True >>> isinstance(s,Filter) True >>> isinstance(s,str) False
>>> type(s)
#查看一个对象属于哪个类
>>> s.__class__
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 ... >>> tc=TalkingCalculator() >>> tc.calculate('1+2*3') >>> tc.talk() Hi,my value is 7
注意:尽量少用多重继承
如果一个方法从多个超类继承,先继承的类中的方法会重新后继承的类中的方法
7.2.8 接口和内省
Python中,不用显示的指定对象必须包含哪些方法才能作为参数接收,不用显示的编写接口
>>> hasattr(tc,'talk') True >>> hasattr(tc,'fnord') False >>>
#getattr可以指定一个默认值,如果不存在,则指定一个默认值
>>> callable(getattr(tc,'talk',None)) True >>> callable(getattr(tc,'fnord',None)) False >>> setattr(tc,'name','Mr.Gumby') >>> tc.name 'Mr.Gumby'
#查看对象内所有存储的值
>>> tc.__dict__ {'name': 'Mr.Gumby', 'value': 7}
如果要看对象由什么组成的,可以看看inspect模块