Unit 35. 클래스 속성과 정적, 클래스 메서드 사용하기

35.1 클래스 속성과 인스턴스 속성 알아보기

속성에는 클래스 속성과 인스턴스 속성 두 가지 종류가 있다. __init__메서드에서 만들었던 속성은 인스턴스 속성이다.

 

35.1.1 클래스 속성 사용하기

클래스 속성은 다음과 같이 클래스에 바로 속성을 만든다.

class 클래스이름:
    속성 = 값

다음은 사람 클래스에 클래스 속성으로 가방 속성을 만들고, 가방에 물건을 넣는 put_bag메서드를 사용하는 코드이다.

class Person:
    bag = []

    def put_bag(self, stuff):
        self.bag.append(stuff)

james = Person()
james.put_bag('book')

maria = Person()
maria.put_bag('key')

print(james.bag)
print(maria.bag)

결과를 보면 두 인스턴스에 넣었던 물건이 합쳐저서 출력되는것을 확인할 수 있다.

클래스 속성은 클래스에 속해있으면서 모든 인스턴스에서 공유된다.

클래스 속성에 접근할 때는 다음과 같이 클래스 이름으로 접근하면 코드가 좀 더 명확해진다.

class Person:
    bag = []
 
    def put_bag(self, stuff):
        Person.bag.append(stuff)

클래스 밖에서도 다음과 같이 클래스 이름으로 클래스 속성에 접근하면 된다.

print(Person.bag)

 

속성, 메서드 이름을 찾는 순서

파이썬에서는 속성, 메서드 이름을 찾을 때 인스턴스, 클래스 순서로 찾는다. 그래서 인스턴스 속성이 있는지 먼저 확인하고, 클래스 속성을 찾는다. 인스턴스와 클래스에서 __dict__ 속성을 출력해보면 현재 인스턴스와 클래스의 속성을 딕셔너리로 확인할 수 있다.

print(james.__dict__)
print(Person.__dict__)

 

35.1.2 인스턴스 속성 사용하기

bag속성을 여러 객체가 공유하지 않으려면 bag를 인스턴스 속성으로 만들면 된다.

class Person:
    def __init__(self):
        self.bag = []

    def put_bag(self, stuff):
        self.bag.append(stuff)

james = Person()
james.put_bag('book')

maria = Person()
maria.put_bag('key')

print(james.bag)
print(maria.bag)

이제 james.bag과 maria.bag을 출력해보면 각자 넣은 물건만 출력된다.

인스턴스 속성은 인스턴스 별로 독립되어 있으며 서로 영향을 주지 않는다.

 

35.1.3 비공개 클래스 속성 사용하기

클래스 속성도 비공개 속성을 만들수 있다. 클래스 속성을 만들 때 __속성처럼 앞에 밑줄 두 개로 시작하면 비공개 속성이된다. 비공개 클래스 속성은 클래스 안에서만 접근할 수 있고, 밖에서는 접근할 수 없다.

class 클래스이름:
    __속성 = 값

클래스에서 공개하고 싶지 않은 속성이 있다면 비공개 클래스를 사용해야 한다. 다음은 기사 게임 캐릭터의 아이템 최대 개수를 비공개 클래스 속성으로 작성한 것이다.

class Knight:
    __item_limit = 10

    def print_limit(self):
        print(Knight.__item_limit)

x = Knight()
x.print_limit()

print(x.__item_limit)

위와 같이 비공개 클래스 속성은 클래스 밖에서는 접근할 수 없고, 클래스 내부의 메서드에서만 접근이 가능하다.

 

클래스와 메서드의 독스트링 사용하기

함수와 마찬가지로 클래스와 메서드 에서도 클론 바로 다음 줄에 """ """ 또는 ''' '''로 독스트링을 사용할 수 있고, 클래스.__doc__, 메서드.__doc__와 같이 출력할 수 있다.

print(Person.__doc__)
print(james.put_bag.__doc__)

 

35.2 정적 메서드 사용하기

인스턴스를 통하지 않고, 클래스에서 바로 호출할 수 있는 정적 메서드와 클래스 메서드가 있다.

정적 메서드는 다음과 같이 메서드 위에 @staticmethod를 붙인다. 이때 정적 메서드는 매개변수에 self를 지정하지 않는다.

