TIL_26 : 객체 지향 프로그래밍

48311 단어 TILOOPOOP

🙄 객체 지향 프로그래밍


➡ 객체란?

  • 속성행동으로 이루어진 존재

ex) instagram 유저 객체

  • 속성 : 이메일 주소, 비밀번호, 친구목록 ...
  • 행동 : 좋아요 누르기, 친구 추가하기 ...

현실에 존재하든, 가상으로 존재하든 속성행동을 떠올릴 수 있다면 모두 객체


➡ 객체 지향 프로그래밍이란?

  • 프로그램을 여러 개의 독립된 객체들과 그 객체들 간의 상호작용으로 파악하는 프로그래밍 접근법
  • 프로그램을 객체들과 객체들 간의 소통으로 바라보는 것

👉 객체 지향 프로그래밍으로 프로그램을 만들려면

  1. 프로그램에 어떤 객체들이 필요할지 정한다
  2. 객체들의 속성과 행동을 정한다
  3. 객체들이 서로 어떻게 소통할지 정한다



🙄 객체를 만드는 법


➡ 클래스와 인스턴스

  • 객체의 틀을 클래스라고 하고 틀로 만든 결과물을 객체(인스턴스)라고 함
    클래스로 객체를 만든다 = 클래스로 인스턴스를 만든다

인스턴스, 객체가 굳이 비교하면 다른거라더라

class User:		# 클래스 이름 첫글자는 무조건 대문자
    pass		# 속성과 행동 입력, 아예 비워 두면 Error

user1 = User()		# user1 인스턴스
user2 = User()		# user2 인스턴스
user3 = User()		# user3 인스턴스

user1, user2, user3는 같은 클래스로 만들었어도 서로 다른 인스턴스


➡ 인스턴스 변수

  • 인스턴스 변수 정의하기
    : 인스턴스 이름.속성이름(인스턴스 변수) = "속성에 넣을 값"
class User:
    pass

user1 = User()
user2 = User()
user3 = User()

user1.name = "구자현"
user1.email = "[email protected]"
user1.password = "12345"

user2.name = "민정호"
user2.email = "[email protected]"
user2.password = "24680"

user3.name = "박준규"
user3.email = "[email protected]"
user3.password = "13579"

print(user1.password)
print(user2.email)
print(user3.name)

# 1235
# [email protected]
# 박준규
  • 같은 속성이름을 갖고 있더라도 다른 값을 갖고 있다.
  • 속성을 공유하는 것이 아닌 각자 개인적으로 소유
  • 인스턴스가 개인적으로 갖고 있는 변수인스턴스 변수 라고한다
  • name, email, password는 모두 인스턴스 변수

➡ 인스턴스 메소드

  • 객체의 속성인스턴스 변수로 나타낸다
  • 객체의 행동함수로 나타낸다

행동을 나타내는 함수를 메소드라고 함

👉 메소드의 3가지 종류

1. 인스턴스 메소드 : 인스턴스 변수를 사용하거나, 인스턴스 변수에 값을 설정하는 메소드
2. 클래스 메소드
3. 정적 메소드

class User:
    def say_hello(some_user):
        # 인사 메세지 출력 메소드
        print("안녕하세요! 저는 {}입니다!".format(some_user.name))

user1 = User()
user2 = User()
user3 = User()

user1.name = "구자현"
user1.email = "[email protected]"
user1.password = "12345"

user2.name = "민정호"
user2.email = "[email protected]"
user2.password = "24680"

user3.name = "박준규"
user3.email = "[email protected]"
user3.password = "13579"

User.say_hello(user1)
User.say_hello(user2)
User.say_hello(user3)

# 안녕하세요! 저는 구자현입니다!
# 안녕하세요! 저는 민정호입니다!
# 안녕하세요! 저는 박준규입니다!

name이라는 인스턴스 변수 사용 ➡ 함수 say_hello인스턴스 메소드


👉 인스턴스 메소드의 특별한 규칙_1

  • 인스턴스의 메소드를 호출하면 파라미터로 인스턴스를 자동으로 넘겨준다
class User:
    def say_hello(some_user):
        # 인사 메세지 출력 메소드
        print("안녕하세요! 저는 {}입니다!".format(some_user.name))

    def login(some_user, my_email, my_password):
        # 로그인 메소드
        if (some_user.email == my_email and some_user.password == my_password):
            print("로그인 성공, 환영합니다")
        else:
            print("로그인 실패, 없는 아이디이거나 잘못된 비밀번호입니다.")

user1 = User()
user2 = User()
user3 = User()

user1.name = "구자현"
user1.email = "[email protected]"
user1.password = "12345"

User.say_hello(user1)			# 클래스에서 메소드를 호출
user1.say_hello()			# 인스턴스의 메소드 호출

user1.login("[email protected]", "12345")

