[Python기초]class 연습

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!


파이썬 클래스(class) 연습

오늘은 객체지향 프로그래밍의 꽃 클래스를 배웠다.

클래스를 가장 쉽게 설명할 수 있는 방법 중 하나는, 붕어빵이다.

붕어빵 틀에서 붕어빵을 여러 개 만들어 낸다.

그것처럼 클래스도 여러 개의 인스턴스를 만들어 낸다.

그리고 클래스는 함수변수를 포함해야 한다.

나중에도 매우 많이 사용될 중요하고 기초적인 부분이기 때문에,

그 개념을 잘익히기 위해 연습문제를 다시 풀어보았다.


문제1: 🐕강아지 클래스를 작성하고 인스턴스를 생성하시오.


조건

  1. Default 매개변수를 갖는 생성자를 정의
  2. 필드는 breed, size, age, color를 넣을 것.
  3. 필드중 breed는 비공개필드로 정의
  4. 메소드는 sleep, sit, run, eat 이며 각 행동의 내용이 출력되게 만들 것
  5. 필드의 값을 변경하고, 변경하는 메소드를 정의
  6. 인스턴스를 생성하되, 인수의 수를 다양하게 입력하여 생성하는 코드 작성
  7. 개의 정보(종, 크기, 나이, 색상)를 출력


풀이

  • 조건 1,2,3을 지켜 작성해 보았다.
class Dog:
    def __init__(self, Breed = '?', Size = '?', Age = '?', Color = '?' ):
        self.__Breed = Breed
        self.Size = Size
        self.Age = Age
        self.Color = Color
# class명을 적을 때는 항상 맨 앞글자가 대문자여야 한다. 그래서 Dog
# __init__은 클래스의 배경이라고 생각하면 된다. 
# 매개변수의 self는 class로 만들어질 instance 자기 자신을 가리킬 때 사용
# 조건 2의 필드를 적어준다. 여기서, 조건 1을 지켜주기 위해 매개변수에 ?(잘모른다는 뜻)을 default 값이 되게 해준다.
# def의 하위코드에서는 인스턴스가 만들어질 때 매개변수에 들어올 값이 자기 자신에게 적용되도록 하는 것을 볼 수 있다.
# 여기서 조건 3을 지키기 위해, Breed 앞에 언더바 2개(__)를 붙여 비공개 필드로 만들어준다.

비공개 필드란? 외부에서 직접 사용하지 못하고 클래스 내부에서만 사용가능 한 필드

  • 조건 4를 지켜 작성해 보았다.
    def Eat(self):
        print(f'{self.Color} 색상의 개가 먹이를 먹습니다.')

    def Sleep(self):
        print(f'{self.Color} 색상의 개가 잠을 자고있습니다.')

    def Sit(self):
        print(f'{self.Color} 색상의 개가 앉습니다.')

    def Run(self):
        print(f'{self.Color} 색상의 개가 뛰어 다닙니다.')
        
# 각 행동들에 어울리는 출력문이 나오게 작성했다.
# 여기서 f`string의 {self.Color}란 개 인스턴스들이 갖게될 색상을 의미한다.
  • 조건 5를 지켜 작성해 보았다.
    def getBreed(self):
        return self.__Breed # getBreed() 메소드를 사용하면, Breed의 값을 반환해준다.
    def setBreed(self, Breed):
        self.__Breed = Breed # setBreed(Breed) 메소드를 사용하면, 인스턴스의 Breed 값을 변경해준다.

    def getSize(self):
        return self.Size
    def setSize(self, Size):
        self.Size = Size

    def getAge(self):
        return self.Age
    def setAge(self, Age):
        self.Age = Age

    def getColor(self):
        return self.Color
    def setColor(self, Color):
        self.Color = Color
        
# 조건 3에서 breed를 비공개 필드로 설정해 놓았다.
# 그래서 클래스로 인스턴스를 만들어서 print(인스턴스.Breed)를 하게 된다면 에러가 난다.
# 이런 이유로 각 필드들을 쉽게 불러오고 변경할 수 있는 함수를 만들었다.
# Breed, Size, Age, Color 4개의 필드
  • 조건 6을 지켜 작성해 보았다.
dog1 = Dog('Neapolitan Mastiff', 'Large', 5, 'Black')
dog2 = Dog('Maltese', 'Small', 2, 'White')
dog3 = Dog('Chow Chow', 'Medium')
dog4 = Dog()

