728x90
from array import array
import math


class Vector2d:
    typecode = 'd'

    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)

    def __iter__(self):
        return (i for i in (self.x, self.y))

    def __repr__(self):
        class_name = type(self).__name__
        return '{}({!r}, {!r})'.format(class_name, *self)

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

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

    def __eq__(self, other):
        return tuple(self) == tuple(other)

    def __abs__(self):
        return math.hypot(self.x, self.y)

    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)

"""
클래스 메서드에는 @classmethod 데커레이터가 붙는다.
self 매개변수가 없다. 대신 클래스 자신이 cls 매개변수로 전달된다.
첫 번째 바이트에서 typecode를 읽는다.
octets 이진 시퀸스로부터 momoryview를 생성하고 typecode를 이용해서 형을 변환한다.
cast()가 반환한 memoryview를 언패킹해서 생성자에 필요한 인수로 전달한다.
"""
v1 = Vector2d(3, 4)
print(v1.x, v1.y)
x, y = v1

print(x, y)
print(v1)
v1_clone = eval(repr(v1))

print(v1 == v1_clone)
print(v1)
octets = bytes(v1)

print(octets)
print(abs(v1))
print(bool(v1), bool(Vector2d(0, 0)))

 

  1. typecode 는 Vector2d와 bytes 간의 변환에 사용하는 클래스 속성이다._
  2. _init__() 안에서 x 와 y를 float로 변환하면 부적절한 인수로 Vector2d 객체를 생성하는 경우 조기에 에러를 잡는 데 도움이 된다.
  3. __iter__() 를 구현하면 Vector2d를 반복할 수 있게 된다. 그렇기 때문에 x, y = my_vector 문장으로
    언패킹할 수 있었다. 이 메서드는 제너레이터 표현식을 이용해서 요소를 차례대로 하나씩 생성한다.

  4. __repr__()은 {!r}을 각 요소에 repr()을 호출해서 반환된 문자열로 치환해 문자열을 만든다.
    vector2d를 반복할 수 있으므로, *self는 format()에 x 와 y속성 을 공급한다.

  5. 반복형 Vector2d에서 튜플을 만들어 순서쌍으로 출력하는 것은 간단하다.
    bytes를 생성하기 위해 typecode를 bytes로 변환한다. 그리고 이것을

  6. 객체를 반복해서 생성한 배열에서 bytes와 연결한다.

  7. 모든 속성을 비교하기 위해 피연산자로부터 튜플을 생성한다. Vector2d 객체를 피연산자로 사용하면 작동하지만,
    문제가 있다. (CAUTION) 참조

  8. magnitude ()는 x 와 y 로 만들어진 직삼각형의 사변의 길이다.

  9. __bool__()은 abs(self)를 사용해서 사변 길이를 계산하고 불리언 형으로 변환한다. 따라서 0.0은 False이고
    그 외 값은 True이다.

CAUTION : __eq__() 메서드는 Vector2d 객체를 피연산자로 사용하면 작동한다.
또한 동일한 숫자값을 가진 어떠한 반복형 객체도 Vector2d 객체와 비교하면 True를 반환한다.
예를들어 Vector(3, 4) == [3, 4]) 이것은 기능일 수도 있고 버그일 수도 있다.

 

728x90

'Python > python - pythonic' 카테고리의 다른 글

Decorator  (0) 2020.12.07
데코레이터를 이해하기전 알아야 할것들  (0) 2020.12.06
WeakValueDictionary 촌극  (0) 2020.12.04
약한참조  (2) 2020.12.02
del 과 가비지 컬렉션  (0) 2020.12.02