美文网首页
__getitem__

__getitem__

作者: SingleDiego | 来源:发表于2018-03-26 15:32 被阅读35次

    上一篇的 Fib 实例虽然能作用于 for 循环,看起来和 list 有点像,但是,把它当成 list 来使用还是不行,比如,取第5个元素:

    >>> Fib()[5]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'Fib' object does not support indexing
    

    要表现得像 list 那样按照下标取出元素,需要实现 __getitem__() 方法。

    先用最简单的例子看看 __getitem__() 方法的用法:

    class Fib(object):
        
        def __getitem__(self, n):
            return n*n
    

    测试:

    >>> f = Fib()
    >>> f[1]
    1
    
    >>> f[5]
    25
    

    接下来我们实现斐波拉契数列:

    class Fib(object):
        def __getitem__(self, n):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
    

    现在,就可以按下标访问数列的任意一项了:

    >>> f = Fib()
    >>> f[0]
    1
    >>> f[1]
    1
    >>> f[2]
    2
    >>> f[3]
    3
    >>> f[10]
    89
    >>> f[100]
    573147844013817084101
    

    但是 Fib 还不能像 list 那样使用切片操作,原因是 __getitem__() 传入的参数可能是一个 int,也可能是一个切片对象 slice,所以要做判断:

    class Fib(object):
        
        def __getitem__(self, n):
            
            if isinstance(n, int): # n是索引
                a, b = 1, 1
                for x in range(n):
                    a, b = b, a + b
                return a
            
            if isinstance(n, slice): # n是切片
                start = n.start
                stop = n.stop
                if start is None:
                    start = 0
                a, b = 1, 1
                L = []
                
                for x in range(stop):
                    if x >= start:
                        L.append(a)
                    a, b = b, a + b
                return L
    

    现在试试 Fib 的切片:

    >>> f = Fib()
    >>> f[0:5]
    [1, 1, 2, 3, 5]
    
    >>> f[:10]
    [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
    

    但是没有对 step 参数作处理,也没有对负数作处理,所以,要正确实现一个 __getitem__() 还是有很多工作要做的。

    此外,如果把对象看成 dict__getitem__() 的参数也可能是一个可以作 keyobject,例如 str

    与之对应的是 __setitem__() 方法,把对象视作 listdict 来对集合赋值。最后,还有一个 __delitem__() 方法,用于删除某个元素。

    总之,通过上面的方法,我们自己定义的类表现得和 Python 自带的 listtupledict 没什么区别,这完全归功于动态语言的“鸭子类型”,不需要强制继承某个接口。

    相关文章

      网友评论

          本文标题:__getitem__

          本文链接:https://www.haomeiwen.com/subject/rljrcftx.html