当一个对象创建时,会自动调用构造方法
class FooBar:
def __init__(self): #创建一个名为__init__的方法,它会自动成为构造方法
self.somevar = 42
f = FooBar()
f.somevar
#其实,这个方法还能加入参数
class FooBar2:
def __init__(self, value = 42):
self.somevar = value
f1 = FooBar()
f1.somevar
#怎么给出value的值呢?直接在类名的括号内给出就可以了
f2 = FooBar2(24)
f2.somevar
与init相对的还有一个del方法
它在对象要被垃圾回收之前调用,具体时间是不可预料的,应该尽量避免
假设存在一个类A和它的子类B,两个类都写有各自的构造方法
那么B的构造方法就会被重写而覆盖掉A的构造方法
那么初始化的时候并没有继承超类的初始化
而往往我们又需要它继承超类的初始化,然后自己添加需要的新的初始化
这时候可以通过两个方法解决——调用超类构造方法的未绑定版本、使用super函数
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print 'Ahhhh......'
self.hungry = False
else:
print 'No, thanks!'
#定义一个基类Bird,它会自动初始化为hungry,它有一个方法eat,会判断自己是否hungry来选择行为
主要用于旧式类,看懂就好
一般在调用一个实例时,self会自动绑定到实例自身,称为绑定方法
但是我们也可以手动给出self的值,称为未绑定(unbound)方法
class SongBird(Bird):
def __init__(self):
Bird.__init__(self) #如果去掉这行,那么由于__init__方法的重写,并不会执行self.hungry = True
#超类.__init__(self)
self.sound = 'Squawk'
def sing(self):
print self.sound
#定义一个Bird的子类SongBird,它会继承超类的初始化,并且添加上自己的初始化sound,并且具有方法sing
#注意第三行代码
注意第三行self,它不是Bird自身,而是SongBird(的实例)
只能用于新式类(必须在模块或者程序的开头加入赋值语句“__metaclass__=type”),要掌握
优点——
class SongBird(Bird):
def __init__(self):
super(SongBird, self).__init__() #把第三行改成这样
#super(子类,self).__init__()
self.sound = 'Squawk'
def sing(self):
print self.sound
规则(protocol):描述管理某种形式行为的规则,说明了应该实现何种方法以及这些方法做什么
python中的多态性是基于对象的行为,而不是祖先的行为
其他语言中对象可能被要求属于某个类,或者实现某个借口,但是python只要求对象遵循给定的规则即可
若对象可变,那么需要使用两个魔法方法;
若对象不可变,那么需要使用四个魔法方法
(假设我们创建了一个类似序列或映射的对象a)
__delitem__(self, key):使用del语句时会被调用,删除对象
执行诸如del a[2]时会调用该方法
附加要求——
#接下来我们来模拟无穷序列的相关操作
def checkIndex(key):
'''
检查所给的键是否是能接受的索引
键应该是非负整数
如果不是整数,引发TypeError
如果是负数,引发IndexError(因为这是一个无穷序列)
'''
if not isinstance(key, (int, long)): raise TypeError #如果key不是int或long类型,引发TypeError
#这里使用的isinstance函数,这个函数应该避免使用的,但是为了遵循序列的规则,我们不得不使用它
if key < 0: raise IndexError
class ArithmeticSequence:
def __init__(self, start = 0, step = 1):
'''
初始化算术序列
start:序列的第一个值
step:步长
changed:用户修改的值的字典
'''
self.start = start
self.step = step
self.changed = {}
def __getitem__(self, key):
'优先去检查用户修改的项,否则计算对应的值'
checkIndex(key)
try:
return self.changed[key] #尝试去取这个值
except KeyError: #如果键错误
return self.start + key * self.step #返回计算值
def __setitem__(self, key, value):
checkIndex(key)
self.changed[key] = value
s = ArithmeticSequence(1, 2) #参数1,2分别传递给start和step的初始化
s[4]
s[4] = 2
s[4]
s[5]
s.changed
del s[4] #我们没有给出__delitem__方法,所以会报错
len(s) #我们没有给出__len__方法,所以也会报错
如果我们要写一个类,它具有列表的大部分功能,但是又要修改一部分功能
就可以把这个类,作为list类型的子类,然后重写你所需要修改的方法(这个行为称为子类化)
相应的字典的类型是dict,字符串的类型是string