본문 바로가기

Programming

객체지향 프로그래밍(1) class, method, instance

객체 : 속성 + 행동을 떠올릴 수 있는 모든 것

객체지향 프로그래밍 : 프로그래밍 패러다임 중 하나, 프로그래밍에 필요한 데이터를 추상화 시켜 속성과 행동을 가진 객체를 만들고, 그 객체들 간 상호작용을 통해 로직을 구성하는 프로그래밍 방법

1. 프로그램에 필요한 객체 정의

2. 객체의 속성과 행동 정의

3. 객체 간 상호작용 정의


객체 구현 in python

파이썬은 순수객체지향언어, 파이썬의 모든 것은 특정 class의 객체(instance)다. type 함수를 통해 인스턴스의 class를 확인할 수 있다. 객체는 속성 변경 여부에 따라 다음 2가지로 구분 된다.

mutable object : 한번 생성한 인스턴스 속성 변경 가능(eg. list, dict, 직접 만든 class)

immutable object : 한번 생성한 인스턴스 속성 변경 불가(eg. tuple, int, float, str, bool)

파이썬에서 class는 객체를 만드는 틀, class로 여러 instance(실제 메모리상에 할당된 객체)를 만들 수 있다. 파이썬 class는 객체의 두 요소 속성과 행동을 각각 인스턴스 변수와 인스턴스 method로 정의한다. 아래 코드를 보면 init method로 User class의 속성, 즉 인스턴스 변수 name, email, pw를 정의하고 User class의 행동을 say_hello라는 method로 정의했음을 알 수 있다.

class User:
    def __init__(self,name,email,pw): # magic method : 특정 상황에서 자동 호출
        self.name = name
        self.email = email
        self.pw = pw
        
    def say_hello(self):
        print(f"안녕! 난 {self.name}!")

또한 인스턴스에서 method를 호출하면 인스턴스가 자동으로 해당 method의 첫번째 파라미터로 들어간다. 따라서 인스턴스 method를 정의할 때 self라는 파라미터를 통해 이를 명시한다.

# User class의 인스턴스 user1 생성
user1 = User('이현','chdnjf103@naver.com','478956')

# 인스턴스 user1에서 method say_hello 호출
user1.say_hello() <- user1이 파라미터로 전달

 

Class 변수

한편, 인스턴스마다 메모리 공간이 따로 존재하는 인스턴스 변수말고 class 전체가 공유하는 class 변수를 선언할 수 있다. 예를 들어 User class로 생성된 인스턴스 갯수를 count라는 class 변수로 유지한다고 하면 다음과 같이 method 밖에 count를 정의한다.

class User:
    count = 0 # class 변수

    def __init__(self,name,email,pw):
        self.name = name
        self.email = email
        self.pw = pw
        User.count += 1 # 인스턴스가 생성될때마다 클래스 변수 count 1씩 증가
        
    def say_hello(self):
        print(f"안녕! 난 {self.name}!")

class 변수는 클래스.count와 같이 클래스로 호출해 다루는게 좋다. 인스턴스.count 처럼 인스턴스로 호출하면 인스턴스 변수와 중복되어 문제가 생길 수 있기 때문!

 

Class method

class 변수를 다루는 class method를 데코레이터 @classmethod를 통해 선언할 수 있다. 인스턴스 method와 비슷하게 자기자신, 즉 class를 자동으로 첫번째 파라미터로 갖는다. 다만 인스턴스 method가 인스턴스에서 호출했을때만 자신을 파라미터로 넘긴것과 다르게, class method는 class, instance 어떤 것으로 호출해도 class 자신을 첫번째 파라미터로 넘겨준다.

class User:
    count = 0 # class 변수, 인스턴스가 아닌 class에서 접근하자!

    def __init__(self,name,email,pw): # magic method : 특정 상황에서 자동 호출
        self.name = name
        self.email = email
        self.pw = pw
        User.count += 1 # 인스턴스가 생성될때마다 클래스 변수 count 1씩 증가
	
    # 클래스 method
    @classmethod
    def number_of_users(cls): # 인스턴스 method의 self 대신 cls
        print(f"총 유저 수 : {cls.count}")

user1 = User('이현','chdnjf103@naver.com','478956')
user2 = User('조수연','susie@naver.com','12345')

# 같은 동작!
user1.number_of_users() # 인스턴스로 class method 호출
User.number_of_users() # 클래스로 class method 호출 

클래스 method : 클래스 변수를 다룰 때, 인스턴스 변수 못 다룸

인스턴스 method : 인스턴스 변수를 다룰 때(+클래스 변수와 함께 다룰 때), 클래스/인스턴스 변수 모두 다룸

 

인스턴스 생성하는 class method

인스턴스 생성에서 init 파라미터가 원하는 자료구조가 아닐 때, 변환 과정을 class method로 선언하면 다음과 같이 깔끔하게 프로그래밍이 가능하다.

class User:
    def __init__(self, name, email, password):
        self.name = name
        self.email = email
        self.password = password

    @classmethod
    def from_string(cls, string_params): # string_params = "이현,chdnjf103@naver.com,1234"
        tem = string_params.split(",")
        name = tem[0]
        email = tem[1]
        password = tem[2]
        return cls(name,email,password) # 클래스 method 첫 파라미터인 cls를 이용해 init 호출로 인스턴스 생성
 
 # 인스턴스 생성
 hyun = User.from_string("이현,chdnjf103@naver.com,1234")

 

Static method

인스턴스/클래스 변수 중 아무것도 사용하지 않는 method로 단순히 기능적인 역할만 하는 method를 정의할 때 사용한다. 클래스, 인스턴스 둘 다 호출가능하다.

class User():
    # 인스턴스 메소드
    def __str__(self):
    	return "사용자: {}, 이메일: {}, 비밀번호: ******".format(self.name, self.email)

    # 클래스 메소드    
    @classmethod
    def number_of_users(cls):
        print("총 유저 수는: {}입니다".format(cls.count))

    # 정적 메소드    
    @staticmethod
    def is_valid_email(email_address):
        return "@" in email_address

 

절차 지향 vs 객체 지향

객체 지향은 class를 이용해 필요한 동작(method)에 관련된 데이터(변수)를 함께 묶어 관리하는 반면, 절차 지향은 필요한 동작들만 함수로 묶어 관리한다. 따라서 객체 지향은 이러한 class로 생성된 객체들 간의 상호작용으로 프로그램을 구성하고, 절차 지향은 함수를 이용해 명령어들을 순차적으로 실행하는 것으로 프로그램을 구성한다.