首页 > 其他 > 详细

序列的修改、散列和切片

时间:2019-03-24 15:59:24      阅读:156      评论:0      收藏:0      [点我收藏+]

Vector第1版(不可切片版):

 

from array import array
import reprlib
import math


class Vector:

    type_code = d

    def __init__(self,components):

        self._components = array(self.type_code,components)

    def __iter__(self):
        return iter(self._components)


    def __repr__(self):
        components = reprlib.repr(self._components)
        components = components[components.find([):-1]
        return Vector({}).format(components)

    def __str__(self):

        return str(tuple(self))

    def __bytes__(self):

        return bytes([ord(self.type_code)]) + bytes(self._components)

    def __eq__(self, other):

        return tuple(self) == tuple(other)

    def __abs__(self):

        return math.sqrt(x*x for x in self._components)

    def __bool__(self):

        return bool(abs(self))

    @classmethod
    def frombytes(cls,octets):

        t_code = chr(octets[0])
        comps = array(t_code)
        comps.frombytes(octets[1:])
        return cls(comps)


longlist = [i for i in range(100)]
longVector = Vector(longlist)
print(repr(longVector):,repr(longVector))

v = Vector([3.1,4.2])
print(str(v):,v)
print(repr(v):,repr(v))
b = bytes(v)
w = Vector.frombytes(b)
print(repr(w):,repr(w))
print(v == w)

输出:
repr(longVector): Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])
str(v): (3.1, 4.2)
repr(v): Vector([3.1, 4.2])
repr(w): Vector([3.1, 4.2])
True

 

Vector第2版(不完美切片版):

from array import array
import reprlib
import math


class Vector:

    type_code = d

    def __init__(self,components):

        self._components = array(self.type_code,components)

    def __iter__(self):
        return iter(self._components)


    def __repr__(self):
        components = reprlib.repr(self._components)
        components = components[components.find([):-1]
        return Vector({}).format(components)

    def __str__(self):

        return str(tuple(self))

    def __bytes__(self):

        return bytes([ord(self.type_code)]) + bytes(self._components)

    def __eq__(self, other):

        return tuple(self) == tuple(other)

    def __abs__(self):

        return math.sqrt(x*x for x in self._components)

    def __bool__(self):

        return bool(abs(self))

    @classmethod
    def frombytes(cls,octets):

        t_code = chr(octets[0])
        comps = array(t_code)
        comps.frombytes(octets[1:])
        return cls(comps)

    # 定义下面两个方法以后,Vector类就支持简单切片
    def __len__(self):
        return len(self._components)

    def __getitem__(self, idx):
        return self._components[idx]


l = [i for i in range(100)]
v = Vector(l)
print(repr(longVector):,repr(v))

# []操作符调用__getitem__
print(v[0],v[-1])

# _components是一个array,所以切片返回array
print(v[1:4])

输出:
repr(longVector): Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])
0.0 99.0
array(d, [1.0, 2.0, 3.0])

 

切片原理

  - 切片背后与slice对象和indices对象有关

  - 实际调用的是slice(start, stop, stride).indices(len)

    - 给定长度为len的序列,计算起始和结尾的索引,以及步幅。超出边界的索引会被截掉。

 

class MySeq:

    def __getitem__(self, item):
        return item

s = MySeq()
l = [1,2,3,4,5]

# 切片时传递给__getitem__的参数是slice对象
# 这里是slice(1, 4, None)
print(s[1:4])

# slice(1, 4, 2)
print(s[1:4:2])

# 在内置可迭代对象的__getitem__中,还要调用indices方法对start、stop、stride进行处理
# 步幅为正数,start=None自动替换成0
# stop超过len,自动替换成len
# (0, 5, 2)
print(slice(None, 10, 2).indices(5))
# 相应切片返回[1, 3, 5]
print(l[:10:2])


# 步幅=None,自动替换成1
# 步幅为正数,start=-3自动替换成len-3
# stop=None自动替换成len
# (2, 5, 1)
print(slice(-3, None, None).indices(5))
# 相应切片返回[3, 4, 5]
print(l[-3::])


# 步幅为负数,start=-3自动替换成len-3
# stop=None自动替换成-1
# (2, -1, -1)
print(slice(-3, None, -1).indices(5))
# 相应切片返回[3, 2, 1]
print(l[-3::-1])


