vector的多维版本

1.一行代码实现如下功能

        #方式一
        # if len(self) != len(other):
        #     return False
        # for a, b in zip(self, other):
        #     if a != b:
        #         return False
        # return True
        #方式二
        return len(self) == len(other) and all(a == b for a, b in zip(self, other))

2.多维

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


class Vector:
    typecode = 'd'
    shortcut_name = 'xyzt'

    def __init__(self, components):
        '''类外直接拿到属性'''
        self._components = array(self.typecode, components)

    def __iter__(self):
        '''返回可迭代的对象'''
        return iter(self._components)

    def __str__(self):
        return str(tuple(self))

    def __repr__(self):
        # 获得有限的长度
        components = reprlib.repr(self._components)
        components = components[components.find('['):-1]
        return 'Vector({})'.format(components)

    def __bytes__(self):
        return bytes([ord(self.typecode)]) + bytes(self._components)

    def __abs__(self):
        return math.sqrt(sum(i * i for i in self))

    def __bool__(self):
        return bool(abs(self))

    @classmethod
    def frombytes(cls, octets):
        typecode = chr(octets[0])
        memv = memoryview(octets[1:]).cast(typecode)
        return cls(memv)

    def __len__(self):
        return len(self._components)

    def __getitem__(self, index):
        cls = type(self)
        if isinstance(index, slice):
            return cls(self._components[index])
        elif isinstance(index, numbers.Integral):
            return self._components[index]
        else:
            msg = '{cls.__name__} indices must be integers'
            return TypeError(msg.format(cls))

    def __getattr__(self, name):
        cls = type(self)
        if len(name) == 1:
            pos = self.shortcut_name.find(name)
            if 0 <= pos <= len(cls.shortcut_name):
                return self._components[pos]
        msg = '{.__name__!r}  has not attribute {!r}'
        raise AttributeError(msg.format(cls, name))

    def __setattr__(self, name, value):
        '''
        1.解决vector修改xyzt属性的问题
        2.设置a to z的属性问题
        3。继承父类的setattr的方法
        '''
        cls = type(self)
        if len(name) == 1:
            if name in cls.shortcut_name:
                error = 'readonly attribute {attr_name!r}'
            elif name.islower():
                error = "can't set attribute 'a' to 'z' {cls_name!r}"
            else:
                error = ''
            if error:
                msg = error.format(attr_name=name, cls_name=cls.__name__)
                raise AttributeError(msg)
        super().__setattr__(name, value)

    def __eq__(self, other):
        # 方式一
        # if len(self) != len(other):
        #     return False
        # for a, b in zip(self, other):
        #     if a != b:
        #         return False
        # return True
        # 方式二
        return len(self) == len(other) and all(a == b for a, b in zip(self, other))

    def __hash__(self):
        hashes = (hash(x) for x in self._components)
        return functools.reduce(operator.xor, hashes)

    def angle(self, n):
        r = math.sqrt(sum(x * x for x in self))
        a = math.atan2(r, self[n - 1])
        if (n == len(self) - 1) and (self[-1] < 0):
            return math.pi * 2 - a
        else:
            return a

    def angles(self):
        return (self.angle(n) for n in range(1, len(self)))

    def __format__(self, format_spec):
        if format_spec.endswith('h'):
            format_spec = format_spec[:-1]
            coords = itertools.chain([abs(self)], self.angles())
            outer_fmt = "<{}>"
        else:
            coords = self
            outer_fmt = "({})"
        components = (format(i, format_spec) for i in coords)
        return outer_fmt.format(' ,'.join(components))

 

posted @ 2019-11-20 14:35  烧刘病  阅读(203)  评论(0编辑  收藏  举报
回到页首