zoukankan      html  css  js  c++  java
  • Python Slice对象到Sequence序列对象

    问题背景

    最近在攻Numpy包,发现以下特别让我很疑惑,因为从python基础而来,终将又回到python中去:

    import  numpy as np
    a = np.array([1,2,3,4])
    b = a[1:2] 
    c = a[1]
    
    print('the type of b is:{},value is {}'.format(type(b),b)) #
    print('the type of c is:{},value is {}'.format(type(c),c))
    
    output:
    the type of b is:<class 'numpy.ndarray'>,value is [2] 
    the type of c is:<class 'numpy.int64'>,value is 2
    
    • b、c数据类型分别为ndarray类、int类,value上b多了一个中括号;
    • 经列表进行切片(slice)以及索引以后,返回不同的对象,分别是列表 list、 integer,在经过查询python doc以后发现这其中存在slice对象 slice对象
      • Slice对象:创建方式:Slice(start,stop,step) 或者 var[start:stop:step] 中间使用冒号,代表var对象内部中在使用Slice对象;
      • 不过在此之前需要提出一点:像序列sequence(元组、列表、字符、slice)都是通过方法__getItem__方法通过整数索引对元素进行访问,slice也是如此。以下是自定义序列(当然协议实现协议还需要有__len__,不过此处用不到)。
    d =slice(1,4,1) # 1 2 3 返回3个元素
    a = [1,2,3,4]
    c = a[d]  #取3个元素 #list列表的索引只能为int或slice对象 否则出现: TypeError: list indices must be integers or slices, not list 
    c1 = a[1:4:1] #a作为列表,使用a:b:c这种索引在内部会产生像上述 同样的slice对象
    print(c) # 2,3,4
    print(c1) # 2,3,4
    
    #list索引接受索引整数和slice对象时分别返回对象是integer、 list对象。这就可以解释在numpy中np.array[1:2] 与np.array[1]维度分别是
    a = [1,2,3,4] 
    b = a[1] # b 返回值:1
    c = slice(1)
    a[c] #返回值:[1] 将slice对象c传入到a中所谓索引,返回[1] 与a[1:2]一致。
    

    切片与__getitem__方法联系

    • [start:stop:step] 在python中就涉及到了切片操作 传递给__getitem__方法分别对应不同的参数,当索引是integer的时候,序列将索引当作元素在序列中位置,直接取数,涉及到切片的时候按照以下进行:
    class Demo():
        def __getitem__(self, item):
            return item
    de =Demo()
    de[1]  # Out[3]: 1  整数索引 返回元素
    de[1,2,3] # Out[4]: (1, 2, 3) 索引中存在逗号,返回元组
    de[1:3:1] # Out[5]: slice(1, 3, 1) 索引中存在冒号: 返回slice对象
    

    穿插点:slice对象、sequence对象

    Slice对象:

    • 在官方定义中,Slice对象经常包含序列的一部分,这样肯定不太理解,换个说法,在方括号中 数字之间有冒号,这里面就存在切片 slice
    • 生成Slice类,slice(start,stop,step),或者slice(stop),上述例子已经给出,此处再多余说一个slice类的方法,indices(len)返回一个元组(start,stop,step)用于规整slice类中对于超出start、stop、step所定义区间的范围,换句话说超出区间的会被截掉:
    slice(1,10).indices(5) 等同于 slice(1:5:1) 
    slice(-2,None,None).indices(6) 等同于 slice(4,6,1),处理负数索引
    'ABCDEFGH'[-3:20:1] 字符串总共长度只有8,索引内stop为20,超出长度,负数为逆序索引,正序索引即为长度+负数索引,step不变,所以前面切片等同于'ABCDEFGH'[5:8:1]
    

    sequence对象

    • python中奉行一切皆对象,也存在许多鸭子类型,对于序列对象也不例外,只要实现了序列接口协议,我们也可以将其当作自定义序列对象:实现了__getitem__以及__len___
    • 当初也是在研究list[index]的时候看python发生了什么,后来了解到当使用 x[key]的时候,内部就会调用x.getitem(key)这一特殊方法,所以接下来需要去深入__getitem__ 方法
    from array import array 
    import numbers
    
    class Demo():
          def __init__(self,temp):
                self.__temp = array.array('i',temp) #其中i作为typecode,代表初始化数组的数据类型是整型
          def __getitem__(self,index): 
                if isinstince(index,slice): #index是slice对象
                      return self.__class__(self.__temp[index])
                elseif isinstance(index,number.integral): #索引是整数 ,至于为何使用numbers.Integral 将在下文中作出解释
                      return slef.__temp[index]
                else:
                      msg = '{cls.__name} indices must be integers' 
                      raise TypeError(msg.format(cls=cls))
          def __len__(self):
                return len(self.__temp)
    de = Demo(range(7))
    de[1:3:1]  # Out: <__main__.Demo at 0x10ffffd68>  # 索引为slice对象的时候,返回Demo实例,无论是list还是numpy中的array,当其索引是slice的时候,返回均是其实实例(slice对象)
    de[slice(1,3,1)] # Out: <__main__.Demo at 0x110013ef0> # 
    de[1] # Out: 1 #整数索引,返回对应位置元素值
    de['s'] # TypeError: Demo indices must be integers #非法索引 报错
    
    

    番外知识点

    +上述代码中使用了isinstance,一般来说我们是检查是否存在继承关系,在查看模块number.integral以及int类源代MRO关系如下:

    import  numbers
    import inspect
    
    print(inspect.getmro(numbers.Integral))  # (<class 'numbers.Integral'>, <class 'numbers.Rational'>, <class 'numbers.Real'>, <class 'numbers.Complex'>, <class 'numbers.Number'>, <class 'object'>)
    print(inspect.getmro(int)) # (<class 'int'>, <class 'object'>)
    
    • 在模块number中的integral类属于抽象类,因为Number继承自元类ABC,在integral源代码末尾将int注册为它的虚拟子类,这样int就可以去实现integral类中所定义的方法。官方对于虚拟子类重写isinstance方法
    • 所以isinstance也不只是检查继承,还有抽象类虚拟子类之间的关系。
  • 相关阅读:
    1058
    light oj 1067 费马小定理求逆元
    HDU 1022
    贪心
    HDU 4994 博弈。
    HDU 5234 背包。
    CodeForces 327B 水题。
    vue的$nextTick使用总结,this.$refs为undefined的解决办法,element Ui的树形控件setCheckedKeys方法无法使用
    Object.assign的用法
    react + antd 实现打印功能(踩了不少坑)
  • 原文地址:https://www.cnblogs.com/ivan09/p/14206409.html
Copyright © 2011-2022 走看看