------
Python:面向对象的编程语言,多态,封装,继承三个主要特性
多态:来自希腊语,意味着有多种形式。
>>> from random import choice >>> x = choice(['Hello,World!',[1,2,'e','e',4]]) >>> x.count('e') 1任何不知道对象到底是什么类型,但又要对对象做的什么的时候,就要用到多态
>>> 1+2 3 >>> 'hot'+'dog' 'hotdog'#和下面的形式是一样的
>>> def add(x,y): return x+y ... >>> add(1,2) 3 >>> add('hot','dog') 'hotdog'#如果要打印信息的长度,只需要对象具有长度即可.
>>> def print_message(x): ... print 'The length of',repr(x),'is',len(x) ...用到的repr()就是多态特性的代表之一:可以对任何东西使用.
>>> print_message('Fnord') The length of 'Fnord' is 5 >>> print_message([1,2,3,4]) The length of [1, 2, 3, 4] is 4事实上,唯一能毁掉多态的就是函数显示的检查类型,比如:type,isinstance,issubclass,如果可能的话,尽量避免这些毁掉多态函数的方式。真正重要的是如何让对象按照我们的方式工作。
------
封装:是对全局作用域中其他区域隐藏多余信息的原则。
多态:使用对象,而不用知道其内部细节
两者概念类似,但是封装不等同于多态
多态可以让用户对于不知道是什么类的对象进行方法调用,而封装是可以不用关心对象是如何创建而直接使用。
------
继承:是一种“懒惰”的行为,程序员不想把代码写几次。
类:一种对象. 鸟类(supperclass)-->百灵鸟(subclass)
Note: Python的类名,不用复数,首字母大写,如果多个单词,首字母同样大写Bird
创建自定义类:
class Person: def setName(self,name): self.name = name def getName(self,name): return self.name def greet(self): print "Hello,World! I am %s" % self.name >>> foo = Person() >>> bar = Person() >>> foo.setName('Luke Skywalker') >>> bar.setName('Anakin Skywalker') >>> foo.greet() Hello,World! I am Luke Skywalker >>> bar.greet() Hello,World! I am Anakin Skywalkerself: 对象自身
------
特性,函数和方法
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... >>> 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 accessible(self): print "The scret message is:" self.__inaccessible() >>> s = Secretive() >>> s.__inaccessible() #不能直接访问 Traceback (most recent call last): File "<pyshell#29>", line 1, in <module> s.__inaccessible() AttributeError: Secretive instance has no attribute '__inaccessible' >>> s.accessible() #但能通过其他方法来访问 The scret message is: Bet you can't see me...#不能被外界直接使用,但可以再类内部使用,从而达到间接调用该方法.
#还有一种访问方法,要体会如何使用,主要是用于测试,看下面
>>> Secretive._Secretive__inaccessible <unbound method Secretive.__inaccessible>#提示未绑定的方法,只要在前面用instance来绑定就可以了。
>>> dir(Secretive) ['_Secretive__inaccessible', '__doc__', '__module__', 'accessible'] #dir()函数也可以看到 instance._ClassName__PrivateMethod() >>> s._Secretive__inaccessible() Bet you can't see me...Note: 如果不需要使用这种方法,但是又想让其他对象不要访问内部数据,那么可以使用单下划线。
前面有单下划线的不会被from module import * 语句导入
------
类的命名空间:
#下面两个函数应该是一样的
>>> def foo(x): return x*x ... >>> foo = lambda x:x*x#定义类时也一样,所有class语句中的代码都在类命令空间中执行,由类内所有成员访问.类的定义其实就是执行class语句中的代码块.这点非常有用,比如说类的语句并不仅限于def,比如下面的也是一样:
>>> class C: ... print "class C is being defined..." ... class C is being defined...再比如像下面的:
>>> class MemberCounter: ... members = 0 ... def init(self): ... MemberCounter.members +=1 ... >>> m1 = MemberCounter() >>> m1.init() >>> m1.members 1 >>> m2 = MemberCounter() >>> m2.init() >>> MemberCounter.members 2也可以像下面这样让其自动初始化
>>> class MC: ... m = 0 ... def __init__(self): ... self.m +=1 ... >>> m1 = MC() >>> m1.m 1
------
Note: Java 支持4中级别,尽管Python给出了单双下划线,但Python并没有真正的私有化支持
如果在实例中重新绑定members呢?
>>> m1.members = 'Two' >>> m1.members 'Two' >>> m2.members 2#这跟函数的局部,全局变量非常类似
------
指定超类:
class Filter: def __init__(self): self.blocked = [] #self.不能少 def filter(self,sequence): #注意这种写法,非常有用 return [x for x in sequence if x not in self.blocked] class SPAMFilter(Filter): #继承自父类或超类:Filter def __init__(self): #重写超类中的__init__方法 self.blocked = ['SPAM'] f1 = Filter() #实际上这个什么也没有过滤,[] print f1.filter([1,2,3]) s = SPAMFilter() #过滤掉了列表中所有含'SPAM'的元素 print s.filter(['SPAM','eggs','SPAM','bacon','SPAM'])输出结果:
>>> [1, 2, 3] ['eggs', 'bacon']NOTE: 注意子类SPAMFilter要点:
1. 重写Filter的init初始化方法
2. filter的方法继承自父类(Filter),不用重写.
第二点解示了继承的好处,我们可以写一大堆过滤的类,全部继承自Filter.
每个类都可以使用超类中,已经实现的方法:filter()
------
调查继承:
>>> issubclass(SPAMFilter,Filter) True
>>> Filter.__bases__ () >>> SPAMFilter.__bases__ (<class __main__.Filter at 0x00000000029E2DC8>,)
>>> s = SPAMFilter() >>> isinstance(s,SPAMFilter) True >>> isinstance(s,Filter) #同样是超类的一个对象 True >>> isinstance(s,str) FalseNote: 使用isinstance并不是个好习惯,使用多态好些.
>>> s.__class__ <class __main__.SPAMFilter at 0x00000000029E2F48>------
多个超类:
>>> class Calculator: def calculator(self,expression): self.value = eval(expression) >>> class Talker: def talk(self): print "Hi,my value is:", self.value >>> class TalkingCalculator(Calculator,Talker): pass
#子类不做任何事,从超类中继承所有的方法,从Calculator中继承calculator方法.
从Talker中继承talk的方法.这种行为成为多种继承
>>> TC = TalkingCalculator() >>> TC.calculator('1+2*3') >>> TC.talk() Hi,my value is: 7Note: 除非对超类特别熟悉,否则尽量避免使用,以免出现不可预知的错误.
------
接口和内省
接口的概念与多态有关。在处理多态对象时,只要关心它的接口即可-也就是公开的方法和特性.
Python,不用显式指定对象必须包含哪些方法才能做为参数接收。
一般来说,只需要让对象实现当前方法即可。 可用hasattr()来检查方法是否已经存在
>>> class Calculator: def calculator(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()>>> hasattr(tc,'talk')
>>> callable(getattr(tc,'talk'))
True
>>> callable(getattr(tc,'fnord',None))
False
与getattr相对应的是setattr
>>> setattr(tc,'name','Mr. Smith')
>>> tc.name
'Mr. Smith'
Note: callable函数在Python3.0不再使用,取而代之的是hasattr(x,'__call__')
------
本章函数
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) 返回对象的类型
------