class 클래스이름:
    @staticmethod
    def 메서드(매개변수1, 매개변수2)
        코드

@staticmethod 처럼 앞에 @가 붙은 것을 데코레이터라고 하며 메서드(함수)에 추가 기능을 구현할 때 사용한다.

다음은 덧셈과 곱셈을 하는 클래스이다.

class Calc:
    @staticmethod
    def add(a,b):
        print(a + b)

    @staticmethod
    def mul(a,b):
        print(a*b)


Calc.add(5,3)
Calc.mul(5,3)

정적 메서드는 위와 같이 호출할 때 클래스에서 바로 메서드를 호출할 수 있다.

정적 메서드는 self를 받지 않기 때문에 인스턴스 속성에는 접근할 수 없다. 그래서 보통 정적 메서드는 인스턴스 속성, 인스턴스 메서드가 필요 없을 때 사용한다.

정적 메서드는 메서드의 실행이 외부 상태에 영향을 끼치지 않는 순수 함수를 만들 때 사용한다. 순수 함수는 부수 효과가 없고, 입력값이 같으면 언제나 같은 값을 반환한다. 정적 메서드는 인스턴스의 상태를 변화시키지 않는 메서드를 만들 때 사용한다.

파이썬의 자료형도 인스턴스 메서드와 정적 메서드로 나누어져 있다. 인스턴스의 내용을 변경시켜야 할 땐 인스턴스 메서드를 사용하고, 인스턴스 내용과 상관 없이 결과만 구하면 될 때는 정적 메서드를 이용한다.

 

35.3 클래스 메서드 사용하기

클래스 메서드는 메서드 위에 @classmethod를 붙인다. 첫번째 매개변수로는 cls를 지정해야 한다.(cls는 class에서 따온 것이다.)

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

다음은 사람 클래스에 인스턴스가 몇 개 만들어졌는지 출력하는 클래스 메서드를 만들었다.

class Person:
    count = 0

    def __init__(self):
        Person.count += 1

    @classmethod
    def print_count(cls):
        print('{} people'.format(cls.count))

james = Person()
maria = Person()

Person.print_count()

인스턴스가 만들어 질때마다 __init__메서드로 클래스 속성 count에 1을 더해준다.

클래스 메서드의 매개변수 cls는 현재 클래스가 들어오기 때문에 cls.count와 같은 방식으로 cls로 클래스 속성 count 에 접근할 수 있다.

print_count 메서드는 클래스 메서드이기 때문에 Person.print_count처럼 클래스로 호출해야 한다.

Person으로 인스턴스를 두 개 만들었기 때문에 '2 people'이 출력된다.

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

다음과 같이 cls를 사용하여 현재 클래스의 인스턴스를 만들 수도 있다. cls()는 Person()와 같다.

    @classmethod
    def create(cls):
        p = cls()
        return p


35.4 퀴즈

정답은 a 이다.

정답은 c이다.

정답은 c,e이다. 클래스 메서드의 첫번째 매개변수는 cls이다. 클래스 메서드는 위에 @classmethod를 붙여야 한다.

 

35.5 연습문제: 날짜 클래스 만들기

정답은 다음 코드와 같다.

    @staticmethod
    def is_date_valid(date):
        year, month, day = map(int, date.split('-'))
        return 0 < month <= 12 and 0 < day <= 31 

클래스.메서드의 형식으로 호출했기 때문에 정적 메서드를 사용하여 날짜 형식에 따라 True와 False를 반환하도록 하였다.

 

35.6 심사문제: 시간 클래스 만들기

정답은 다음 코드와 같다.

    @staticmethod
    def is_time_valid(time):
        h, m, s = map(int, time.split(':'))
        return 0 < h <=24 and 0 <= m <= 59 and 0 <= s <= 60
    
    @classmethod
    def from_string(cls, time):
        h, m, s = map(int, time.split(':'))
        t = cls(h,m,s)
        return t

