1、构造函数
(1) __init__
l 要为类提供构造函数,只要在类中实现__init__()方法:
class FooBar:
def __init__(self):
self.somevar = 42
>>> f = FooBar()
>>> f.somevar
42
l 可以为构造函数提供参数:
class FooBar:
def __init__(self, value=42):
self.somevar = value
>>> f = FooBar('This is a constructor argument')
>>> f.somevar
'This is a constructor argument'
l 重载构造函数的例子:
class Bird:
def __init__(self):
self.hungry = 1
def eat(self):
if self.hungry:
print 'Aaaah...'
self.hungry = 0
else:
print 'No, thanks!'
class SongBird(Bird):
def __init__(self):
self.sound = 'Squawk!'
def sing(self):
print self.sound
l 由于重载构造函数时没有调用父类的构造函数,所以执行下面语句会抛异常:
>>> sb = SongBird()
>>> sb.sing()
Squawk!
>>> sb.eat()
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "D:/workshop/src/python/bird.py", line 5, in eat
if self.hungry:
AttributeError: SongBird instance has no attribute 'hungry'
(2)调用非绑定的父类构造函数
l 在子类的构造函数调用supperclass._init__(),由于是非绑定的,需要传递self
class SongBird(Bird):
def __init__(self):
Bird.__init__(self)
self.sound = 'Squawk!'
def sing(self):
print self.sound
l 这样就能正常调用eat()方法:
>>> sb = SongBird()
>>> sb.sing()
Squawk!
>>> sb.eat()
Aaaah...
(3) 使用supper()函数
l supper()只能在new-style类中使用:基类必须继承object
l 调用supper()时,将当前的类和实例作为参数传递,调用__init__()时不需要传递self:
class Bird(object):
def __init__(self):
self.hungry = 1
def eat(self):
if self.hungry:
print 'Aaaah...'
self.hungry = 0
else:
print 'No, thanks!'
class SongBird(Bird):
def __init__(self):
super(SongBird, self).__init__()
self.sound = 'Squawk!'
def sing(self):
print self.sound
l 使用supper()函数要比调用非绑定的父类构造函数更好,特别是多重继承时,只需要调用一次就行了
2、项目访问
l 为了使自己创建的类具有Sequence和Mapping的基本功能,可以实现下面的Magic方法:
Ø __len__(self):返回项目的数目,对于Sequence是元素个数,对于Mapping是key/value对的个数
Ø __getitem__(self, key):根据key返回值,对于Sequence,key为0~n-1(n为Sequence的长度,可以为负数),对于Mapping,key可以是任意值
Ø __setitem__(self, key, value):保存值value到key指定的地方(对可变对象可用)
Ø __delitem__(self, key):根据key删除值(对可变对象可用)
l 下面是一个实现的例子:
def checkIndex(key):
"""
Is the given key an acceptable index?
To be acceptable, the key should be a non-negative integer. If it
is not an integer, a TypeError is raised; if it is negative, an
IndexError is raised (since the sequence is of infinite length).
"""
if not isinstance(key, (int, long)): raise TypeError
if key<0: raise IndexError
class ArithmeticSequence(object):
def __init__(self, start=0, step=1):
"""
Initialize the arithmetic sequence.
start - the first value in the sequence
step - the difference between two adjacent values
changed - a dictionary of values that have been modified by
the user
"""
self.start = start # Store the start value
self.step = step # Store the step value
self.changed = {} # No items have been modified
def __getitem__(self, key):
"""
Get an item from the arithmetic sequence.
"""
checkIndex(key)
try: return self.changed[key] # Modified?
except KeyError: # otherwise...
return self.start + key*self.step # ...calculate the value
def __setitem__(self, key, value):
"""
Change an item in the arithmetic sequence.
"""
checkIndex(key)
self.changed[key] = value # Store the changed value
l 下面是调用的一些例子,由于没有实现__delitem__(),所以del操作会抛异常:
>>> s = ArithmeticSequence(1, 2)
>>> s[4]
9
>>> s[4] = 2
>>> s[4]
2
>>> del s[4]
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
AttributeError: __delitem__
3、继承内建类
l 上面为实现内建类具有的功能,需要逐个实现方法,其实可以直接继承这些内建的类,重载需要调整功能的方法:
class CounterList(list):
def __init__(self, *args):
super(CounterList, self).__init__(*args)
self.counter = 0
def __getitem__(self, index):
self.counter += 1
return super(CounterList, self).__getitem__(index)
l 下面是调用的一些例子:
>>> cl = CounterList(range(10))
>>> cl
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del cl[3:6]
>>> cl.counter
0
>>> cl[4] + cl[2]
9
>>> cl.counter
2