supergravity

파이썬 - Object-Oriented Programming (OOP) 기초 - 보완 필요 본문

콘텐츠/파이썬 -OOP

파이썬 - Object-Oriented Programming (OOP) 기초 - 보완 필요

supergravity 2021. 9. 6. 17:42

0. Object-Oriented Programming (OOP) 

OOP는  객체를 기반으로 하여 프로그래밍을 하는 방법을 말합니다.

여기서 말하는 객체는 클래스의 인스턴스입니다.

객체가 클래스의 인스턴스란 말이 무엇일까요?

 

먼저 임기의 집합이 있다고 상상을 해봅시다. 

집합 안에는 생물들이 있습니다.

생물 중에는 사람과 나무들이 존재합니다.

사람들은 모두 2명이고 이름은 김과 이입니다.

사람들은 나무의 열매를 따먹으며 생활합니다.

나무는 사과나무 2개가 존재 하지만 높이가 다릅니다.

 

이를 OOP적으로 해석해 봅시다.

생물이라는 가장 큰 클래스가 있습니다.

이 클래스 안 해는 사람과 사과나무 클래스가 존재합니다.

사람과 사과나무 클래스는 생물이 클래스가 가지고 있는 고유의 특성을 가지고 있습니다.

사람클래스의 인스턴스로 김과 이가 있고 나무의 열매를 따먹습니다.

사과나무클래스의 인스턴스로 높이가 다른 사과나무 2개가 있습니다.

 

OOP 클래스 구라 구현 코드

 

생물클래스:

    살아있음

 

사람클래스 (상위 클래스는 생물 클래스임):

    살아있음(생물 특징임)

    머리가있음

    이름 :

    열매따먹기()

 

사과나무클래스 (상위 클래스는 생물 클래스임):

    살아있음(생물 특징임)

    높이:

    열매생산()

 

사람들의 경우 이름(attributes or properties)이라는 속성과

나무의 열매를 따먹는(methods) 행동양식을 가지고 있습니다.

또한 생물클래스의 특징인 살아있음이라는 속성을 가지고 있습니다. 이들은 사람들의 공통 속성으로 사람클래스에서 정의되어 있습니다.

 

이 예에서 볼 수 있듯이 객체가 클래스의 인스턴스란

추상적인 클래스에 해당하는 실제 존재를 말합니다.

 

1. 무지성 네안데르탈인 식으로 구현해 보기

위에 정리한 OOP의 예를 파이썬으로 구현해 봅시다.

 

위에서 정의한 구라 구현을 이용하여 다른 사람들이 코드를 보더라도

클래스의 정이가 어떠한지를 알려 주었습니다.

그리고 파이썬의 기본 데이터 구조인 리스트와 함수를 활용하여 클래스의 오브잭트를 구현했습니다.

# OOP 클래스 구라 구현 코드

# 생물클래스:

#     살아있음



# 사람클래스 (상위 클래스는 생물 클래스임):

#     살아있음(생물 특징임)

#     이름 :

#     열매따먹기()



# 사과나무클래스 (상위 클래스는 생물 클래스임):

#     살아있음(생물 특징임)

#     높이:

#     열매생산()


def get_and_eat():
    print("열매 획득")
    print("와 맛있다")
def make():
    print("사과 생성됨 ㅎ")
  

kim = ["살아있음", "머리있음","김", get_and_eat()]
lee = ["살아있음", "머리없음","이", get_and_eat()]

tree_1 = ["살아있음", 10, make()]
tree_2 = ["살아있음", 5, make()]

 

실제 이게 이론적으로 구현이 된 거긴 하지만......

여러 가지 단점이 존재합니다.

 

첫째는 오브잭트의 리스트 인덱스에 해당하는 데이터에 대해서 기억을 해야 한다.

둘째 리스트를 이용하여 오브잭트를 만들 때 순서나 크기가 틀리더라도 안전장치 없이 생성이 된다.

셋쨰 파이썬의 기본적인 기능을 사용하여 만들기 때문에 자유도가 높습니다.

그래서 사람들 마다 개성 있는 코드를 작성하게 된다. 결과적으로 다른 사람 코드를 보기 싫어진다.

=> 이러한 이유는 코드의 재사용률을 감소시켜 시간 낭비하게 만든다.

 

위와 같은 코드로 작성하게 되면 협업 시 엄청난 시간낭비를 하게 됩니다.

그래서 파이썬에서는 OOP를 빠르고 일관성 있게 구현할 수 있는 기능을 제공하고 있습니다.

 

2. 호모 사피엔스처럼 구현하기

