OOP 기초개념

2019-04-16

.

그림, 실습코드 등 학습자료 출처 : https://github.com/ythwork

  • OOP는 object oriented programming를 의미한다.

  • 추상화기법으로 추상화를 객체를 통해서 구현하는 것이다.

  • 객체 = 변수 + 함수

  • 관련있는 변수(데이터)와 관려있는 함수(기능,행동)를 하나로 모아두는 것

  • oop를 구현할 때는 class로 구현한다.

(참고로 자바는 클래스를 구현하지는 않는다. 그래서 자바로 클래스를 구현하려면 closer를 쓰면된다.)

  • 예를 들어서 아래와 같이 사람이라는 클래스를 파이썬 코드로 구현해보자
# 사람 클래스
# 멤버 : 어떤 객체가 가지는 특성값
# 메서드 : 객체가 가지는 기능을 표현

class Person:
    # __init__은 생성자라고 하며 객체가 생성할때 이 기능으로 만든다.
    def __init__(self, name, age, height):
        # 사람이라면 누구나 가지고 있는 특성에 대한 값을 정의
        # 사람마다 특성은 갖지만 특성값은 사람마다 다르다.
        # 아래를 인스턴스 멤버라고 한다.
        self.name = name
        self.age = age
        self.height = height
        
    # 인스턴스 메서드 : 기능 혹은 행동
    
    def get_old(self):
        self.age+=1
        
    def walk(self):
        print("walking") 
        
## 객체 혹은 인스턴스
## 위에는 사람이 어떻다는 특성을 나타낸것이지 어떤 사람을 나타내지는 않았다.

## 이렇게 생성된 사람을 객체(오브젝트) 또는 인스턴스라고 한다.
kim = Person('cathy',10,180)
park = Person('minsu',20,170)


kim.get_old()
park.get_old()
## 객체와 클래스는 다른 존재이고
## 객체는 클래스를 참조해서 만들게 된다.
## 각각은 서로 다른 메모리 공간에 저장된다.

kim.name
'cathy'
  • 위에 구현한 코드는 외부에서 인스턴스 멤버에 바로 접근하는데 사실 이런 경우는 전형적으로 안좋은 케이스라고 할 수 있다. 이렇게 구현하면 안된다.

  • 외부에서 어떤 객체의 인스턴스 멤버에 접근할때 바로 접근하지 않고 가능하면 함수 또는 메서드로 접근해야 한다. 인스턴스 멤버에 바로 접근할때는 유저 프로그래머가 실수를 할 수 있기 때문이다.

  • 예를 들어 나이를 양수값만 입력해야 하는데 마이너스값으로 입력한다던가, 이름에 숫자를 입력한다던가 이런문제가 발생하면 프로그램 원천적으로 문제가 발생할 수 있다.

  • 위에 구현한것처럼 하지 않으려먼 사람 클래스에 get_name이라는 함수를 만들어서 함수로 이름을 호출하면 된다.

class Person:
    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height
    
    def get_name(self):
        return self.name
    
    def set_age(self, age):
        if age <= 0:
            print("나이를 잘못 입력했습니다.")
            return
        self.age = age
        
    def get_age(self):
        return self.age
    
    def get_old(self):
        self.age+=1
        
    def walk(self):
        print("walking")   

kim = Person('cathy',10,180)

kim.get_name()
'cathy'
  • 이렇게 나이를 잘못입력했을때 함수내부에서 걸러주는 기능이 있다면 사용자의 실수를 차단할 수 있다. 그래서 외부에서 인스턴트 멤버에 바로 접근하는 것을 막는 이유다.

  • 아래와 같이 프로그램 사용자가 실수로 나이를 -50이라고 입력할 수 있는 경우가 있는데, 위와 같이 프로그램을 구현하면 프로그래밍을 하는 입장에서 원천적으로 이런 실수가 일어나는 것을 막아줄 수 있다.

kim.set_age(-50)
나이를 잘못 입력했습니다.
  • 그런데 유저프로그래머들은 대부분 “다 필요없고 그냥 직접 접근하는 방법처럼 쓰고 싶어” 한다.

  • 그래서 마치 멤버에 바로 접근하는 것처럼 보이지만 내부적으로는 property라는 것을 이용해서 함수를 호출해서 접근하는 방법을 구현할 수 있다.

  • 아래와 같이 setter나 getter라는 것이 있는데 이런 기능을 access function이라고 한다.

  • 예를 들어서 setter는 멤버를 변경하고 싶을때 쓸 수 있고

ex) kim.set_age(50)

  • 예를 들어서 getter 멤버에 접근하고 싶을때 쓸 수 있다.

ex) yang.get_name(), yang.get_age()

  • property를 이용한 person 구현 예시
class Person:
    def __init__(self, name, age, height):
        self.name = name
        self.__age = age
        self.height = height
    
    def get_name(self):
        return self.name
    
    ## 함수이름이 유저 프로그래머가 멤버라고 생각하고 호출하는 이름
    ## 그냥 property만 붙이면 getter이다.
    @property
    def age(self):
        return self.__age
        
    @age.setter    
    def age(self,age):
        
        if age <= 0:
            print("잘못된 값이 입력되었습니다.")
            return
        
        self.__age = age
    
    def get_old(self):
        self.age+=1
        
    def walk(self):
        print("walking")   

kim = Person('cathy',10,180)

kim.age = 20

kim.age
20

[기타 OOP에서 알고 있어야하는 개념]

1) garbage collection

  • 메모리 관리에 관한 얘기이다.

  • 쓸모 없어진 메모리 관리하는 것으로 파이썬은 reference count로 가비지 컬랙션을 구현했다.

  • C언어는 메모리를 할당해주면 일일히 다 삭제해주는 코드가 필요하다.

2) 파이썬의 reference count

  • ex) a = 10 ==> reference count = 1

  • ex) a = 10, b = 10 ==> reference count = 2

  • ex) a = 10, b = 10, c = 10 ==> reference count = 3

  • ex)

a = 10

b = 10

c = 10

del c

==> reference count = 2

  • 이런식으로 변수를 다 삭제해서 더이상 10을 가리키는게 아무것도 없으면 10은 reference count = 0 이 되어 메모리에서 자동으로 삭제된다.

  • 참고로 자주 할당하는 데이터는 메모리에 미리 만들어놓았다. 파이선을 만든 개발자들이 예를들어 1이나 작은 숫자들은 아무래도 자주쓰이기 때문에 메모리에 미리 만들어놓았다.

  • reference count 예시

a = 'hello'

import sys

b = a

sys.getrefcount(a)
4
del b

sys.getrefcount(a)
2
del a

sys.getrefcount(a)
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-7-54f892929e6e> in <module>
      1 del a
      2 
----> 3 sys.getrefcount(a)


NameError: name 'a' is not defined

3) ADT(Abstract Data Type) 추상자료형

  • 어떤 자료구조의 내부구조를 말한다.

  • 이 자료구조가 가지는 기능(오퍼레이션), 역할을 의미한다.

  • 기능은 결국에는 함수로 구현한다.

  • 간단하게 ADT를 정의하자면 내가 사용하는 자료구조의 함수의 사용법이다.

  • 실제 정의는 그 내부구조가 어떻게 구현되어 있는지, 기능은 어떻게 되어있는지에 관한 것이다.

  • list.append의 ADT 예시

help(list.append)
Help on method_descriptor:

append(self, object, /)
    Append object to the end of the list.