day 9 두 점 사이의 거리 구하기

5 minute read

두 점 사이의 거리 구하기

클래스로 점 구현하기

class Point2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
p1 = Point2D(x=30, y=20)    # 점1
p2 = Point2D(x=60, y=50)    # 점2
 
print('p1: {} {}'.format(p1.x, p1.y))    # 30 20
print('p2: {} {}'.format(p2.x, p2.y))    # 60 50
p1: 30 20
p2: 60 50

image

# 그럼 √(루트)는 어떻게 구현해야 할까요? 이때는 math 모듈의 sqrt 함수를 사용하면 편리합니다. sqrt는 제곱근을 뜻하는 square root에서 따왔습니다.

# math.sqrt(값)
# n  제곱근을 반환, 값이 음수이면 에러 발생

# 이제 sqrt 함수까지 사용해서 p1과 p2의 거리를 구해보겠습니다.

피타고라스의 정리로 두 점의 거리 구하기

image

import math
 
class Point2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
p1 = Point2D(x=30, y=20)    # 점1
p2 = Point2D(x=60, y=50)    # 점2
 
a = p2.x - p1.x    # 선 a의 길이
b = p2.y - p1.y    # 선 b의 길이
 
c = math.sqrt((a * a) + (b * b))    # (a * a) + (b * b)의 제곱근을 구함
# c = math.sqrt((a ** 2) + (b ** 2))
# c = math.sqrt(math.pow(a, 2) + math.pow(b, 2))

print(c)    # 42.42640687119285
42.42640687119285

참고 | 절댓값 함수

# 내장 함수 abs 또는 math 모듈의 fabs 함수를 사용하면 양수 또는 음수를 절댓값(absolute value)으로 만들 수 있습니다.

# abs(값)

# 정수는 절댓값을 정수로 반환, 실수는 절댓값을 실수로 반환

# math.fabs(값)

# 절댓값을 실수로 반환

참고 | namedtuple 사용하기

# 파이썬에서는 각 요소에 이름을 지정해 줄 수 있는 튜플인 namedtuple을 제공합니다( collections 모듈). namedtuple은 자료형 이름과 요소의 이름을 지정하면 클래스를 생성해줍니다. 여기서 자료형 이름은 문자열, 요소의 이름은 문자열 리스트로 넣어줍니다.

# 클래스 = collections.namedtuple('자료형이름', ['요소이름1', '요소이름2'])

# namedtuple로 생성한 클래스는 값을 넣어서 인스턴스를 만들 수 있으며 인스턴스.요소이름 또는 인스턴스[인덱스] 형식으로 요소에 접근할 수 있습니다.

# 인스턴스 = 클래스(값1, 값2)

# 인스턴스 = 클래스(요소이름1=값1, 요소이름2=값2)

# 인스턴스.요소이름1

# 인스턴스[인덱스]

# 다음은 namedtuple을 사용하여 점을 표현한 뒤 두 점의 거리를 구합니다.
import math
import collections
 
Point2D = collections.namedtuple('Point2D', ['x', 'y'])    # namedtuple로 점 표현
 
p1 = Point2D(x=30, y=20)    # 점1
p2 = Point2D(x=60, y=50)    # 점2
 
a = p1.x - p2.x    # 선 a의 길이
b = p1.y - p2.y    # 선 b의 길이
 
c = math.sqrt((a * a) + (b * b))
print(c)    # 42.42640687119285
42.42640687119285

사각형의 넓이 구하기


image

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2
 
rect = Rectangle(x1=20, y1=20, x2=40, y2=30)
 
width = abs(rect.x2 - rect.x1)
height = abs(rect.y2 - rect.y1)
area = width * height                       
print(area)
200
# 표준 입력으로 x, y 좌표 4개가 입력되어 
# Point2D 클래스의 인스턴스 리스트에 저장됩니다. 
# 여기서 점 4개는 첫 번째 점부터 마지막 점까지 순서대로 이어져 있습니다. 
# 다음 소스 코드를 완성하여 
# 첫 번째 점부터 마지막 점까지 연결된 선의 길이가 출력되게 만드세요.
import math
import collections




class Point2D:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
 
length = 0.0
p = [Point2D(), Point2D(), Point2D(), Point2D()]
p[0].x, p[0].y, p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y = map(int, input().split())

for i in range(1,len(p)):
    a = p[i-1].x - p[i].x    # 선 a의 길이
    b = p[i-1].y - p[i].y    # 선 b의 길이
    length += math.sqrt((a * a) + (b * b))


print(length)
10 10 20 20 30 30 40 40
42.42640687119285

요약

클래스

클래스는 객체를 표현하기 위한 문법입니다. 클래스는 class에 클래스 이름을 지정하고 :(콜론)을 붙인 뒤 다음 줄부터 def로 메서드를 작성합니다. 메서드는 클래스 안에 들어있는 함수를 뜻합니다.

class 클래스이름:        # 클래스 만들기
    def 메서드(self):    # 메서드 만들기
        코드

클래스는 ()(괄호)를 붙인 뒤 변수에 할당하여 인스턴스(객체)를 만듭니다. 그리고 인스턴스 뒤에 .(점)을 붙여서 메서드를 호출합니다.

인스턴스 = 클래스()    # 인스턴스(객체) 만들기
인스턴스.메서드()      # 인스턴스로 메서드 호출

클래스의 속성

클래스에 인스턴스 속성을 만들 때는 __init__ 메서드 안에서 self.속성에 값을 할당해줍니다. 그리고 인스턴스 속성에 접근할 때는 메서드 안에서 self 뒤에 .(점)을 붙여서 접근하거나, 인스턴스 뒤에 .을 붙여서 접근합니다.

