Skip to main content

Command Palette

Search for a command to run...

2020년 2학기 파이썬 두번째 스터디 정리

Updated
5 min read

오늘은 클래스 사용법, raise 사용법, exception 처리, tuple 자료형, set 자료형을 다루었고, iterator와 관련된 map 함수도 짧게 다루었습니다.

클래스

클래스를 선언하는 방법은 가장 간단한 방법은 pass를 사용하는 것입니다.

class Car:
    pass

이렇게 선언한 클래스는

car = Car()

처럼 초기화할 수 있습니다. 그리고 pass를 사용한 선언은 아래 코드와 똑같다고 보시면 됩니다.

class Car:
    def __init__(self):
        pass

아래와 같은 방식으로 클래스에 메소드를 선언하고 사용할 수 있습니다.

class Car:
    def wheels(self):
        return 4

car = Car()
print(car.wheels()) # 4 출력

클래스를 사용하는 이유엔 여러가지가 있습니다. 예를 들어 약마다 작용이 다르므로 먹었을 때의 효과 역시 다를 것이고, 이를 코드로 표현할 때 쓰이는 도구가 클래스입니다.

또한, 클래스는 관련된 변수를 묶어주는 데에도 사용됩니다. 게임 플레이어가 4명이 있다고 생각합시다. 클래스를 사용하지 않으면 player1_hp, player1_max_hp,player1_mp, player1_max_mp,player2_hp, player2_max_hp,player2_mp, player2_max_mp, player3_hp, ... 이런 식으로 변수가 매우 많이 필요해집니다.

변수가 많으면 실수할 가능성도 올라가고, 유지보수에도 좋지 않습니다. 따라서 이런 경우에도 클래스를 사용합니다.

상속

아래 코드를 보면 Car 클래스는 run, stop 이라는 이름의 메소드를 정의하지도 없고, running이라는 프로퍼티도 정의하지 않습니다.

class Vehicle:
    def run(self):
        print('Vehicle.run()')
        self.running = True
    def stop(self):
        print('Vehicle.stop()')
        self.running = False

class Car(Vehicle):
    pass

car = Car()

car.run()
assert car.running

car.stop()
assert not car.running

그럼에도 위 코드가 잘 실행되는 건, Car이라는 클래스가 Vehicle이라는 클래스를 상속하기 때문입니다.

오버로딩

class Vehicle:
    def run(self):
        print('Vehicle.run()')
        self.running = True
    def stop(self):
        print('Vehicle.stop()')
        self.running = False

class Car(Vehicle):
    def run(self):
        print('Car.run()')
        self.running = True

car = Car()

car.run()
assert car.running

car.stop()
assert not car.running

위 코드는

Car.run()
Vehicle.stop()

을 출력합니다. Vechicle 클래스의 run이라는 메소드가 호출되지 않은 것이죠. 이를 오버라이딩이라고 부릅니다.

super 호출

메소드를 오버라이딩한 경우에도 아래처럼 부모 클래스의 함수를 호출할 수 있습니다.


class Vehicle:
    def __init__(self):
        self.running = False

    def run(self):
        print('Vehicle.run()')
        self.running = True

    def stop(self):
        print('Vehicle.stop()')
        self.running = False


class Car(Vehicle):
    def run(self):
        print('Starting Car.run()')

        # super()을 써야합니다.
        super().run()

        print('Finishing Car.run()')


car = Car()
car.run()
car.stop()

위 코드는

Starting Car.run()
Vehicle.run()
Finishing Car.run()
Vehicle.stop()

를 출력합니다.

오류 발생 (raise)

0으로 나누기를 시도했을 때 한국어로 0으로 나눌 수 없습니다라는 에러를 던지는 함수를 파이썬으로 구현하면 다음과 같습니다.


def divide(a, b):
    if b == 0:
        raise ArithmeticError('0으로 나눌 수 없습니다')

    return a // b

예외 처리

프로그램이 실행되다보면 많은 예외 케이스가 있습니다. 와이파이가 끊긴다던가 input 파일이 없다던가...

try:
    f = open('nonexistant-file.txt', 'r')
    print('읽기 성공')
except FileNotFoundError as e:
    print('읽기 실패')
    print(e)

위 프로그램을 실행하면

