OOP getter and setter

게터 세터는 속성과 관련된 메소드 encapsulation을 하기 위함! 감기약 캡슐안에 뭐가 들었는진 모르지만 믿고 먹는것 마냥 캡슐을 만들어 보쟈

vector element

v = (0, 1, 2)라는 벡터의 v0(첫번째)에 3을 넣어라 하면

1
2
3
4
5
6
>>> x = Vector(0,1,2)
>>> print (x[0])
0
>>> x.vec[0] = 3
>>> x
Vector(3,1,2)

vector라는 것을 만들고, 그의 타입이 리스트이기에 그 0번째 element에 3을 넣어야함 너무 자세히 알아야 하는거 아님? ㅇㅅㅇ

vector의 0번째에 있는 element의 값을 가져와서 확인하고, 변경하고 싶따

  • 값을 얻는 경우 : get
  • 값을 변경하는 경우 : set

get을 하는게 getter set을 하는게 setter

getter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import math
class Vector:
    def __init__(self,lst):
        self.vec = list(lst)
    def __repr__(self):
        return "Vector({})".format(self.vec)
    def __add__(self,other):
        x = self.vec
        y = other.vec
        if len(x) != len(y):
            print("Error")
            return None
        return Vector([x[i] + y[i] for i in range(len(self.vec))])
    def __sub__(self,other):
        x = self.vec
        y = other.vec
        if len(x) != len(y):
            print("Error")
            return None
        return Vector([x[i] - y[i] for i in range(len(self.vec))])
    def size(self):
        return math.sqrt(sum([x**2 for x in self.vec]))
x = Vector((0,1,2))
x[0]

TypeError Traceback (most recent call last)

in () 22 return math.sqrt(sum([x**2 for x in self.vec])) 23 x = Vector((0,1,2)) ---> 24 x[0] TypeError: 'Vector' object does not support indexing 파라미터를 주면 그걸 읽어오는 작업을 하는 getter 메소드를 정의해야함 ```python def __getitem__(self,key): return self.vec[key] ``` 를 추가하고 다시 실행해보면 0이라고 정확히 나옴
### setter ``` python import math class Vector: def __init__(self,lst): self.vec = list(lst) def __repr__(self): return "Vector({})".format(self.vec) def __add__(self,other): x = self.vec y = other.vec if len(x) != len(y): print("Error") return None return Vector([x[i] + y[i] for i in range(len(self.vec))]) def __sub__(self,other): x = self.vec y = other.vec if len(x) != len(y): print("Error") return None return Vector([x[i] - y[i] for i in range(len(self.vec))]) def __getitem__(self,key): return self.vec[key] def size(self): return math.sqrt(sum([x**2 for x in self.vec])) x = Vector((3,1,2)) x[0] = 10 x ``` > TypeError Traceback (most recent call last) in () 25 return math.sqrt(sum([x**2 for x in self.vec])) 26 x = Vector((3,1,2)) ---> 27 x[0] = 10 TypeError: 'Vector' object does not support item assignment assignment하는 기능이 엄쪄라고 에러가 난다 ``` python def __setitem__(self,key,val): self.vec[key] = val ``` setter 메소드 추가 ``` python x = Vector((3,1,2)) x[0] = 10 x ``` > Vector([10, 1, 2])
## Encapsulation Vector 라는 리스트 타입의 클래스를 만들어서 여러가지 리스트 비슷한 기능들을 제공함 원칙: 사용자가 알아야하는 저보의 양을 가능한 줄이는 것이 좋음 접근 방법: 사용자가 이미 알고 있는 내용으로 충분히 유추할 수 있도록 이미 알고 있던 연산자, 남들이 많이 쓰는 메소드 방법과 동일하게 만들기 e.g. python의 [] operator의 동작으로 Vector의 동작을 예측할 수 있도록함 관용적으로 사용자가 몰라도 되는 attribute는 '\_vec' 등 밑줄로 시작되는 이름을 부여 ## 길이를 매번 계산하는것보다 dimension을 넣어두고 확인하는 방법이 빠르고 쉬움 ``` python import math class Vector: def __init__(self,lst): self._vec = list(lst) self._dim = len(self._vec) def __repr__(self): return "Vector({})".format(self._vec) def __add__(self,other): x = self._vec y = other._vec if len(x) != len(y): print("Error") return None return Vector([x[i] + y[i] for i in range(self._dim)]) def __sub__(self,other): x = self._vec y = other._vec if sef._dim != other._dim: print("Error") return None return Vector([x[i] - y[i] for i in range(self._dim)]) def dim(self): return self._dim def __getitem__(self,key): return self._vec[key] def __setitem__(self,key,val): self._vec[key] = val def size(self): return math.sqrt(sum([x**2 for x in self._vec])) x = Vector(range(100)) x[2] = 10 x ``` > Vector([0, 1, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]) x나 print(x)나 같은 결과 근데 이미지이면 어떨까? ``` python from skimage import novice,data import math class Vector: def __init__(self,lst): self._vec = list(lst) self._dim = len(self._vec) def __repr__(self): return "Vector({})".format(self._vec) def __add__(self,other): x = self._vec y = other._vec if len(x) != len(y): print("Error") return None return Vector([x[i] + y[i] for i in range(self._dim)]) def __sub__(self,other): x = self._vec y = other._vec if sef._dim != other._dim: print("Error") return None return Vector([x[i] - y[i] for i in range(self._dim)]) def dim(self): return self._dim def __getitem__(self,key): return self._vec[key] def __setitem__(self,key,val): self._vec[key] = val def size(self): return math.sqrt(sum([x**2 for x in self._vec])) x = Vector(range(100)) x[2] = 10 x = novice.open(data.data_dir + "/chelsea.png") print(x) ``` > Picture(451 x 300) ``` x ``` > 냐옹이 이미지 x의 모든 픽셀들을 다 찍어주는것과 중간값을 print하는 것은 다른 결과를 나타냄 ``` print(x): 계산 중간 값(__str__) x : x계산 최종 값(__repr__) ``` ```py def __str__(self): if (self.dim() > 3): return "Vector({},{},...)".format(self._vec for i in range(len(self._vec))) else: return self.__repr__() ```
## Code duplication: the motive of inheritance ```python class Point: def __init__(self,lst): self._vec = list(lst) def distance(self,other): lst = [self._vec[i] - other._vec[i] for i in range(return math.sqrt(sum([x*x for x in lst])) ``` The similarity between Vector and Point can be better utilized using inheritance