class 클래스이름:
    def __init__(self):
        self.속성 = 값      # 인스턴스 속성 만들기
 
    def 메서드(self):
        self.속성           # self 뒤에 .을 붙여서 인스턴스 속성에 접근
 
인스턴스 = 클래스()         # 인스턴스(객체) 만들기
인스턴스.속성               # 인스턴스 속성에 접근

클래스에 바로 속성을 만들면 클래스 속성이 되며 해당 클래스로 만든 모든 인스턴스가 값을 공유합니다. 클래스 속성은 self 또는 클래스 뒤에 .(점)을 붙여서 접근합니다.

class 클래스이름:
    속성 = 값    # 클래스 속성 만들기
 
    def 메서드(self):
        self.속성           # self 뒤에 .을 붙여서 클래스 속성에 접근
        클래스.속성         # 클래스 뒤에 .을 붙여서 클래스 속성에 접근
클래스.속성    # 클래스 속성에 접근

속성을 만들 때 __속성과 같이 __(밑줄 두 개)로 시작하면 비공개 속성이 됩니다. 비공개 속성은 클래스 안에서만 접근할 수 있고, 클래스 바깥에서는 접근할 수 없습니다(비공개 메서드도 같은 방식).

class 클래스이름:
    __속성 = 값    # 비공개 클래스 속성
 
    def __init__(self):
        self.__속성 = 값      # 비공개 인스턴스 속성

정적 메서드와 클래스 메서드

정적 메서드와 클래스 메서드는 인스턴스를 통하지 않고 클래스에서 바로 호출할 수 있는 메서드입니다. 정적 메서드는 메서드 위에 @staticmethod를 붙이며 매개변수에 self를 지정하지 않습니다.

class 클래스이름:
    @staticmethod    # 정적 메서드 만들기
    def 메서드(매개변수1, 매개변수2):
        코드

정적 메서드는 self를 받지 않으므로 인스턴스 속성에 접근할 수 없습니다. 따라서 정적 메서드는 인스턴스 속성, 인스턴스 메서드가 필요 없을 때 사용합니다.

클래스 메서드는 메서드 위에 @classmethod를 붙이며 매개변수에 cls를 지정합니다.

class 클래스이름:
    @classmethod    # 클래스 메서드 만들기
    def 메서드(cls, 매개변수1, 매개변수2):
        코드

클래스 메서드는 메서드 안에서 클래스 속성, 클래스 메서드에 접근해야 할 때 사용합니다.

클래스 상속

클래스 상속은 물려받은 기능을 유지한채로 다른 기능을 추가할 때 사용합니다. 기능을 물려주는 클래스를 기반 클래스, 상속을 받아 새롭게 만드는 클래스를 파생 클래스라고 합니다.

상속은 클래스를 만들 때 ( )(괄호)를 붙이고 괄호 안에 기반 클래스 이름을 넣어줍니다.

class 기반클래스이름:
    코드
 
class 파생클래스이름(기반클래스이름):    # 기반 클래스를 상속받음
    코드

기반 클래스의 속성에 접근하거나 메서드를 호출할 때는 super() 뒤에 .을 붙여서 사용합니다. 또는, super(파생클래스, self) 형식으로 사용할 수도 있습니다.

class 기반클래스이름:
    def \__init__(self):
        self.속성 = 값
 
class 파생클래스이름(기반클래스이름):
    def \__init__(self):
        super().\__init__()              # super()로 기반 클래스의 메서드 호출
        super().속성                    # super()로 기반 클래스의 속성에 접근
        super(파생클래스, self).속성    # super에 파생 클래스와 self를 넣는 형식

상속 관계와 포함 관계

상속은 학생과 사람처럼 명확하게 같은 종류이며 동등한 관계일 때 사용하며 is-a 관계라고 부릅니다. 포함은 사람과 사람 목록처럼 동등한 관계가 아니라 포함 관계일 때 사용하며 has-a 관계라고 부릅니다.

메서드 오버라이딩

파생 클래스에서 기반 클래스의 메서드를 새로 정의하는 것을 메서드 오버라이딩이라고 합니다. 메서드 오버라이딩은 파생 클래스에서 메서드를 정의할 때 기반 클래스의 메서드 이름과 똑같이 만들어줍니다.

class Person:
    def greeting(self):
        pass
 
class Student(Person):
    def greeting(self):       # 메서드 오버라이딩
        super().greeting()    # super()로 기반 클래스의 메서드 호출
 
james = Student()
james.greeting()     # Student의 greeting 메서드가 호출 됨

메서드 오버라이딩은 원래 기능을 유지하면서 새로운 기능을 덧붙일 때, 프로그램에서 어떤 기능이 같은 메서드 이름으로 계속 사용되어야 할 때 활용합니다.

다중 상속

다중 상속은 여러 기반 클래스로부터 상속을 받아서 파생 클래스를 만드는 방법입니다. 클래스를 만들 때 ( )(괄호) 안에 클래스 이름을 ,(콤마)로 구분해서 넣어줍니다.

class 기반클래스이름1:
    코드
 
class 기반클래스이름2:
    코드
 
class 파생클래스이름(기반클래스이름1, 기반클래스이름2):    # 다중 상속 사용하기
    코드

추상 클래스

추상 클래스는 메서드 목록만 가진 클래스이며 상속받는 클래스에서 메서드 구현을 강제하기 위해 사용합니다. 추상 클래스를 사용하려면 import로 abc 모듈을 가져온 뒤 클래스의 ( )(괄호) 안에 metaclass=ABCMeta를 지정하고, 메서드 위에 @abstractmethod를 붙여줍니다.

from abc import *
 
class 추상클래스이름(metaclass=ABCMeta):    # 추상 클래스 만들기
    @abstractmethod
    def 메서드이름(self):
        코드

Leave a comment