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模块