Point concept

point는 평면뿐만 아니라 위도 경도가 있는 한점, 3차원의 한점.. 등 많음

하나의 단위. tuple과 유사 그러나 blank.x = 10처럼 개별적으로 변경 가능 x와 y 각각을 개별적으로 바꾸지 않도록 정의를 해야함 -> 둘 중 하나만 바뀌어도 다른 점이 되기 때문

1
2
3
4
5
6
7
8
class Point:
    def __init__(self):
        self.x = 0
        self.y = 0
    def x(self):
        return self._x
    def y(self):
        return self._y


Point method

현재 위치에서 얼마만큼을 옮겨가달라는 메소드가 있으면 점을 제대로 옮길 수 있음

1
2
3
4
5
6
7
8
9
class Point:
    ...
    def move(self,dx,dy):
        self._x += dx
        self._y += dy
    def distance(self, other):
        dx = self.x() - other.x()
        dy = self.y() - other.y()
        return math.sqrt(dx**2 + dy**2)


Vector concept

벡터가 한번 정해지고 나면 벡터 안에 들어있는 엘리먼트들을 읽어올 수는 있고 각각을 따로 변화시킬 수 있음 2차원보다 더 큰 차원들이 존재할 수 있음 BUT 순서가 있는 숫자들의 모임

1
2
3
class Vector:
    def __init__(self,lst):
        self._vec = list(lst)

tuple이 오든 set이 오든 모두 list로 저장하기로 함

append()는 가능해야할까? 놉! 벡터의 차원이 한번 정해지면 차원이 변할 수는 없음

Vector method

1
2
3
4
5
6
7
8
class Vector:
    def __add__(self,other):
        ...
    def __sub__(self,other):
        ...
>>> x = Vector([1,2,3])
>>> x.append()
Error: ...

list를 이용하여 구현(list type)된 class이지만 벡터의 어디에도 append라는 메소드가 정의되어 있지 않기때문에 append()되지 않음 list가 아닌 vector로써 사용하는거다아악 list로 구현되어 있지 않은 add와 sub을 vector에 구현되어 있으면 add와 sub할 수 있고 list로 구현되어 있는 append를 vector에 구현하지 않으면 append할 수 없음

vector의 곱하기는 inner product(내적) -> 벡터연산에 많이 사용됨 outer product(외적) -> 3차원

Point와 Vector의 유사성

Point의 차원 = Vector의 차원과 동일 Point의 이동 = Vector의 덧셈으로 계산 가능 Point간의 거리 = Vector의 뺄셈 및 크기로 계산 …

1
2
3
4
5
6
7
8
9
10
4차원 공간상의 두점 a(a1,a2,a3,a4)와 b(b1,b2,b3,b4)
거리 = sqrt( (a1-b1)제곱 + (a2-b2)제곱 + (a3-b3)제곱 + (a4-b4)제곱 )

점이아니라 Vector로 보자
두 Vector v1(a1,a2,a3,a4)과 v2(b1,b2,b3,b4)의 차이는
v1 - v2 = (a1-b1, a2-b2, a3-b3, a4-b4)

이 것의 사이즈는?
sqrt( (a1-b1)제곱 + (a2-b2)제곱 + (a3-b3)제곱 + (a4-b4)제곱 )
두 점 사이의 거리 = 두 벡터의 차의 크기

–> Point는 일종의 특별한 Vector로 볼 수 있다! —-> Inheritance : 이미 구현된 클래스의 기능을 기반으로 특별한 성질을 더하는것

Point의 차원을 늘리려면 x,y,z,w… 자꾸 늘어나고 제일 처음에 나오는게 x라고 가정하고 짜놨는데 4차원으로 늘어나는 순간 w가 먼저 나와야 하니까 순서도 막 바뀜

Vector에서 구현되어 있는 것들을 가져다가 사용하는게 Point를 구현할때 깔끔하겠다는 생각이 듦? 얍얍

Inheritance

1
2
3
4
5
6
7
8
9
class Vector:
  def __init__(self,lst):
    ...
class Point (Vector):
    def __init__(self,x,y):
        super().__init__([x,y])
    def distance(self,other):
      v = self - other
      return v.size()

Point는 inherited class Vector는 super class Point inherits Vector attribues

Specialising inherited class

1
2
3
>>> p1 = Point(0,1)
>>> print(p1)
Vector([0, 1])

ㅇㅅㅇ..? point줬는데염! –> We should specialize __str__() and __repr__()

1
2
3
4
5
6
7
8
9
10
class Point(Vector):
    def __init__(self,x,y):
        super().__init__([x,y])
    def __repr__(self):
        return "Point({},{})".format(self.x(),self.y())
    def __str__(self):
        return self.__repr__()
>>> p1 = Point(0,1)
>>> print(p1)
Point(0,1)

뜐 됐당

하지만 또 남은게 있다

1
2
>>> p1 = Point(0,1)
>>> p1[0] = 10

Point(x,y)의 x만 set하거나 y만 set할 수는 없어야함

1
2
3
4
5
6
7
8
class Point(Vector):
    def __setitem__(self,key,val):
        print("Error: Point cannot assign new item")
>>> v1 = Vector([0,1])
>>> v1[0] = 10
>>> p1 = Point(0,1)
>>> p1[0] = 10
Point does not support __setitem__

뀨 now Point is a specialised Vector

그렇다면 이제 전체적으로 보쟈 원래의 Point는

1
2
3
4
5
6
7
8
9
10
11
12
13
import math
class Point2():
    def __init__(self,x,y):
        self._x = x
        self._y = y
    def x(self):
        return self.x
    def y(self):
        return self.y
    def distance(self,other):
        dx = self.x() - other.x()
        dy = self.y() - other.y()
        return math.sqrt(dx**2 + dy**2)

하나하나 다 새로 만들어야 했지만

Vector 를 상속받은 Point는

1
2
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
import math
class Vector:
    def __init__(self,lst):
        self._vec = list(lst)
    def __repr__(self):
        return "Vector({})".format(self._vec)
    def __getitem__(self,key):
        return self._vec[key]
    def __setitem__(self,key,val):
        self._vec[key] = val
    def __add__(self,other):
        return Vector([self[i] + other[i] for i in range(len(self._vec))])
    def __sub__(self,other):
        return Vector([self[i] + other[i] for i in range(len(self._vec))])
    def size(self):
        return math.sqrt(sum([self[i]**2 for i in self._vec]))

class Point (Vector): #Vector를 inherit
    def __init__(self,x,y):
        super().__init__([x,y]) #super class(vector)의 init
    def __repr__(self):
        return "Point({},{})".format(self[0],self[1])
    def distance(self,other):
        d = self - other
        return d.size()
    def x(self):
        return self[0]
    def y(self):
        return self[1]
    def __setitem__(self,key,val): #Point는 각값을 따로 바꾸지 않도록함
        print("Error!")


1
2
3
v = Vector([1,2])
v[0] = 10
print(v)

Vector([10, 2])


1
2
3
p1 = Point(1,0)
p2 = Point(0,1)
print(p1.distance(p2))

1.4142135623730951


1
2
p1[0] = 10 #여기서 (1)Error출력하고 (2)더 이상 실행하지 않도록 할 예정 -> 아직 (1)까지만 함
print(p1)

Error! Point(1,0)