is_time_valid는 조건문에 들어가 True와 False만 반환하면 되기에 정적 메서드로 입력값을 시, 분, 초로 분리하여 각 값이 올바른 형식인지 검사하였다. from_string는 인스턴스 속성이 필요하기 때문에 클래스 메서드로 메서드 내에서 입력값을 시, 분, 초로 분리하여 새로운 인스턴스를 만들어 반환하였다.

 

Unit 36. 클래스 상속 사용하기

클래스 상속은 물려받은 기능을 그대로 유지한 채로 다른 기능을 추가할 때 사용하는 기능이다. 기능을 물려주는 클래스를 기반 클래스, 상속을 받아 새롭게 만드는 클래스를 파생 클래스라고 한다. 보통 기반클래스를 부모클래스 또는 슈퍼클래스 라고 부르고, 파생클래스를 자식클래스 또는 서브클래스 라고 부른다.

새로운 기능이 필요할 때 마다 계속 클래스를 만들면 중복되는 부분도 계속해서 만들어야 한다. 이때 상속을 사용하면 중복되는 기능을 만들지 않아도 되기 때문에 상속클래스는 기존 기능을 재사용 할 수 있어서 효율적이다.

 

36.1 사람 클래스로 학생 클래스 만들기

클래스 상속은 다음과 같이 파생클래스를 만들 때 괄호를 붙이고 괄호 안에 기반클래스 이름을 넣는다.

class 기반클래스이름:
    코드
    
class 파생클래스이름(기반클래스이름):
    코드

 

다음은 사람클래스를 만들고 사람클래스를 상속받아 학생클래스를 만든 것이다.

class Person():
    def greeting(self):
        print('hello')
    
class Student(Person):
    def study(self):
        print('do study')

james = Student()
james.greeting()
james.study()

Student 클래스를 만들 때 괄호 안에 기반클래스의 이름인 Person을 넣었다.

Student 클래스에는 greeting메서드가 없지만, Person클래스를 상속받아 Person클래스의 메서드를 호출할 수 있다.

이후 Student클래스만 갖고 있는 study 메서드를 호출하였다.

클래스 상속은 기반 클래스의 기능을 유지하며 새로운 기능을 추가할 수 있다. 클래스 상속은 연관되면서 동등한 개념일 때 사용한다.

클래스의 상속 관계를 확인하려면 issubclass를 사용한다. 기반클래스의 파생클래스가 맞으면 True, 아니면 False를 반환한다.

함수 사용법은 다음과 같다.

issubclass(파생클래스, 기반클래스)

 

36.2 상속 관계와 포함관계 알아보기

36.2.1 상속관계

위에서 만든 Student 클래스는 Person 클래스를 상속받아 만들어졌다. 

학생 Student는 사람 Person과 같은 종류이며 동등한 관계이다.

상속은 명확하게 같은관계이며 동등한 관계일 때 사용한다. 영어로는 is-a 관계라고 부른다.

 

36.2.2 포함관계

class Person:
    def greeting(self):
        print('안녕하세요.')
 
class PersonList:
    def __init__(self):
        self.person_list = []	# 리스트 속성에 Person인스턴스를 넣음
 
    def append_person(self, person):
        self.person_list.append(person)

위 코드의 경우 상속을 사용하지 않고, 속성에 인스턴스를 넣어서 관리하므로 PersonList가 Person을 포함하고 있다. 두 클래스는 동등한 관계가 아니라 포함관계이다. 포함 관계는 영어로 has-a 관계라고 부른다.

같은 종류의 동등한 관계라면 상속을 사용하고, 그 이외에는 속성에 인스턴스를 넣는 포함방식을 사용하면 된다.

 

36.3 기반 클래스의 속성 사용하기

class Person:
    def __init__(self):
        print('Person __init__')
        self.hello = 'Hello!'
    
class Student(Person):
    def __init__(self):
        print('Student __init__')
        self.school = 'python dojang'

james = Student()
print(james.school)
print(james.hello)

위 코드를 실행해보면 기반클래스의 hello속성에 접근하려고 하면 에러가 발생한다. 기반 클래스 Person의 __init__메서드가 호출되지 않았기 때문이다. Person클래스의 __init__가 실행되지 않으면 self.hello도 실행되지 않아서 속성이 만들어지지 않는다.

 

36.3.1 super()로 기반 클래스 초기화하기

