01.Python 기초 - 클래스(Class) 보충

ID짱재·2021년 3월 3일
0

Python

목록 보기
15/39
post-thumbnail

🌈 클래스(Class) 보충

🔥 클래스 기본

🔥 접근 제한자 : __

🔥 클래스 상속

🔥 오버라이딩(다형성)

🔥 인스턴스변수와 클래스변수


1. 클래스 기본

  • 클래스에 생성자(__init__)를 지정 후, 클래스를 호출할 때는 객체로 변수에 저장
  • 클래스 객체에 선언된 메서드를 연결시켜 출력할 수 있음
  • self는 class 자기 자신을 의미함

✍🏻 python

class Person:
    def __init__(self, name, age): # 생성자, 초기자
        self.name = name
        self.age = age
    def display(self):  # 메서드 = class 안에서 기능하는 함
        print(self.name,self.age)
p1 = Person('홍길동',25)
p2 = Person('김철수',33)
print(p1.name) # 홍길동
print(p1.age) # 25
print(p2.name) # 김철수
print(p2.age) # 33
p1.display() # 홍길동 25
p2.display() # 김철수 33
  • 클래스 생성자에 input으로 정보를 입력받은 후, list에 추가시키고 for문으로 출력

✍🏻 python

class Person:
    def __init__(self):
        self.name = input('name : ')
        self.age = int(input('age : '))
    def display(self):
        print(self.name+' :', self.age)
li = []
for i in range(3):
    li.append(Person()) # 클래스를 이곳에서 호출했기 때문에 input이 각 3번씩 실행되고 for문 종료
for i in li:
    i.display() # 클래스 내 메서드 출력은 여기서 실행


2. 접근 제한자 : __

  • 기본적으로 클래스는 생성된 클래스 객체에 생성자를 호출하면 클래스 내의 값을 호출할 수 있음
  • 접근 제한자 기능은 이런 기본적인 기능을 제한하는 방법으로 __를 사용하여 생성자를 지정함
  • 아래 eng값을 출력하였을 때, __eng로 접근 제한이 되었기 때문에 속성이 없다는 에러가 발생

✍🏻 python

class Sj:
    def __init__(self):
        self.kor = 90
        self.__eng = 77
        self.mat = 88
s1 = Sj()
print(s1.mat) # 88
print(s1.eng) # AttributeError: 'Sj' object has no attribute 'eng'

  • 이렇게 접근 제한자를 사용하면 외부에서 클래스 내 값을 호출할 수 없음
  • 다만, 클래스 내부에서는 생성자 값을 접근에 사용할 수 있음
  • 즉, 클래스에서 접근 제한자는 외부에서 내부로 직접 접근하는 것을 제한하는 기능임

✍🏻 python

class Sj:
    def __init__(self):
        self.kor = 90
        self.__eng = 77
        self.mat = 88
    def display(self):
        print(self.__eng, self.kor, self.mat)
s1 = Sj()
s1.display()

  • 보안 및 안정성의 측면에 있어 생성자에 직접 접근하는 것보다는 메서드를 통해 접근하는 방식이 권장됨

✍🏻 python

class Sj:
    def __init__(self):
        self.__eng = 77
    def get_data(self):  # 외부에서 eng값을 출력하는 메서드
        return self.__eng
    def set_data(self,eng): # 외부에서 메서드를 통해 eng값에 접근하여 값을 수정
        self.__eng = eng
s1 = Sj()
s1.set_data(100) # SJ클래스의 set_data 메서드에 값을 수정
print(s1.get_data()) # 100

3. 클래스 상속

  • 기존에 만들었던 클래스를 새로운 클래스에서 상속받아와 사용하는 것을 클래스 상속이라 함
  • 상속받을 클래스의 파라미터로 부모 클래스명을 넣어주면 상속됨

✍🏻 python

class Person: # Person이라는 calss
    def __init__(self):
        self.name = '홍길동'
        self.age = 25
class Korean(Person): # Korean class에 Person을 상속
    pass
person1 = Korean()
print(person1.name) # 홍길동 👈 상속되었기 때문에 Korean 클래스의 객체로 출력 가능
print(person1.age) # 25 👈 상속되었기 때문에 Korean 클래스의 객체로 출력 가능
  • 두 개의 클래스에서 객체만들어 모두 자유롭게 호출할 수 있음

✍🏻 python

class Person:
    def __init__(self):
        self.name = '홍길동'
        self.age = 25
class Korean(Person):
    pass
person1 = Person()
print(person1.name, person1.age) # 홍길동 25
person2 = Korean()
print(person2.name, person2.age) # 홍길동 25
  • 부모의 생성자를 생성자를 상속 받고, 자기만의 생성자도 갖는 방법
  • super().__init__() : 부모 클래스에 __init__을 유지하면서 아래 새로운 생성자 추가 가능
  • super().__init__() 없이 생성자를 추가하면, Person의 __init__은 사용할 수 없음
    • __init__이 덮어씌어진 것이기 때문에 현재 지정한 것만 사용 가능

✍🏻 python

class Person:
    def __init__(self):
        self.name = '홍길동'
        self.age = 25
class Korean(Person):
    def __init__(self):
        super().__init__()  # 부모클래스(Person)의 __init__
        self.lang = '한국어'
person1 = Person()
print(person1.name, person1.age) # 홍길동 25
person2 = Korean()
print(person2.name, person2.age, person2.lang) # 홍길동 25 한국