# Dog 클래스를 사용해 dog1...dog4를 만들어준다.
# dog1은 주어진 인수 4개 다 입력
# dog2도 주어진 인수 4개 다 입력
# dog3는 앞의 인수 2개만 입력
# dog4는 입력 X

  • 조건 7을 지켜 작성해 보았다.
def dogInfo(name):
    print(f'품종: {name.getBreed()}')
    print(f'크기: {name.getSize()}')
    print(f'나이: {name.getAge()}')
    print(f'색상: {name.getColor()}')

dog4.setBreed('Jindo') # dog4의 Breed를 Jindo로 변경
dog4.setColor('Yellow') # dog4의 Color를 Yellow로 변경

dog1.Eat() # Eat메소드 확인
dog2.Sleep() # Sleep메소드 확인
dog3.Sit() # Sit메소드 확인
dog4.Run() # Run메소드 확인

dogInfo(dog1)
dogInfo(dog2)
dogInfo(dog3)
dogInfo(dog4)




# 클래스 밖에서 dogINfo함수를 생성했다.
# dog1~4를 넣어서 출력한다.

이제 적은 코드들의 결과를 확인해보자. Default값과 메소드들이 잘 적용된 상태로 출력된다.

Black 색상의 개가 먹이를 먹습니다.
White 색상의 개가 잠을 자고있습니다.
? 색상의 개가 앉습니다.
Yellow 색상의 개가 뛰어 다닙니다.
품종: Neapolitan Mastiff
크기: Large
나이: 5
색상: Black
품종: Maltese
크기: Small
나이: 2
색상: White
품종: Chow Chow
크기: Medium
나이: ?
색상: ?
품종: Jindo
크기: ?
나이: ?
색상: Yellow

문제 2: 🐕문제 1번의 강아지 클래스에서 객체 간의 크기를 비교하고, 연산하는 메소드를 작성해 실행해보시오.

파이썬에는 특별한 메소드가 존재한다. 그것을 매직 메소드(Magic Method)라고 부른다. __메소드이름__의 형태를 가지고 있는데 인스턴스를 생성하고 계산을하거나 비교를 할 때 사용할 수 있는 다양한 메소드를 가지고 있다.

위의 1번 문제를 푼 상태에서, 특별한 메소드를 사용하여 더 깊이 파이썬을 연구해보자!


조건

  1. Dog 클래스로 만든 객체 간의 Size 크기를 비교하는 메소드를 작성
  2. Dog 클래스로 만든 객체 간의 Age를 더하고, 빼고, 곱하고, 나누는 메소드 작성
  3. 1번 문제에서 객체의 정보를 함수를 통해 출력했었는데, 매직 메소드를 사용해서 출력해보시오.