파이썬에서 함수를 정의할 때 def라는 키워드를 제공하고 있습니다.

이러한 키워드를 클래스에 대해서도 제공을 하고 있는데 그건 class입니다!

함수를 정의할 때와 마찬가지로 키워드 뒤에 클래스 이름 그리고 :를 순차적으로 작성해야 합니다.

 

class Life:
    pass

class Person:
    pass

class Tree:
    pass

 

파이썬에서 클래스의 이름은 CapitalizedWords를 사용합니다.

이건 대부분의 개발자가 사용하는 방법이니 객기 부리지 말고 그냥 사용합시다.

 

클래스 내에 작성된 코드는 pass만 작성되어 있는 상태입니다.

대게 pass는 나중에 작성할 코드 부분을 나타낼떄 사용합니다.

만약 pass가 없으면 오류가 떠 다름 부분의 코드를 수정할 때 방해가 됩니다.

 

 

pass를 해두어 오류를 방지합시다.

기본 세팅은 되었으니 하나씩 구현해 봅시다.

먼저 가장 상위 클래스인 Life에 대해서 해봅시다.

 

class Life:
    is_ok = True

class Person(Life):
    pass

class Tree(Life):
    pass

클래스 라이프의 본문에 살아 있는지를 나타내는 속성(attribute)을 생성하였습니다.

그리고 Person과 Tree의 상위 클래스가 Life라는 사실을 (Life)를 추가하여 설정했습니다.

 

다음으로  Person을 구현해 봅시다.

class Life:
    is_ok = True

class Person(Life):
    have_hands = True
    def __init__(self, name):
        self.name = name
        
    def get_and_eat(self):
        print(self)
        print("열매 획득")
        print("와 맛있다")


class Tree(Life):
    pass

Person이라는 클래스의 3가지 종류의 문법 방식이 사용되었습니다.

3가지의 방법을 통해 2가지 속성과(attribute)와 열매를 따먹는 메서드(Methdod)를 구현했습니다.

 

파이썬 클래스에서 속성을 정의하는 방법은 두 가지가 있습니다.

인스턴스 속성(instance attributes), 클래스 속성(class attributes)입니다.

 

메서드를 정의하는 방법에는 

인스탄스 메서드(instance method)가 있습니다.

 

2.1 인스턴스 속성(instance attributes)

인스턴스 속성의 경우 오브잭트(클래스의 인스턴스)의 고유한 속성을 정의할 때 사용합니다.

위의 예제에서 __int__() 함수를 이용하여 인스턴스 속성을 정의할 수 있습니다.

__init__() 함수는 파이썬에서 OOP를 체계적으로 작성을 돕기 위해 만든 특별메서드중 하나입니다.

__init__() 말고도 여러 가지 함수가 존재하는 데 모두 양 쪽에 __가 붙어 있습니다.

이를 파이썬 개발자들은 던더라고 부릅니다.

클래스 내에서 개인적인 함수를 작성할 때는 특별메서드와 구별하기 위해서 던더 방법을 사용하지 않는 것이 좋습니다.

언제 특별메서드

에 새로운 함수가 추가될지 모르기 때문입니다.

 

그러면 다시 __init__() 함수에 대해서 이야기해봅시다.

 __int__() 함수의 파라매터를 살펴보면 self와 name이 있습니다.

name의 경우 사람의 이름을 나타내는 파라매터 이기에  사람의 이름을 파라매터로 받아 오브잭트에 저장하겠구나!

라고 금방 눈치를 챌 수 있습니다.

그러면 self는 뭘까요?

OOP의 경우 메모리 효율성을 위해 클래스에서 생성된 인스턴스들은 클래스 함수를 공유합니다.

그래서 클래스 내부의 함수 입장에서는 어떤 오브잭트가 실행될 것인지 알아야 합니다.

이를 self 파라매터를 통해서 함수에게 어떤 오브잭트인지 알려줍니다.

 

note : 파이썬 에서 제공하는 특별 메서드와 자체적으로 제작한 메서드는 작동방식이 약간 다르다.

나중에 다른 글에서 알아보자.

 

정리를 해보면 클래스가 처음 생성이 되면 __init__함수가 실행이 되고 self(오브잭트 정보)와 name을 이용하여 

인스턴스 속성(instance attributes)을 정의합니다.

 

위 예제는 이러한 특성을 이용하여 인스턴스의 속성을 오브잭트가 생성될 때 추가돼도 구현한 것입니다.

 __int__() 함수의 파라매터를 살펴보면 self와 name이 있습니다.

name의 경우 사람의 이름을 나타내는 파라매터 이기에 