super()를 사용하여 기반 클래스의 __init__ 메서드를 호출할 수 있다. 다음과 같이 super() 뒤에 점을 붙여서 메서드를 호출하는 방식이다.

super().메서드
class Person:
    def __init__(self):
        print('Person __init__')
        self.hello = 'Hello!'
    
class Student(Person):
    def __init__(self):
        print('Student __init__')
        super().__init__()
        self.school = 'python dojang'

james = Student()
print(james.school)
print(james.hello)

super().__init__() 처럼 기반 메서드의 __init__ 메서드를 호출해주면 기반 클래스가 초기화되어 속성이 만들어진다. 실행 결과를 보면 Person __init__ 과 Student __init__ 이 둘다 출력되었다.

 

36.3.2 기반 클래스를 초기화하지 않아도 되는 경우

파생클래스에서 __init__메서드를 생략하면 기반클래스의 __init__이 자동 호출되므로 super()은 사용하지 않아도 된다.

class Person:
    def __init__(self):
        print('Person __init__')
        self.hello = 'Hello!'
    
class Student(Person):
    pass

james = Student()
print(james.hello)

super()은 괄호 안에 파생클래스와 self를 넣어서 현재 클래스가 어떤 클래스인지 명확하게 표시하는 방법도 있다. super()와 기능은 같다.

super(파생클래스, self).메서드

 

36.4 메서드 오버라이딩 사용하기

메서드 오버라이딩은 파생클래스에서 기반 클래스의 메서드를 새로 정의하는 것이다.

class Person:
    def greeting(self):
        print('hello')
    
class Student(Person):
    def greeting(self):
        print('hello i am student')

james = Student()
james.greeting()

Person 클래스에 greeting메서드가 있는 상태에서 파생클래스인 Student에도 greeting 메서드를 만들었다.

Student의 greeting메서드를 호출하니 hello i am student가 출력되었다. 

오버라이딩은 무시하다, 우선하다 라는 뜻을 갖고 있어 기반클래스의 메서드를 무시하고, 파생클래스의 메서드를 출력하였다.

메서드 오버라이딩은 프로그램에서 어떤 기능이 같은 메서드 이름으로 계속 사용되어야 할 때 사용된다. 

Person클래스와 Student클래스의 greeting메서드를 보면 hello라는 문구가 중복된다. 이와 같은 경우 오버라이딩 된 메서드에서 super()로 기반클래스의 메서드를 호출하여 재활용하면 중복을 줄일 수 있다.

class Person:
    def greeting(self):
        print('hello')
    
class Student(Person):
    def greeting(self):
        super().greeting()
        print('i am student')

james = Student()
james.greeting()

중복되는 기능은 파생 클래스에서 다시 만들지 않고, 기반 클래스의 기능을 사용하면 된다. 메서드 오버라이딩은 원래 기능을 유지하며 새로운 기능을 덧붙일 때 사용한다.

 

36.5 다중 상속 사용하기

다중 상속은 여러 클래스로부터 상속을 받아서 파생 클래스를 만드는 방법이다. 다음과 같이 클래스를 만들때 괄호 안에 상속받는 클래스 이름을 콤마로 구분하여 넣는다.

class 기반클래스이름1:
    코드
 
class 기반클래스이름2:
    코드
 
class 파생클래스이름(기반클래스이름1, 기반클래스이름2):
    코드

다음은 사람클래스와 대학교 클래스를 만든 뒤 다중 상속으로 상속받는 학생 클래스를 만든 것이다.

class Person:
    def greeting(self):
        print('hello')
    
class University:
    def manage_credit(self):
        print('Manage Credit')

class Undergraduate(Person, University):
    def study(self):
        print('do study')

james = Undergraduate()
james.greeting()
james.manage_credit()
james.study()

Undergraduate 클래스는 기반 클래스로 Person클래스와 University 클래스를 상속받아서 위와 같이 Undergraduate 클래스의 인스턴스로 Person의 greeting과 University의 manage_credit 메서드를 호출할 수 있다.

 

36.5.1 다이아몬드 상속

class A:
    def greeting(self):
        print('hello A')

class B(A):
    def greeting(self):
        print('hello B')

class C(A):
    def greeting(self):
        print('hello C')