# 안녕하세요! 저는 구자현입니다!
# 안녕하세요! 저는 구자현입니다!
# 로그인 성공, 환영합니다

👉 규칙_2 : self 사용

class User:
    def say_hello(self):
        # 인사 메세지 출력 메소드
        print("안녕하세요! 저는 {}입니다!".format(self.name))

    def login(self, my_email, my_password):
        # 로그인 메소드
        if (self.email == my_email and self.password == my_password):
            print("로그인 성공, 환영합니다")
        else:
            print("로그인 실패, 없는 아이디이거나 잘못된 비밀번호입니다.")

user1 = User()
user2 = User()
user3 = User()

user1.name = "구자현"
user1.email = "[email protected]"
user1.password = "12345"

User.say_hello(user1)
user1.say_hello()

user1.login("[email protected]", "12345")

# 안녕하세요! 저는 구자현입니다!
# 안녕하세요! 저는 구자현입니다!
# 로그인 성공, 환영합니다
  • 인스턴스 메소드를 정의할 때, 항상 첫 파라미터는 인스턴스를 받기 위한 파라미터를 써줘야함
  • python 세계에서는 self를 쓰기로 약속

첫 번째 파라미터의 이름은 꼭❗ self로 쓰기


➡ 인스턴스 변수와 같은 이름의 파라미터

class User:
    def check_name(self, name):
        # 파라미터로 받는 name이 유저의 이름과 같은지 불린으로 리턴하는 메소드
        return self.name == name

user2 = User()

user2.name = "민정호"
user2.email = "[email protected]"
user2.password = "24680"

print(user2.check_name("민정호"))
print(user2.check_name("박준규"))

# True
# False
  • 인스턴스의 변수와 파라미터의 이름이 둘다 name으로 동일

아무런 문제 없다 !!


➡ initialize 메소드

  • 아래와 같이 메소드를 작성하면 인스턴스 변수를 한번에 설정할 수 있다
class User:
    def initialize(self, name, email, password):
        self.name = name
        self.email = email
        self.password = password

user1 = User()
user1.initialize("Young", "[email protected]", "123456")

user2 = User()
user2.initialize("Yoonsoo", "[email protected]", "abcdef")

user3 = User()
User.initialize(user3, "Taeho", "[email protected]", "123abc")

user4 = User()
User.initialize(user4, "Lisa", "[email protected]", "abc123")

print(user1.name, user1.email, user1.password)
print(user2.name, user2.email, user2.password)
print(user3.name, user3.email, user3.password)
print(user4.name, user4.email, user4.password)

# Young [email protected] 123456
# Yoonsoo [email protected] abcdef
# Taeho [email protected] 123abc
# Lisa [email protected] abc123

➡ __init__ 메소드

  • __init__ : 인스턴스가 생성될 때 자동으로 호출되는 특수 메소드

  • 인스턴스 생성초기값 설정 동시에 가능

  • 그래서 보통 클래스에는 __init__ 메소드가 항상 존재

특수 메소드 : 특정 상황에서 자동으로 호출되는 메소드

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

user1 = User("Young", "[email protected]", "123456")
user2 = User("Yoonsoo", "[email protected]", "abcdef")
user3 = User("Taeho", "[email protected]", "123abc")
user4 = User("Lisa", "[email protected]", "abc123")

print(user1.email)
print(user2.name)
print(user3.password)

➡ __str__ 메소드

  • print 함수를 호출할 때 자동으로 호출됨

  • return 값을 출력

  • 원하는 정보를 나오게 할 때 사용

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

    def __str__(self):
        return "사용자: {}, 이메일: {}, 비밀번호: ******".format(self.name, self.email)
 
user1 = User("구자현", "[email protected]", '12345')
user2 = User("박준규", "[email protected]", "24680")

print(user1)
print(user2)

# __str__이 없다면 출력되는 저장경로
# <__main__.User object at 0x0000021303A65FD0>
# <__main__.User object at 0x0000021303A65F10>

# 사용자: 구자현, 이메일: [email protected], 비밀번호: ******
# 사용자: 박준규, 이메일: [email protected], 비밀번호: ******

➡ 클래스 변수 #1

클래스 변수란?

  • 여러 인스턴스들이 공유하는 속성

  • 클래스 이름 밑에 정의

class User:
    count = 0

    def __init__(self, name, email, pw):
        self.name = name
        self.email = email
        self.pw = pw

        User.count += 1

user1 = User('구자현','[email protected]', '12345')
user2 = User('민정호', '[email protected]', '13579')
user3 = User('박준규', '[email protected]', '24680')

print(User.count)

# 3

➡ 클래스 변수 #2

  • 클래스 이름.클래스 변수 이름 으로 변수의 값을 읽는다

  • 인스턴스 이름.클래스 변수 이름 으로 읽기도 가능

  • 같은 이름클래스 변수인스턴스 변수가 있으면 인스턴스 변수를 읽음