self가 파라매터로 들어가는 이유는 무엇일까요?

구조적으로 메모리 효율성을 위해 오브잭트들이 함수를 공유하도록 프로그래밍하였기 때문입니다.

name의 경우 

 

2.2 클래스 속성(class attributes) 

이와 반대로 클래스 속성은 모든 오브잭트가 같은 속성을 가지고 있을 때 사용하는 속성입니다.

그래서 self라는 키워드도 필요가 없습니다.

또한 메모리 효율성을 위해서 모든 오브잭트들은 클래스에 저장된 값을 공유합니다.

위에서 설명한 함수와 같은 맥락입니다.

 

2.3 인스턴스 메서드(Instance Methods)

인스턴스 메서드는 클래스 안에 정의된 함수들입니다.

이 메서드들은 인스턴스만이 사용할 수 있어 인스턴스 메서드라고 불립니다.

또한 인스턴스 메서드는 __init__(self,)와 같이 첫 번째 파라매터가 self입니다.

이 self 파라매터를 통해요 오브잭트의 정보를 받아옵니다.

 

__init__()에서 생성된 인스턴스 속성의 경우 dot을 이용해 접근하여 이용할 수 있습니다.

 

나머지 막일을 진행합시다...........

class Life:
    is_ok = True

class Person(Life):
    have_hands = True
    def __init__(self, name):
        self.name = name

        
    def get_and_eat(self):
        print(self)
        print("열매 획득")
        print("와 맛있다")
        
   

class Tree(Life):
    def __ini__(self, height):
        self.height = height
    def _make(self):
        print(f"{self.name} 에서 열매 생성!")

 

3. 오브잭트 생성

 

자 위에 고생하여 만들어 놓은 클래스를 이용하여 실제 오브잭트를 만들어 봅시다.

오브잭트를 생성시키고 변수에 넣어 봅시다.

kim_obj = Person("kim")

이렇게 작성하면 

Person클래스의 init함수가 self와 "kim"을 가지고 오브잭트를 생성하고

생성된 오브잭트를 kim_obj의 레퍼런스로 정의를 합니다.

 

만약 "kim"이 변수로 드어가지 않았을 때를 실험해 봅시다.

__init__함수의 name 파라매터가 부족하여 오류가 나고 있습니다.

 

다시 정상적인 케이스로 돌아와 인스턴스 메서드를 실행해 봅시다.

self 파라매터에 관한 정보와 잡다한 문자열들이 출력되고 있습니다.

이전 챕터에서 클래스에 작성된 함수는 공유되고 이를 인스턴스 매서드라고 정의했습니다.

인스턴스 메서드는 오브잭트 모두 가지고 있는 것이 아닌 클래스에서 1개만 보관하고 필요할 때마다 호출하여 사용한다고 했습니다.

이때 어떤  오브잭트가 함수를 사용하는지 알기 위하여 self파라매터를 사용한다고 했는데...

프린트를 이용하여 출력 해보면 self는 생성된 오브잭트의 정보인 것을 확인할 수 있습니다.

 

4. 상속 Inherit

 

 Person과 Tree의 상위클래스(부모클래스)는 Life입니다.

이를 클래스 이름 뒤에 (Life)를 사용하여 구현하였습니다.

상위클래스의 특징을 상속받은 하위 클래스는

상위 클래스의 속성(attribute)과 메서드(method)를 덮어쓰거나 사용할 수 있습니다.

하위 클래스에서 상위클래스에 접근하는 키워드는 super()입니다. 

super()와 dot을 이용하여 속성과 메서드에 접근이 가능합니다.

이 예제는 Life의 속성에 접근하여 출력하는 예제입니다.

 

5. 결론

파이썬을 사용하다 보면 OOP로 코드를 작성할 일이 있을 것이라 생각됩니다.

실제 OOP를 작성할때 파이썬의 특수메서드를 이용하여 작성을 한다면 일관성 있는 코드를 작성할수 있어 매우 좋습니다.

이번 글에서는 __init__()함수만 다루었지만 ..

기초내용을 바탕으로 OOP특수함수를 익힌다면 파이썬 고수가 될수 있는 바탕이 될것 이라 생각이 됩니다.

 

 

 

https://realpython.com/python3-object-oriented-programming/

 

Object-Oriented Programming (OOP) in Python 3 – Real Python

In this tutorial, you'll learn all about object-oriented programming (OOP) in Python. You'll learn the basics of the OOP paradigm and cover concepts like classes and inheritance. You'll also see to how instantiate an object from a class.

realpython.com

 

Comments