# 从2开始,倒退到3,切片为空
# (2, 3, -1)
print(slice(-3, 3, -1).indices(5))
# 相应切片返回[]
print(l[-3:3:-1])

 

Vector第3版(完美切片版):

 

from array import array
import reprlib
import math
import numbers

class Vector:

    type_code = d

    def __init__(self,components):

        self._components = array(self.type_code,components)

    def __iter__(self):
        return iter(self._components)


    def __repr__(self):
        components = reprlib.repr(self._components)
        components = components[components.find([):-1]
        return Vector({}).format(components)

    def __str__(self):

        return str(tuple(self))

    def __bytes__(self):

        return bytes([ord(self.type_code)]) + bytes(self._components)

    def __eq__(self, other):

        return tuple(self) == tuple(other)

    def __abs__(self):

        return math.sqrt(x*x for x in self._components)

    def __bool__(self):

        return bool(abs(self))

    @classmethod
    def frombytes(cls,octets):

        t_code = chr(octets[0])
        comps = array(t_code)
        comps.frombytes(octets[1:])
        return cls(comps)

    # 定义下面两个方法以后,Vector类就支持简单切片
    def __len__(self):
        return len(self._components)

    def __getitem__(self, idx):

        cls = type(self)

        if isinstance(idx,slice):
            # 把slice对象传递给_components的__getitem__函数
            return cls(self._components[idx])
        elif isinstance(idx,numbers.Integral):
            # 直接返回相应元素
            return self._components[idx]
        else:
            msg = {0} indices must be integers
            raise TypeError(msg.format(cls.__name__))


l = [i for i in range(100)]
v = Vector(l)
print(repr(longVector):,repr(v))

# 传入整数,__getitem__返回相应元素
print(v[0],v[-1])

# 经过改造后,切片返回Vector对象
print(repr(v[1:4]))

 

Vector第4版(带hash版):

from array import array
import reprlib
import math
import numbers
import functools
import operator

class Vector:

    type_code = d

    def __init__(self,components):

        self._components = array(self.type_code,components)

    def __iter__(self):
        return iter(self._components)


    def __repr__(self):
        components = reprlib.repr(self._components)
        components = components[components.find([):-1]
        return Vector({}).format(components)

    def __str__(self):

        return str(tuple(self))

    def __bytes__(self):

        return bytes([ord(self.type_code)]) + bytes(self._components)

    def __eq__(self, other):

        # zip生成一个由元组构成的生成器,在Vector由大数据量的可迭代对象构成时,效率比较高
        # all函数在每一个元素都为True时返回True
        return len(self)==len(other) and all(a==b for a,b in zip(self,other))

    def __hash__(self):

        # reduce接受三个参数,第一个参数是一个可接受两个参数的函数
        # 第二个参数是一个可迭代对象,第三个参数是初始值,如果可迭代对象为空,返回这个初始值
        hashes = (hash(i) for i in self)
        return functools.reduce(operator.xor, hashes, 0)

    def __abs__(self):

        return math.sqrt(x*x for x in self._components)

    def __bool__(self):

        return bool(abs(self))

    @classmethod
    def frombytes(cls,octets):

        t_code = chr(octets[0])
        comps = array(t_code)
        comps.frombytes(octets[1:])
        return cls(comps)

    # 定义下面两个方法以后,Vector类就支持简单切片
    def __len__(self):
        return len(self._components)

    def __getitem__(self, idx):

        cls = type(self)

        if isinstance(idx,slice):
            # 把slice对象传递给_components的__getitem__函数
            return cls(self._components[idx])
        elif isinstance(idx,numbers.Integral):
            # 直接返回相应元素
            return self._components[idx]
        else:
            msg = {0} indices must be integers
            raise TypeError(msg.format(cls.__name__))

    shortcut = xyzt

    # 动态存取属性
    def __getattr__(self, item):
        cls = type(self)
        if len(item) == 1:
            pos = cls.shortcut.find(item)
            if 0 <= pos < len(self._components):
                return self._components[pos]
            else:
                raise AttributeError({0} has no attribute {1}.format(cls,item))


l = [3.1, 4.2]
v = Vector(l)
print(repr(v):,repr(v))

print(v.x:,v.x)

print(hash(v):,hash(v))

输出:

repr(v): Vector([3.1, 4.2])
v.x: 3.1
hash(v): 384307168202284039

 

序列的修改、散列和切片

原文:https://www.cnblogs.com/StackNeverOverFlow/p/10561741.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!