Вход | Регистрация

Решение на трета задача

  • Thumbs_upThumbs_upThumbs_up

    Ето едно примерно решение - има много вариации, това е просто един пример.

    class Quaternion:
    
        def __init__(self, *args):
            if len(args) == 1 and not isinstance(args[0], (int, float)):
                self.__init__(*args[0])
            elif len(args) == 2:
                self.__coordinates = (args[0].real, args[0].imag, args[1].real, args[1].imag)
            else:
                self.__coordinates = tuple(args + (0, 0, 0, 0))[:4]
    
        def tuple(self):
            return self.__coordinates
    
        def __getitem__(self, index):
            return self.__coordinates[index]
    
        def __setitem__(self, index):
            raise TypeError
    
        def __getattribute__(self, attr):
            attrs = ['e', 'i', 'j', 'k']
            if attr in attrs: return self[attrs.index(attr)]
            if attr == 'scalar': return self[0]
            if attr == 'vector': return Quaternion(0, *self[1:])
            return object.__getattribute__(self, attr)
    
        def __setattr__(self, attr, value):
            if attr in ['e', 'i', 'j', 'k', 'scalar', 'vector']: raise TypeError
            return object.__setattr__(self, attr, value)
    
        def __eq__(self, other):
            return tuple(self) == tuple(Quaternion(other))
        
        def __add__(self, other):
            return Quaternion(*map(sum, zip(self, Quaternion(other))))
    
        __radd__ = __add__
    
        def __neg__(self):
            return self * -1
    
        def __sub__(self, other):
            return self + (-other)
    
        def __rsub__(self, other):
            return (-self) + other
    
        def __mul__(self, other):
            q1, q2 = self, Quaternion(other)
            return Quaternion(q1.e*q2.e - q1.i*q2.i - q1.j*q2.j - q1.k*q2.k,
                              q1.e*q2.i + q1.i*q2.e + q1.j*q2.k - q1.k*q2.j,
                              q1.e*q2.j - q1.i*q2.k + q1.j*q2.e + q1.k*q2.i,
                              q1.e*q2.k + q1.i*q2.j - q1.j*q2.i + q1.k*q2.e)
    
        __rmul__ = __mul__
    
        def __truediv__(self, other):
            return self * (1/other) 
    
        def __invert__(self):
            return self.scalar - self.vector
    
        def __abs__(self):
            return (self * ~self).e ** 0.5
    
        def unit(self):
            return self / abs(self)
    
        def reciprocal(self):
            return ~self / (abs(self) ** 2)
    
        def __pow__(self, other):
            if other == 1: return self
            return self ** (other - 1) * self
    
        def __hash__(self):
            return hash(tuple(self))
    
        def __bool__(self):
            return self != Quaternion()
    
        def __str__(self):
            return '{0}{1:+}i{2:+}j{3:+}k'.format(*self)
    
        def __repr__(self):
            return 'Quaternion{0}'.format(tuple(self))
    
    Quaternion.e = Quaternion(1, 0, 0, 0)
    Quaternion.i = Quaternion(0, 1, 0, 0)
    Quaternion.j = Quaternion(0, 0, 1, 0)
    Quaternion.k = Quaternion(0, 0, 0, 1)

    Заб. вместо

    for attr, val in zip('eijk', self): object.__setattr__(self, attr, val) # in __init__ и
    
    scalar = property(lambda self: self.e)
    vector = property(lambda self: Quaternion(0, *self[1:]))

    може да се откоментира __getattribute__

    06.04.2009 (променeно 06.04.2009)
  • Здрасти,

    Не че искам да се заяждам, ама защо в слайдовете пише че __nonzero__(self) се използва за конвертиране към булев тип? Гледам ти използваш __bool__. Надявам се до другата година да го оправите и в слайдовете.

    ПП Ако сте го споменавали на лекции, се извинявам за този постинг. Тогава грешката си е у мене, че не съм присъствал

    Поздрави, Павел

    06.04.2009 (променeно 06.04.2009)
  • Да на лекцията го пишеше (nonzero), после го fix-нах (може би един ден след публикуването на лекцията, мързи ме да гледам svn лога за точно кога).

    P.S. в "hyper thread-a" за трета по някое време го имаше

    06.04.2009 (променeно 07.04.2009)
  • Хареса ми това, че имплементираш "подробно" само __add__ и __mul__, а всички останали операции изразяваш алгебрично чрез тях.

    Само една забележка: Quaternion(1,2,3,4) ** 0 == Quaternion(1).

    06.04.2009 (променeно 06.04.2009)
  • Само една забележка: Quaternion(1,2,3,4) ** 0 == Quaternion(1).

    Няма нужда - "** - Повдигане на степен (като втори параметър на ** винаги е int >= 1)"

    07.04.2009
  • Thumbs_up

    Да прав си, все пак вие пишете условията =-)

    07.04.2009
  • Thumbs_up

    Трябваше да дадем кватернион на степен кватернион, голям пропуск.

    07.04.2009
  • Трябваше да дадем кватернион на степен кватернион, голям пропуск.

    Едва ли е еднозначна функция. Ама можеше exp(q) да дадете :)

    07.04.2009 (променeно 07.04.2009)
  • Хм, прав си. И все пак си е пропуск :)

    07.04.2009