Python学习:定制类(实现一个类表现的很像一个list)

[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)// #/a/b/c/d

你可能感兴趣的:(Python学习:定制类(实现一个类表现的很像一个list))