풀이

  • 다양한 매직 메소드가 존재하지만 위의 조건을 충족하며 사용할 메소드를 나열해보겠다.

    __ge__() : >=
    __gt__() : >
    __lt__() : <
    __le__() : <=
    __ne__() : !=
    __eq__() : ==
      
    __add__() : +
    __sub__() : -
    __mul__() : *
    __divmod__() : //, %
      
    __init__() : 생성자, 초기화	
    __repr__() : 어떤 객체의 ‘출력될 수 있는 표현’(printable representation)을 문자열의 형태로 반환
    


  1. Dog 클래스로 만든 객체 간의 Size 크기를 비교하는 메소드를 작성

        def __gt__(self, other): # greater than
            return self.Size > other.Size # self인스턴스 사이즈가 other인스턴스 사이즈보다 크다. 
       
        def __ge__(self, other): # greater equal
            return self.Size >= other.Size #self인스턴스 사이즈가 other인스턴스 사이즈보다 같거나 크다.
       
        def __lt__(self, other): # less than
            return self.Size < other.Size # self인스턴스 사이즈가 other인스턴스 사이즈보다 작다.
       
        def __le__(self, other): # less equal
            return self.Size <= other.Size # self인스턴스 사이즈가 other인스턴스 사이즈보다 같거나 작다.
       
        def __eq__(self, other): # equal
            return self.Size == other.Size # self인스턴스 사이즈가 other인스턴스 사이즈가 같다.
       
        def __ne__(self, other): # not equal
            return self.Size != other.Size # self인스턴스 사이즈가 other인스턴스 사이즈가 같지 않다.
       
    # 위에 설명했듯이 비교할때 사용하는 특별한 메소드다.
    # 조건에서는 Size의 크기를 따질 수 있는 비교 메소드다.
    # 비교를 통해 True나 False값을 반환해준다.
    
    • 하지만 개의 사이즈를 Large, Medium, Small로 표기하고 있다. 문자의 크기를 비교할 땐 ASCII코드의 영향을 받아서 결과가 나올 것이라 일반적인 정수나 실수의 비교랑은 차이가 있을 것이다. 우선 결과를 보자.
    • dog1의 Size는 Large, dog2의 Size는 Small이다.
    print(dog1 > dog2)
    print(dog1 >= dog2)
    print(dog1 < dog2)
    print(dog1 <= dog2)
    print(dog1 == dog2)
    print(dog1 != dog2)
    
    False 
    False
    True
    True
    False
    True
    
    • 결과는 ==와 !=만 제외하고 생각한 것과 반대로 논리형 요소를 반환해주고 있다.
    • 문자열의 앞글자인 대문자들의 ASCII 코드를 확인해보자.
    print(ord('L')) # Large
    print(ord('M')) # Medium
    print(ord('S')) # Small
    
    76 # Large
    77 # Medium
    83 # Small
    
    • 이렇기 때문에 메소드를 사용해서 논리형을 반환했을 때 반대로 나온 것이다.
    • Size의 요소를 3가지만 사용하므로, 다행히도 L M S의 크기가 역순으로 정렬되어 있다.
    • 그래서 제대로 된 값을 구하기 위해 위의 비교 메소드를 조금씩 수정해보자.
        def __gt__(self, other):
            return self.Size < other.Size
       
        def __ge__(self, other):
            return self.Size <= other.Size
       
        def __lt__(self, other):
            return self.Size > other.Size
       
        def __le__(self, other):
            return self.Size >= other.Size
       
        def __eq__(self, other):
            return self.Size == other.Size
       
        def __ne__(self, other):
            return self.Size != other.Size
    
    True
    True
    False
    False
    False
    True
    
    • 이제 정상적으로 출력되는 것을 확인할 수 있다.
  2. Dog 클래스로 만든 객체 간의 Age를 더하고, 빼고, 곱하고, 나누는 메소드 작성

        def __add__(self, other):
            return self.Age + other.Age
       
        def __sub__(self, other):
            return self.Age - other.Age
       
        def __mul__(self, other):
            return self.Age * other.Age
       
        def __divmod__(self, other):
            return (self.Age // other.Age, self.Age % other.Age)
       
    # 인스턴스의 필드값들을 연산하기 위해 저 메소드들을 사용했다.
    # 순서대로 덧셈, 뺄셈, 곱셉, 나눗셈의 몫과 나머지
    
    • 해당 메소드를 생성했으니, 메소드를 사용해보자!
    • dog1의 Age는 5, dog2의 Age는 2
    print(dog1 + dog2)
    print(dog1 - dog2)
    print(dog1 * dog2)
    print(divmod(dog1, dog2))
    
    7
    3
    10
    (2, 1) # (몫, 나머지)
    
    • 잘 출력되는 것을 확인할 수 있다.
  3. 1번 문제에서 객체의 정보를 함수를 통해 출력했었는데, 매직 메소드를 사용해서 출력해보시오.

    • 1번 문제에서 객체의 정보들을 출력했을 때 결과는 이렇다.

      품종: Neapolitan Mastiff
      크기: Large
      나이: 5
      색상: Black
      품종: Maltese
      크기: Small
      나이: 2
      색상: White
      품종: Chow Chow
      크기: Medium
      나이: ?
      색상: ?
      품종: Jindo
      크기: ?
      나이: ?
      색상: Yellow
      
    • 나는 여기서 객체를 출력될 수 있는 표현을 하게 만들어주는 매직메소드인 __repr__ 메소드를 사용할 것이다.

          def __repr__(self):
              return f'품종: {self.__Breed}\n크기: {self.Size}\n나이: {self.Age}\n색상: {self.Color}'
             
      # Breed, Size, Age, Color 순으로 나오게 출력문을 구성하고 return 값을 반환해라.
      
      print(dog1)
      print(dog2)
      print(dog3)
      print(dog4)
      
      품종: Neapolitan Mastiff
      크기: Large
      나이: 5
      색상: Black
      품종: Maltese
      크기: Small
      나이: 2
      색상: White
      품종: Chow Chow
      크기: Medium
      나이: ?In
      색상: ?
      품종: Jindo
      크기: ?
      나이: ?
      색상: Yellow
      
    • 잘 출력되는 것을 확인할 수 있다!!!


문제 3: 클래스 상속(Inheritance)

인간이 부모가 자식에게 재산을 물려주는 것과 같은 상속이 파이썬의 클래스에도 존재한다.

클래스의 구성 요소를 상속 해주는 부모 클래스(Super Class)와 상속을 받는 자식 클래스(Sub Class)로 나눌 수 있다.

예를 들어, 자동차라는 객체를 만들기 위한 클래스가 존재한다. 자동차에는 일반 승용차와 트럭 등 일반적인 구성요소가 같지만 용도나 생김새가 다른 종류의 자동차도 존재한다. 그래서 자동차 클래스의 구성요소를 승용차 클래스트럭 클래스가 받아서 각 클래스들이 자신들의 필요에 의해 추가해야 하거나 빼야하는 부분들을 건들여서 인스턴스를 생성할 수 있는 것이다. 이 때 자동차 클래스가 부모 클래스, 트럭이나 승용차 클래스가 자식 클래스다.

비슷한 예제로 개념을 확실히 이해해보자.

우리 지구에는 동물과 식물이 있다. 동물이 식물과 다른 점이 있다면 그것은 아마도 소리를 낼 수 있다는 것이다. 그런 동물 중에서도 사람, 개, 고양이 등 다양한 동물이 존재하고 있다. 동물의 종류마다 소리를 내는 방식이 다르고, 외형, 사는 곳 등 여러가지가 다를 것이다.

동물을 부모클래스로 개나 고양이 등의 자식클래스를 만들어 보자.


조건

  1. Animal(동물) 클래스는 부모 클래스다.
    • 메소드 : talk(), eat(), sleep()
    • 필드 : age, leg, color, place
  2. Dog(개) 클래스는 자식 클래스다.
    • 메소드의 talk()를 재정의해서 사용
    • 필드는 자유롭게 재정의
  3. Cat(고양이) 클래스는 자식 클래스다.
    • 메소드의 talk()를 재정의해서 사용
    • 필드는 자유롭게 재정의


풀이

  1. Animal 클래스
class Animal:
    count = 0 # 자식 클래스를 포함한 여러 클래스에서 공유할 변수다.

    def __init__(self, age='?', leg='?', color='?', place='?'):
        self.age = age
        self.leg = leg
        self.color = color
        self.place = place
        Animal.count += 1
        print(f'{Animal.count}번째 동물이 탄생했습니다.')
        # Animal 클래스의 배경을 깔아준다(생성자). 각 매개변수들의 기본값을 내 주관대로 ?로 지정
        # 매개변수에 입력되는 값으로 self.필드의 값이 변하게 해준다.
        # 그리고 한 마리의 동물이 생성될 때마다 count의 수가 올라가게 클래스 변수를 사용해준다.
        # 클래스 변수 Animal.count는 Animal을 포함한 자식클래스들이 객체를 생성할 때마다 1씩 추가된다.
        # 그리고 생성될 때마다 'n'번째 동물이 탄생되었다는 알림을 출력해준다.
        
    def talk(self):
        print('hmm..') # 모든 동물이 낼 수 있는 숨소리 'hmm..'을 talk() 메소드로 생성

    def eat(self):
        print('eating') # 먹는다는 것을 뜻하는 'eating'을 eat() 메소드로 생성

    def sleep(self):
        print('zzz...') # 잠자는 것을 표현하는 'zzz..'를 sleep() 메소드로 생성

    def __repr__(self):
        return f'나이: {self.age}\n다리 개수: {self.leg}\n색상: {self.color}\n사는 곳: {self.place}'
    # 문제 2번에서 사용한 것처럼 인스턴스를 '표현'하기 쉽게 만드는 __repr__ 메소드 사용
  1. Dog 클래스
class Dog(Animal): # class 자식클래스(부모클래스):
    def __init__(self, age, leg, color, place, hairLen): 
        # 개는 털이 있는 동물이라서 털이 장모인지 단모인지 뜻하는 hairLen 필드 추가 
        super().__init__(age, leg, color, place)
        # 부모(super) 클래스 Animal에게 물려받을 구성요소를 정하는 코드 
        self.hairLen = hairLen # 추가한 필드와 매개변수를 이어줌

    def talk(self):
        print('Wal! Wal Wal!!') # 조건 2번. 개는 '왈! 왈!왈!' 짓는다. talk() 재정의

    def __repr__(self):
        return f'나이: {self.age}\n다리 개수: {self.leg}\n색상: {self.color}\n사는 곳: {self.place}\n털 길이: {self.hairLen}'
    # Dog 클래스를 사용해 만든 인스턴스의 정보를 출력하기 편하게 만듦.
  1. Cat 클래스
class Cat(Animal): # class 자식클래스(부모클래스):
    def __init__(self, age, leg, color, place, hairLen): 
        # 고양이도 털이 있는 동물이라서 털이 장모인지 단모인지 뜻하는 hairLen 필드 추가 
        super().__init__(age, leg, color, place)
        # 부모(super) 클래스 Animal에게 물려받을 구성요소를 정하는 코드 
        self.hairLen = hairLen # 추가한 필드와 매개변수를 이어줌

    def talk(self):
        print('Meow~~~~') # 조건 3번. 고양이는 '미유~' 하고 소리를 낸다. talk() 재정의

    def __repr__(self):
        return f'나이: {self.age}\n다리 개수: {self.leg}\n색상: {self.color}\n사는 곳: {self.place}\n털 길이: {self.hairLen}'
    # Cat 클래스를 사용해 만든 인스턴스의 정보를 출력하기 편하게 만듦.
  • 이제 각 클래스들을 사용해볼 시간이 왔다.
  • 우선 Animal 클래스 먼저 사용해 보겠다.
animal1 = Animal(place = 'sea') # animal1에 Animal 클래스의 객체 생성
print(animal1)
1번째 동물이 탄생했습니다.
나이: ?
다리 개수: ?
색상: ?
사는 곳: sea

매개변수 place = ‘sea’와 나머지 디폴드 값이 잘 적용되어 정보가 출력되었고, 첫 객체 생성으로 ‘1번째 동물이 탄생했다는 ‘ 알람이 출력된다.

  • 다음은 Dog와 Cat 클래스를 사용해보자.
cat1 = Cat(3, 4, 'white', 'land', 'short')
dog1 = Dog(1, 4, 'black', 'land', 'long')
# 순서대로 나이, 다리의 개수, 색상, 사는곳, 털의 길이

cat1.talk() # 자식 클래스에서 재정의한 talk()
dog1.talk() # 자식 클래스에서 재정의한 talk()

print(dog1) # 인스턴스의 정보 출력
print(cat1)
2번째 동물이 탄생했습니다.
3번째 동물이 탄생했습니다.
Meow~~~~
Wal! Wal Wal!!
나이: 1
다리 개수: 4
색상: black
사는 곳: land
털 길이: long
나이: 3
다리 개수: 4
색상: white
사는 곳: land
털 길이: short
  • Iterable한 리스트를 사용해서 객체를 한꺼번에 생성할 수도 있다.
animals = [Cat(1,4,'white','land','long'), Cat(5,4,'gray','land','short'), Dog(2,4,'black','land', 'long')]

for animal in animals:
    animal.talk()
4번째 동물이 탄생했습니다.
5번째 동물이 탄생했습니다.
6번째 동물이 탄생했습니다.
Meow~~~~
Meow~~~~
Wal! Wal Wal!!

느낀 점

사실 수업을 파이썬 기초 수업을 들으며 제일 어려웠던 부분은 아니였다. 하지만 서비스를 만들거나 무엇인가를 할 때 처음 만들어놓은 대로 사용하는 것이 아니라

'’다양한 니즈나 필요에 맞춰 바꿀 때 써먹을 때 큰 틀을 두고 이런 개념으로 사용할 수도 있겠구나.’

라는 생각을 하게 되었다.

클래스가 객체지향 프로그래밍의 인 이유를 확장성 이라고 생각하면 되려나?…

사실 적으면서도 무슨 말을 하려는지 잘 모르겠지만..ㅋㅋㅋ

나중에 과정이 끝나고 무언갈 만들어볼 때 유용하게 써먹어야겠다. 📷

2022

[web]jQuery 복습 3

2 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]jQuery 복습 2

11 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]jQuery 복습 1

16 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리4

6 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리3

6 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리2

6 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]JavaScript 정리1

7 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]CSS 기초 정리

9 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[web]HTML 기초 정리

2 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

[Pandas]pandas 연습

3 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

맨 위로 이동 ↑

2021

[Python기초]module

1 분 소요

[Noitce] 고쳐야하거나 틀린 것이 있으면 말씀해주세요!

맨 위로 이동 ↑