헷갈릴 수 있기 때문에 클래스 변수에 값을 읽어올 때 반드시 클래스 이름으로만 ❗❗

class User:
    count = 0

    def __init__(self, name, email, pw):
        self.name = name
        self.email = email
        self.pw = pw

        User.count += 1

user1 = User('구자현','[email protected]', '12345')
user2 = User('민정호', '[email protected]', '13579')
user3 = User('박준규', '[email protected]', '24680')

user1.count = 5			# 같은 이름을 가진 인스턴스 변수

print(User.count)
print(user1.count)
print(user2.count)
print(user3.count)

# 3
# 5
# 3
# 3

➡ decorator

  • 기존 함수에 새로운 기능 추가하는 역할

  • 여러 함수에 중복되는 기능을 간결하게 하기 위함

def add_print_to(original):
    def wrapper():
        print('함수 시작')
        original()
        print('함수 끝')
    return wrapper

@add_print_to			# decorator
def print_hello():
    print('안녕하세요!')

print_hello()

# 함수시작
# 안녕하세요!
# 함수 끝

➡ 클래스 메소드 #1

  • 인스턴스 메소드 : 인스턴스 변수의 값을 읽거나 설정하는 메소드

  • 클래스 메소드 : 클래스 변수의 값을 읽거나 설정하는 메소드

  • 첫 번째 파라미터의 이름은 반드시 ❗❗ cls로 쓰기

클래스 메소드는 인스턴스 메소드와 달리 첫 번째 파라미터로 클래스 자동 전달
클래스 메소드 decorator로 number_of_users를 클래스 메소드로 만들어 줬기 때문

class User:
    count = 0

    def __init__(self, name, email, pw):
        self.name = name
        self.email = email
        self.pw = pw

        User.count += 1

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

user1 = User('구자현','[email protected]', '12345')
user2 = User('민정호', '[email protected]', '13579')
user3 = User('박준규', '[email protected]', '24680')

User.number_of_users()
user1.number_of_users()

# 총 유저 수는: 3입니다
# 총 유저 수는: 3입니다

➡ 클래스 메소드 #2

  • number_of_users는 인스턴스 변수를 사용하지 않기 때문에 클래스 메소드로 만듦

  • 인스턴스 변수를 사용하지 않으니 self에 접근할 필요가 없다

  • 클래스 변수만 사용하는 경우 클래스 메소드로 작성해야 함

  • 인스턴스 변수 사용 ➡ 인스턴스 메소드
    클래스 변수 사용 ➡ 클래스 메소드

둘 다 쓴다면 ❓
인스턴스 메소드를 사용한다 ❗
👉 인스턴스 메소드self를 이용해 인스턴스 변수에,
클래스 이름.클래스 변수 를 이용해 클래스 변수에 접근할 수 있지만
클래스 메소드는 인스턴스 변수 접근 불가 ❗❗

class User:
    count = 0

    def __init__(self, name, email, pw):
        self.name = name
        self.email = email
        self.pw = pw

        User.count += 1

    def number_of_users(self):			# 인스턴스 메소드
        print("총 유저 수는: {}입니다".format(User.count))

user1 = User('구자현','[email protected]', '12345')
user2 = User('민정호', '[email protected]', '13579')
user3 = User('박준규', '[email protected]', '24680')

User.number_of_users(user1)
user1.number_of_users()

# 총 유저 수는: 3입니다
# 총 유저 수는: 3입니다
  • 인스턴스 없이도 필요한 정보가 있다면 클래스 메소드로 작성
  • User.count는 인스턴스가 하나도 없더라도 필요한 정보
class User:
    count = 0

    def __init__(self, name, email, pw):
        self.name = name
        self.email = email
        self.pw = pw

        User.count += 1

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

User.number_of_users()

# 총 유저 수는: 0입니다

# 인스턴스가 하나도 없을 때에도 사용할 가능성이 있다면 클래스 메소드로 만들어야한다.

➡ 정적 메소드

  • 인스턴스 변수, 클래스 변수를 전혀 다루지 않는 메소드

  • 인스턴스, 클래스 두 가지 모두를 통해 사용 가능

  • 인스턴스 변수나 클래스 변수 중 아무것도 사용하지 않을 메소드라면 정적 메소드로 만듦

class User:
    count = 0
    # 문자열에 @가 들어있는지 체크하는 정적 메소드    
    @staticmethod			# decorator를 표시해야 함
    def is_valid_email(email_address):
        return "@" in email_address

# 클래스로 접근
print(User.is_valid_email("jahyeongu"))
print(User.is_valid_email("[email protected]"))

# 인스턴스로 접근
print(user1.is_valid_email("jahyeongu"))
print(user1.is_valid_email("[email protected]"))

# False
# True
# False
# True



좋은 웹페이지 즐겨찾기