4. 오버라이딩(다형성)

  • 상속과 오버라이딩 : '부모이기는 자식 없다.'는 말처럼, 부모에 상속을 받았더라고 그 메서드를 다시 지정하면은 새로 지정된 자식의 메서드가 효력이 있음
  • 🎉 예시 : 내가 차가 없어 아빠차를 빌려 타면 아빠차도 내차라고 생각하고 쓰지만, 나도 차를 갖게된후에는 내차는 내차고 아빠차는 아빠차다.
  • 즉, 부모의 클래스에 생성자나 매서드를 상속 받은 상황에서 같은 이름으로 자식 클래스에서 새롭게 지정된다면 덮어씌어지기가 되버림

✍🏻 python

class Person:
    def __init__(self):
        self.name = '홍길동'
        self.age = 25
    def say(self): # say 메서드 생성
        pass
class Korean(Person):
    def __init__(self):
        super().__init__()  # 부모클래스(Person)의 __init__
        self.lang = '한국어'
    def say(self): # say 상속받았으나, 오버라이딩
        print('안녕하세요.')
class Ameriacon(Person):
    def __init__(self):
        super().__init__()
        self.name = 'Dave'
        self.lang = '영어'
    def say(self): # say 상속받았으나, 오버라이딩
        print('Hello!')
person1 = Person()
print(person1.name, person1.age) # 홍길동 25
korean1 = Korean()
print(korean1.name, korean1.age, korean1.lang) # 홍길동 25 한국
american1 = Ameriacon()
print(american1.name, american1.age, american1.lang) # Dave 25 영어
korean1.say() # 안녕하세요. # say 메서드를 상속받았으나, 오버라이딩함
american1.say() # Hello! # say 메서드를 상속받았으나, 오버라이딩함

  • 오버라이딩 연습 예시
  • 도형의 부모 클라스를 만든 후, 자식 클라스1(사각형)과 자식 클라스2(원)을 만들어 오버라이딩 하기

✍🏻 python

# 부모클라스 좌표 입력
class Point: 
    def __init__(self):
        self.x = int(input('좌표 입력(x) : '))
        self.y = int(input('좌표 입력(y) : '))
    def display(self):
        pass
# 자식 클라스1 : 사각형 만들기 클라스(가로, 세로 입력)
class Rect(Point): 
    def __init__(self):
        super().__init__()
        self.w = int(input('넓이 입력(w) : '))
        self.h = int(input('높이 입력(h) : '))
    def display(self):
        print(f'사각형의 좌표는 ({self.x},{self.y})이고, 넓이는 {self.w} 높이는 {self.h} 입니다.')
# 자식 클라스2 : 원 만들기 클라스(반지름 입력)
class Circle(Point): 
    def __init__(self):
        super().__init__()
        self.r = int(input('반지름 입력(r) : '))
    def display(self): 
        print(f'원의 좌표는 ({self.x},{self.y})이고, 반지름은 {self.r} 입니다.')
# main 함수
def main():
    li=list()
    while True:
        s = input('번호를 입력하세요(1.사각형 2.원 3.조회 4.종료) : ')
        if s == '1':  # 1이라면 Rect()클래스 실행하여 입력하고 li에 추가
            li.append(Rect())
        if s == '2':  # 2라면 Circle()클래스 실행하여 입력하고 li에 추가
            li.append(Circle())
        if s == '3':  # 3이라면 리스트(li)를 for문 돌려서 출력
            for i in li:
                i.display()
        if s == '4':  # 4라면 종
            break
    print('프로그램을 종료합니다.')
main() # main 함수 실행


5. 인스턴스변수와 클래스변수

  • 상품을 받아 리스트에 추가하는 Class를 만들고 리스트를 출력하면 값이 모두 다름
  • 이처럼 클래스에서는 객체별로 생성자를 따로 관리하기 때문에 각 각의 리스트가 존재함
  • 이를 리스트를 인스턴스 변수라하고, 이는 생성자 내부 뿐아니라 다른 메서드에서도 self를 통해 접근 가능함

✍🏻 python

# 인스턴스 변수 예시
class Person:
    def __init__(self, sp): # 생성자
        self.li = [] # 인스턴스 변수 : 생성자로 리스트를 생성
        self.li.append(sp) # 파라미터로 받은 sp를 리스트에 추가
    def display(self):
        print(self.li)
p1 = Person('우유')
p1.display()
p2 = Person('콜라')
p2.display()
p3 = Person('쥬스')
p3.display()

  • 이에 반해 클래스 변수는 각 객체별로 관리되지 않고, 모든 객체들이 공유하여 사용함
  • 단, 클래스 변수를 지정할 때에는 생성자 및 메서드 밖에 존재해야하고, self를 붙이지 않음
  • 이에 생성자나 메서드에서 클래스 변수(리스트)를 접근하기 위해서는 클래스명을 연결시킴

✍🏻 python

# 클래스 변수 예시
class Person:
    li = [] # 클래스 변수 : self 없음, 생성자 및 메서드 밖에서 존재
    def __init__(self, sp):
        Person.li.append(sp) # 리스트가 생성자 소속이 아니기 때문에 self로 접근 못함. 클래스명으로 접근
    def display(self):
        print(Person.li) # 클래스명으로 접근
p1 = Person('우유')
p1.display()
p2 = Person('콜라')
p2.display()
p3 = Person('쥬스')
p3.display()

profile
Keep Going, Keep Coding!

0개의 댓글