[0]所谓的定制类,就是自己定义许多__xxx__
方法,这样的方法都是有特殊用途的,比如__len__()
的作用就是让这个类可以作用于len(object)函数。
[1]定制__str__和__repr__
,这两个方法分别是用于print和直接打印变量的,如果有这两个方法的话,就会调用它们.为了直接获得类内部一些比较有用的数据信息,我们返回一些比较重要的属性.
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name: %s)' % self.name
__repr__ = __str___
>>> print(Student('Michael'))
Student object (name: Michael)
[2]:定制__iter__和__next__,
这是为了让这个类成为一个可以迭代的对象.用于for循环.为了获得这个属性,我们必须写两个方法,next用于获得下一个数据,iter用来返回类里面的可迭代对象(可能是它自己):举例,一个fib类:for循环不断调用next获得下一个对象
class fib():
def __init__(self):
self.a,self.b = 0,1
def __iter__(self):
return self
def __next__(self):
if(self.a>10**4):
raise StopIteration()
self.a ,self.b = self.b,self.a+self.b
return self.a
def __str__(self):
return self.a
for i in fib():
print(i)
但是,我们的程序并不完善,因为一旦遍历完了fib,就不能遍历第二次了,因此我们需要修改:
def __next__(self):
if(self.a>10**4):
self.a,self.b = 0,1
raise StopIteration()
self.a ,self.b = self.b,self.a+self.b
return self.a
[3]__getitem__
:从名字就很容易得知,这是为了让我们的类表现的像list一样,可以直接用[i]提取第i个元素;
def __getitem__(self,n):
a,b = 1,1
for i in range(n):
a,b = b,a+b
return a
注意,这样没有检测参数,为了贴近list,作如下修改:
def __getitem__(self,n):
a,b = 1,1
if(type(n)!=int):raise ValueError('the n must be an integer')
if(n<0):raise IndexError('the index must be positive')
if(n>10**4): raise IndentationError('the index is too large')
for i in range(n):
a,b = b,a+b
return a
[4]注意到list还有一个silce方法,可以L[:3],所以我们还需要对getitem的参数添加更多的判断
def __getitem__(self,n):
a,b = 1,1
if(type(n) == int):
if(n<0):raise IndexError('the index must be positive')
if(n>10**4): raise IndentationError('the index is too large')
for i in range(n):
a,b = b,a+b
return a
if(type(n) == slice):
L = []
start = n.start if(n.start!=None) else 0
end = n.stop
step = n.step if(n.step!=None) else 1
if(type(start)!=int or type(end)!=int or type(step)!=int): raise IndentationError('slice indices must be integers or None')
if(start<0 or end < 0):raise IndexError('the index must be positive ')
if((end-start)*step < 0) return []
for i in range(min(start,end),max(start,end)):
L.append(a)
a,b = b,a+b
return L[start:end:step]
以上这段代码实现了list切片的一部分功能,比如[a:b:step]的所有情况,利用了list本身的方法来判断是返回[]还是进行倒序,或者其他的计算.同时仔细的进行了对参数类型的判断.
[5]__getattr__
方法,当你的类某些属性不存在的时候,判断是否要动态返回该属性.比如下面的代码,不管属性怎么变,我们都可以返回相应的路径.
class Chain(object):
def __init__(self, path=''):
self._path = path
def __getattr__(self, path):
print('now call :%s'%self._path)
return Chain('%s/%s' % (self._path, path))
def __str__(self):
return self._path
__repr__ = __str__
f=Chain()
print(f.a.b.c.d)//