class D(B, C):
    pass

x = D()
x.greeting()

기반 클래스 A가 있고, B, C는 A를 상속 받고, D는 다시 B, C를 상속받는다. 그림으로 이 관계를 확인하면 다음과 같다.

클래스 간의 관계가 다이아몬드 처럼 생겨서 다이아몬드 상속 이라고 부른다. A,B,C 모두 greeting라는 메서드를 갖고 있고, A를 상속받은, B,C를 상속받은 D는 어떤 클래스의 메서드를 호출해야할지 매우 애매한 상황에 놓인다. 프로그램에서 이렇게 명확하지 않은 상황은 큰 문제를 일으킬 수 있기 때문에 죽음의 다이아몬드 라고도 불린다.

 

36.5.2 메서드 탐색 순서 확인하기

파이썬에서 이러한 다이아몬드 상속의 해결책을 제시하기 위해 메서드 탐색 순서(Method Resolution Order, MRO)를 따른다. 클래스 D에서 mro를 사용하면 메서드 탐색 순서가 나온다.

print(D.mro())

MRO에 따르면 D메서드의 호출 순서는 자기자신 D, 그 다음이 B이다. 따라서 D로 greeting를 호출하면 B의 메서드가 호출된다.

파이썬에서 상속 관계가 복잡하게 얽혀있다면 MRO를 살펴보는 것이 좋다.

 

파이썬에서 object는 모든 클래스의 조상이다. 모든 클래스는 object클래스를 상속받기 때문에 기본적으로 object를 생략했다.

class X(object):	# object는 모든 클래스에 기본적으로 상속되어 있어 보통은 생략한다.
    pass

 

36.6 추상 클래스 사용하기

추상클래스는 메서드의 목록만 가진 클래스이며 상속받는 클래스에서 메서드 구현을 강제하기 위해 사용한다.

추상 클래스를 만드려면 import로 abc모듈을 가져와야 한다. 그리고 클래스의 괄호 안에 metaclass=ABCMeta를 지정하고, 메서드를 만들 때 위에 @abstractmethod를 붙여서 추상 메서드로 지정해야 한다.

from abc import *

class 추상클래스이름(metaclass=ABCMeta):
    @abstractmethod
    def 메서드이름(self):
        코드
from abc import *
 
class StudentBase(metaclass=ABCMeta):
    @abstractmethod
    def study(self):
        pass
 
    @abstractmethod
    def go_to_school(self):
        pass
 
class Student(StudentBase):
    def study(self):
        print('do study')
 
james = Student()
james.study()

위 코드를 실행하면 다음과 같은 에러가 발생한다. 추상클래스에서 지정한 go_to_school메서드가 상속받은 클래스인 Student에서 구현하지 않았기 때문이다.
추상클래스를 상속받았다면 @abstractmethod가 붙은 추상 메서드를 모두 구현해야 한다. 다음과 같이 코드를 수정하면 에러 없이 실행 가능하다.

from abc import *
 
class StudentBase(metaclass=ABCMeta):
    @abstractmethod
    def study(self):
        pass
 
    @abstractmethod
    def go_to_school(self):
        pass
 
class Student(StudentBase):
    def study(self):
        print('do study')
    
    def go_to_school(self):
        print('go school')
 
james = Student()
james.study()
james.go_to_school()

추상클래스는 파생 클래스가 반드시 구현해야 하는 메서드를 정해줄 수 있다.

추상클래스의 추상메서드를 다 구현했는지 확인하는 시점은 파생클래스의 인스턴스를 만들 때 이다. 위 코드에서는 james = Student() 코드 부분이다.

 

36.6.1 추상메서드를 빈 메서드로 만드는 이유

추상 클래스는 인스턴스로 만들 수가 없다. 추상클래스를 인스턴스로 만드려고 하면 에러를 발생한다. 그래서 추상클래스의 추상 메서드는 빈 메서드로 만든다. 인스턴스를 만들 수 없기 때문에 추상메서드를 호출할 일도 없기 때문이다.

추상클래스는 오로지 상속에만, 파생클래스에서 반드시 구현해야 할 메서드를 정해줄 때만 사용한다.

 

36.7 퀴즈

정답은 c이다.

