Vector 버전 #3: 동적 속성 접근

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

Fluent Python

목록 보기
69/130

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

객체지향 상용구

Vector 버전 #3: 동적 속성 접근

Vector2d에서 Vector로 진화하면서 v.x, v.y처럼 벡터 요소를 이름으로 접근하는 능력을 상실했지만 @prperty 데커레이터를 이용해서 x와 y에 읽기 전용 접근을 제공하여 Vector에 네 개의 프로피터를 작성할 수도 있지만, 그 과정은 지루하고 getattr() 특별 메서드를 이용하면 더 깔끔하게 구현이 가능하다.

속성을 찾지 못하면 인터프리터는 getattr()메서드를 호출하여 my_obj.x 표현식이 주어지고, 파이썬은 my_obj 객체에 x 속성이 있는지 검사하고 없다면, 이 객체의 클래스에서 더 검색하고 상속 그래프를 따라 계속 올라간다.

#vector_v3.py의 일부: vector_v2.py의 Vector 클래스에 추가된 __getattr__()메서드

shortcut_names = 'xyzt'

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

인터프리터는 단지 v,x에 바인딩된 값 10을 반환하고 우리가 구현한 getattr()은 shortcut_names에 나열된 가상 속성의 값을 가져오기 위해서 self._components 이외의 다른 속성에는 주의를 기울이지 않고, 이런 불이치 문제를 해결하려면 Vector 클래스에서 속성값을 설정하는 부분의 논리를 수정해야 한다.


#vector_v3.py의 일부: Vector 클래스에 추가된 __setattr__()메서드

def __setattr__(self, name, value):
	cls = type(self)
    if len(name) == 1:
    	if name in cls.shortcut_names:
        	error = 'readonly attribute {attr_name!r}'
        elif name.islower():
        	error = "can't set attributes 'a' to 'z' in {cls_name!r}"
        else:
        	error = ''
        if error:
        	msg = eeror.format(cls_name=cls.__name__, attr_name = name)
            raise AttributeError(msg)
    super().__setattr__(name, value)

AttributeError와 함께 출력할 에러 메시지를 선택하는 동안 내장된 complex 형의 동작을 조사했고, complex 형이 불변형이며 real과 imag, 두 개의 데이터 속성을 가지고 있으므로 complex 형의 두 속성 중 하나를 변경할 때 "속성을 설정할 수 없습니다" 라는 메시지와 함께 AttributeError가 발생했다.

프로퍼티로 보호한 읽기 전용 속성을 설정할 때는 읽기 전용 속성이라는 에러 메시지가 나오고, 이 두 메시지에서 영감을 얻어 setattr()에 사용할 에러 메시지를 정했지만 금지된 속성을 더욱 명확히 보인다.


Vector 요소에 저장하는 기능을 지원하진 않지만, 이 예제에서 알 수 있는 중요한 것이 있다.


객체 동작의 불일치를 피하려면 _Getattr()을 구현할 때 setattr()도 함께 구현해야 하고 , 벡터 요소의 변경을 허용하고 싶은 경우, setitem() 메서드를 구현하면 v[0] = 1.1의 형태로, setattr__() 메서드를 구현하면 v,x=1,1로 작성할 수 있다.

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

0개의 댓글