읽기 실패
FileNoutFoundError (# elided)

이 출력됩니다. f = open('nonexistant-file.txt', 'r') 이 줄에서 exception이 발생하기에, 아래 줄은 실행되지 않은 것이죠.

여러가지 오류 처리

except 문을 여러 개 쓰면 여러가지 에러를 잡을 수 있습니다.

이때 주의하실 점이 하나 있는데요, 오류 클래스 간의 상속관계가 있다면 자식 클래스에 대한 except문이 먼저 와야 한다는 점입니다.

try:
    res = 5 // 0
    # 순서 중요 (클래스 상속)
except ZeroDivisionError as e:
    print('ZeroDivisionError 발생')
except ArithmeticError as e:
    print('ArithmeticError 발생')

위 코드는 ZeroDivisionError 발생을 출력합니다. 하지만

try:
    res = 5 // 0
    # 순서 중요 (클래스 상속)
except ArithmeticError as e:
    print('ArithmeticError 발생')
except ZeroDivisionError as e:
    print('ZeroDivisionError 발생')

위 코드는 ArithmeticError 발생을 출력합니다. ZeroDivisionErrorArithmeticError를 상속하기 때문인데,

except ZeroDivisionError as e:
    print('ZeroDivisionError 발생')

이 부분이 실행되지 않는 dead code가 됩니다

전혀 다른 오류인 경우 순서가 중요하지 않습니다.

try:
    # 주석 해제된 경우 아래의 연산이 실행되지 않음
    # f = open('non-existing-file.txt', 'r')

    res = 5 // 0
    # 순서 중요 (클래스 상속)
except ZeroDivisionError as e:
    print('ZeroDivisionError 발생')
    print(e)
except ArithmeticError as e:
    print('ArithmeticError 발생')
    print(e)
except FileNotFoundError as e:
    print('FileNotFoundError 발생')
    print(e)

tuple 자료형

학교 수업 시간에 다루지 않았다고 해서 튜플 내용도 다루었습니다. 파이썬의 tuple 타입은 상당히 편리합니다.


arr = [1, 2, 3, 4, 5]

# 주의: 배열의 길이가 왼쪽의 변수 개수와 같아야 함
a, b, _, c, _ = arr

print(a)
print(b)
print(c)

위 코드는

1
2
4

를 출력합니다.

tuple 반환

파이썬에서는 함수에서 tuple 자료형을 반환할 수 있습니다.

def verify(s):
    if 6 <= len(s) <= 12:
        return True, ""

    return False, "입력한 값이 올바르지 않습니다"


success, msg = verify("1000000")
# success, msg = verify("100000000258y7034957823")

print('success:', success)
print('msg:', msg)

위 코드를 보면 return 문의 인자가 여러 개이고, 함수를 호출한 쪽에선 success, msg 처럼 destructuring 하는 걸 볼 수 있습니다.

set 자료형

set은 파이썬이 기본으로 제공해주는 기본 타입 중 하나입니다. list 타입과는 다르게 set의 경우 종북된 원소를 허용하지 않습니다. 배열에서 중복된 원소를 제거하고 싶을 때 다음과 같이 사용할 수 있습니다.


arr = [1, 3, 5, 3, 1, 6, 3, 2]
print(arr)  # [] 사용
s = set(arr)  # 오브젝트 개념, 키가 set안에 존재하면 (값이) true, 없으면 false

print(s)  # {} 사용

for n in s:
    print(n)

참고로 set 타입을 print 함수를 이용해 출력하면 배열과 달리 {}로 감싸져있습니다. 이는 중복된 원소를 허용하지 않음을 나타냅니다.

참고로 set 자료형 역시 iterable이고, 아래와 같이 for-in 문의 오른쪽에 넣을 수 있습니다.


arr = [1, 3, 5, 3, 1, 6, 3, 2]
for n in set(arr):
    print(n)

iterator - map

map은 적용할 함수와, 원본 iterator를 받아서 각 원소에 제공된 함수를 적용한 뒤, 해당 함수의 반환값을 뱉는 iterator를 반환하는 함수입니다.

말로 하니까 좀 복잡한데, 아래 코드의 경우 각 원소에 1을 더한 iterator를 반혼합니다.

scores = [1, 6, 5, 6, 7, 8, 9, 3, 2, 1, 1]

def add_1(n):
    return n + 1

m = map(add_1, scores)

참고로 iterator들은 일반적으로 print 할 경우 원소들의 값을 뱉지 않습니다. 원소들의 값을 출력할 떈 다음과 같이 list로 감싸면 됩니다.

scores = [1, 6, 5, 6, 7, 8, 9, 3, 2, 1, 1]

def add_1(n):
    return n + 1

m = map(add_1, scores)
print(list(m))

More from this blog

한국의 학벌에 대한 생각

내 블로그의 제목이 kdy1: The way I think 인만큼 앞으로는 내 생각을 더 자주 올리려고 한다. 한국 기준으로, 학벌은 사람을 볼 때 꽤나 유용한 지표이지만, 절대적이지는 않다. 경험적인 얘기일 뿐이지만, 성균관대학교 자퇴생으로서 느낀 것들이 몇 가지 있다. 대학까지 간 사람의 학벌은 학습 능력 x 성실함 에 대체로 비례한다. 그래서 의미가

Apr 3, 20261 min read

인간 지능에 대한 메모장

최종 업데이트: 2026/03/15 지능의 유전 현재 인류 기준으로, 고지능자는 고지능 유전자가 많이 겹친 사람이다. 지능의 유전엔 X 염색체가 매우 중요한 역할을 한다. 그리고 이게 남자와 여자의 지능 분포 차이를 만든다. 극상위권에 여자가 거의 없는 이유가 이것이다. 고지능 X 염색체가 여자한테서 발현되려면 2개가 있어야 한다. 이는 인간의 생

Mar 15, 20262 min read

Ai 코딩 팁 2 (한국어)

발표 자료: https://gamma.app/docs/AI--2a52e7tk3eb1ch1 AI 활용법 관련해서 간단하게 발표를 했다. 발표 자료 앞쪽은 전에 블로그에 올린 글이랑 같은 내용이다. 이 글에서는 기존 글에서 다루지 않은 내용들을 다루겠다. 에러 메시지 및 로깅 구체적 타입 및 스키마 활용 any 타입은 사람에게도 위험하지만, AI에게는 더 위험하다. 마찬가지로, JSON.parse처럼 아무 제약 없는 파싱 느슨한 인터페이스 ...

Jan 30, 20265 min read

kdy1: The way I think

233 posts