20161217py学习笔记:魔法方法/
1、魔法方法也是method,也是定义class中用到函数,只不过这些函数的名字,前后都是双下划线。
初始化:__init__
class FooBar:
def __init__(self,value=42):
self.somevar=value
原来想用‘somevar’,大概得这么写:
>>>f=FooBar()
>>>f.__init__
#如果__init__下还有几个self.some*,这么一写得全引用出来,但是我们想用的只是somevar,所以用__init__可以写成如下形式:
>>>f=FooBar()
>>>f.somevar #定义在初始化中,直接就拿来用
>>>42
#加个参数也可以:
>>>f=FooBar('this is a constructor argument')
>>>f.somevar
>>>this is aconstructor argument
2、superclass与subclass都有构造方法的情况下,subclass如何调用superclass的构造方法
class Bird:
def __init__(self):#这是类的方法
self.hungry=True
def eat(self):#这是实例的方法
if self.hungry:
print'Aaaah...'
self.hungry=False
else:
print'No,thanks!'
class SongBird(Bird):
def __init__(self):
self.sound='Squawk!'
def sing(self):
print self.sound
>>>sb=SongBird()
>>>sb.eat()
会报错,因为subclass的构造方法把superclass的覆盖了。
在subclass中添加superclass的构造方法
做如下修改:
class SongBird(Bird):
def __init__(self):
Bird.__init__(self)#在subclass的构造方法中,加上superclass的构造方法
self.sound='Squawk!'
def sing(self):
print self.sound
但是输出时,会变得比较奇怪。
>>>sb=SongBird()
>>>sb.eat()
>>>'Aaaah...'
>>>sb.eat()
>>>'No,thanks'
这是因为在调用实例的方法时,self参数会被自动绑定到实例上(这也是上面的例子(***),为什么直接调用sb.eat()会说no thanks),if句子根本没起作用;
直接调用类的方法(Bird.__init__),就没有实例被绑定。
使用superclass直接调用
class SongBird():
def __init__():
super(Bird,self).__init__()
self.sound='Squawk!'
def sing(self):
print self.sound
3、魔法方法之基本的序列和映射规则
def checkIndex(key):
'''所给的键是能接受索引的吗?为了能被接受,键应该是一个非负的整数。如果它不是一个整数,会引发TypeError;如果是负数,会引发IndexError。(因为序列是无限长的)。
if not isinstance(key,(int,long)):raise TypeError
if key<0: raise IndexError
class ArithmeticSequence:
def __init__(self,start=0,step=1):
'''
初始化算术序列
self.start,序列中的第一个值
self.step,两个相邻的差值
self.changed,用户修改的值得字典
self.start=start
self.step=step
self.changed={}
def __getitem__(self,key):
'''
Get an item from the aritmetic sequence.
'''
try: return self.changed[key] #修改了吗?
except KeyError: #否则...
return self.start+key*self.step #...计算值
def __setitem__(self,key,value):
'''
修改算术序列中的一个项
'''
checkIndex(key)
self.changed[key]=value #保存更改后的值
4、子类化list/dict/string
class CounterList(list):#subclass CounterList继承了superclass list的特性
def __init__(self,*args):
super(CounterList,self).__init__(*args)#super函数,调用superclass list的构造方法
self.counter=0
def __getitem__(self,index):#重写了__getitem__方法
self.counter+=1
return super(CounterList,self).__getitem__(index)