정답은 d이다.

정답은 a,d이다. 함수 이름을 같게 만드는것이 메서드 오버라이딩이다. 오버라이딩 된 메서드에서도 super()로 기반 클래스의 메서드를 호출할 수 있다.

정답은 b,e이다.

 

36.8 연습문제: 리스트에 기능 추가하기

정답은 다음 코드와 같다.

class AdvancedList(list):
    def replace(self, target, change):
        while target in self:
            self[self.index(target)] = change

list클래스를 상속받은 클래스에 replace 메서드를 만들어서 리스트에서 바꿀 요소를 지정한 요소로 바꾸는 메서드를 만들었다.

 

36.9 실습문제: 다중 상속 사용하기

정답은 다음 코드와 같다.

class Bird(Animal, Wing):
    def fly(self):
        print('날다')

Bird클래스는 Animal 과 Wing 클래스를 상속받으며 fly라는 메서드를 갖는다.

 

Unit 37. 두 점 사이의 거리 구하기

37.1.1 클래스로 점 구현하기

2차원 평면에서 위치를 표현하려면 x와 y값이 필요하다. 다음과 같이 Point2D로 점을 만드는 클래스를 구현하고 점 두 개를 만들었다.

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

2차원 평면에서 두 점을 표시해보면 다음 모양과 같다.

 

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

두 점의 거리를 구하려면 피타고라스 정리를 이용해야 한다. 

피타고라스 정리는 a^2 * b^2 = c^2 이고, p1과 p2로 직각 삼각형을 그리면 다음과 같다.

피타고라스 정리를 이용하려면 먼저 변 a,b의 길이를 알아야 한다. a,b의 길이는 다음과 같다.

a = p2.x - p1.x
b = p2.y - p1.y

피타고라스 정리에서 c의 길이를 구하려면 제곱근을 구해야한다. 파이썬에서 제곱근은 math 모듈의 sqrt 함수를 이용하여 구할 수 있다.

p1과 p2의 거리를 구하는 코드는 다음과 같다.

import math

class Point2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
p1 = Point2D(x=30, y=20)
p2 = Point2D(x=60, y=50)
 
a = p2.x - p1.x
b = p2.y - p1.y

c = math.sqrt((a*a) + (b*b))
print(c)

거듭제곱을 구할 때는 math모듈의 pow 함수를 사용해도 된다.

math.pow(값,지수)
c = math.sqrt(math.pow(a, 2) + math.pow(b, 2))

또한 파이썬의 거듭제곱 연산자 **를 사용해도 된다.

c = math.sqrt((a ** 2) + (b ** 2))

 

절댓값 함수

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

abs(값)
math.fabs(값)

 

namedtuple 사용하기

collections모듈의 namedtuple함수를 사용하여 각 요소에 이름을 지정해 줄 수 있다. namedtuple은 자료형 이름과 요소의 이름을 지정하면 클래스를 생성해준다. 자료형 이름은 문자열, 요소의 이름은 문자열 리스트로 넣어줘야 한다.

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

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

다음은 namedtuple를 이용하여 두 점 사이의 거리를 구한 것이다.

import math
import collections
 
Point2D = collections.namedtuple('Point2D', ['x', 'y']) 
 
p1 = Point2D(x=30, y=20) 
p2 = Point2D(x=60, y=50)   
 
a = p1.x - p2.x  
b = p1.y - p2.y   
 
c = math.sqrt((a * a) + (b * b))
print(c)    

 

37.2 연습문제: 사각형의 넓이 구하기

정답은 다음 코드와 같다.

wid = abs(rect.x2 - rect.x1)
hei = abs(rect.y2 - rect.y1)
area = wid * hei

높이와 밑변의 길이는 경우에 따라 음수가 될수 있기 때문에 abs함수를 이용하여 절댓값으로 만들었다.

 

37.3 두 점 사이의 거리 구하기

정답은 다음 코드와 같다.

length = 0
for i in range(len(p)-1):
    a = p[i+1].x - p[i].x
    b = p[i+1].y - p[i].y
    length += math.sqrt((a*a) + (b*b))

반복문을 활용해서 각 점사이의 거리를 구한 후 값들을 더해줬다.

+ Recent posts