Vector 버전 #1: Vector2d 호환

매일 공부(ML)·2023년 1월 17일
0

Fluent Python

목록 보기
66/130

객제지향 상용구

시퀀스,해킹, 해시, 슬라이스

Vector 버전 #1: Vector2d 호환

Vector 생성자는 Vector2d 생성자와 호환되지 않도록 설계하여, init() 메서드에서 임의의 인수 *args를 받아서 Vector(3,4) 나 Vector(3,4,5)형태로 작동하게 만들 수 있으나 시퀀스 생성자는 내장 시퀀스처럼 반복형을 인수로 받게 만드는 것이 좋다.

#Vector.__init__ , Vector.__repr__() 테스트

Vector([3.1, 4.2])
Vector((3,4,5))
Vector(range(10))

생성자 시그니처가 달라진 점 외에 요소 두 개를 가진 Vector 클래스는 Vector2로 수행했던 모든 테스트와 동일한 결과가 나오도록 만들어졌다.


#vector_v1.py: vector2d_v1.py에서의 유도

from array import array
import reprlib
import math

class Vector:
	typecode = 'd'
    
    def __init__(self, components):
    	self._components = array(self.typecode, 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([ird(self.typecode)]) + 
        		bytes(self._components))
                
                
    def __eq__(self,other):
    	return tuple(self) == tuple(other)
        
    def __abs__(self):
    	return math.sqrt(sum(x * x for x 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)

reprlib.repr()을 사용한 방법을 자세히 설명하면, 이 함수는 생략 기호를 이용해서 생성할 문자열의 길이를 제한하므로 대형 구조체나 재귀적 구조체도 안전하게 표현하고, repr()이 Vector객체를 배열의 형태로 사용하여 구현 내용을 외부로 노출하지 않길 원한다.


repr()을 구현할 때, reprlib.repr(list(self._components))문장으로 components를 간략히 출력할 순 있으나 시간소요가 많으므로 바깥쪽에 글자들을 잘라낸다.


생성자가 호환되지 않으므로 상속받는 것은 좋지 않고, init()에서 매개변수를 영리하게 처리해서 이 문제를 해결할 수 있지만, 두 번째가 더 중요하고 Vector클래스가 시퀀스 프로토콜을 구현하는 독자적이길 원한다.

profile
성장을 도울 아카이빙 블로그

0개의 댓글