[파이썬 Projects]/<파이썬 기초>

[파이썬] 파이썬 기초 - 클래스 보완

기록자_Recordian 2025. 1. 22. 11:32
728x90
반응형
클래스 이전 내용

[파이썬] 파이썬기초: 클래스 - 1

클래스(Class) 와 객체(object) 클래스: 똑같은 무언가를 계속 만들어 낼 수 있는 설계 도면객체: 클래스로 만든 피조물. 클래스로 만든 객체는 객체 마다 고유한 성격을 가진다. ◆ 파이썬 클래스의

puppy-foot-it.tistory.com

 

[파이썬] 파이썬 기초: 클래스 - 2

이전 내용 [파이썬] 파이썬기초: 클래스 - 1클래스(Class) 와 객체(object) 클래스: 똑같은 무언가를 계속 만들어 낼 수 있는 설계 도면객체: 클래스로 만든 피조물. 클래스로 만든 객체는 객체 마다

puppy-foot-it.tistory.com


클래스 기본값 지정하기

 
예를 들어, 아래와 같이 숫자를 1씩 증가 또는 감소 시켜주는 Counter 라는 클래스를 생성한 뒤,
메서드로 숫자를 1씩 증가시키는 increment, 1씩 감소시키는 miss_count를 생성하였다.
또한, a와 b 라는 카운터 클래스의 각각의 인스턴스를 생성하였다.
 
아래 코드를 실행하면

class Counter:
    def __init__(self): # 생성자(초기화)
        self.count = 0
    def increment(self): # 메서드1
        self.count += 1
    def miss_count(self): # 메서드1
        self.count -= 1
        
a = Counter() # 카운터 클래스의 인스턴스 a 생성
a.increment()

b = Counter() # 카운터 클래스의 인스턴스 b 생성
b.increment()
b.increment()
b.miss_count()

print(f"현재까지 a의 카운팅 숫자는 {a.count} 입니다.")
print(f"현재까지 b의 카운팅 숫자는 {b.count} 입니다.")

 
만약, 어떤 인스턴스는
기본값을 0이 아닌 다른 값을 주거나,
increment 메서드 호출 시 특정 숫자를 증가시키거나,
miss_count 메서드 호출 시 특정 숫자를 감소시키는 등의 기능을 추가해 주는데, 인자가 할당되지 않을 경우에는 기존과 같이
기본값을 유지하고 싶을 때는 initValue를 지정해주면 된다.
 
아래 코드는 위의 설명을 구현한 코드이다.

class Counter:
    def __init__(self, initValue=0):
        self.count = initValue
    def increment(self, initValue=1): # 메서드1
        self.count += initValue
    def miss_count(self, initValue=1): # 메서드2
        self.count -= initValue

a = Counter() # 카운터 클래스의 인스턴스 a 생성
a.increment()

b = Counter() # 카운터 클래스의 인스턴스 b 생성
b.increment() # 숫자 미부여 시 기본값 1
b.increment()
b.miss_count() # 숫자 미부여 시 기본값 1

c = Counter(100) # value를 특정 숫자로 초기화할 수도 있다.
c.increment()
c.miss_count(50) # 마찬가지로, miss_count 메서드에도 특정 숫자를 줄 수 있다.


print(f"현재까지 a의 카운팅 숫자는 {a.count} 입니다.")
print(f"현재까지 b의 카운팅 숫자는 {b.count} 입니다.")
print(f"현재까지 c의 카운팅 숫자는 {c.count} 입니다.")

a, b 인스턴의 경우, 초깃값을 주지 않았으므로 0으로 시작하게 된다.
그러나 c 인스턴스의 경우 100이라는 인자를 주었으므로 100으로 시작하게 된다.
 
a와 b 인스턴스의 경우 increment() 메서드와 miss_count() 메서드를 각각 호출 시, 인자를 주지 않았으므로 각 인스턴스의 초깃값에서 1씩 증가 또는 1씩 감소하게 된다.
 
그러나 c 인스턴스의 경우 increment() 메서드는 인자를 생략하였으나, miss_count() 메서드에 50 이라는 인자를 할당하였으므로, c 인스턴스의 초깃값인 100에서 1이 증가하고 50이 감소하게 된다.
따라서 (내장함수 count를 활용하여) c의 현재 수를 출력하면 51이 나오게 된다.


참조 공유, 객체 함수 호출, 클래스 변수

 
아래와 같이 채널, 음량, 전원을 출력하는 Television 클래스가 있다.

class Television:
    def __init__(self, channel, volume, on):
        self.channel = channel
        self.volume = volume
        self.on = on

    def setChannel(self, channel):
        self.channel = channel

    def getChannel(self):
        return self.channel

    def setVolume(self, volume):
        self.volume = volume

    def getVolume(self):
        return self.volume

    def show(self):
        print(self.channel, self.volume, self.on)
        
t1 = Television(20, 5, True)
t1.show()
t1.setChannel(15)
t1.show()
print("현재 볼륨은 ", t1.getVolume(), "입니다.")

[현재 Television 클래스의 형태]

  • setChannel() 메서드: 채널 setter (채널 속성 값을 변경할 수 있다.)
  • getChannel() 메서드: 채널 getter
  • setVolume() 메서드: 볼륨 setter (볼륨 속성 값을 변경할 수 있다.)
  • getVolume() 메서드: 볼륨 getter
  • show() 메서드: Television 클래스의 인스턴스 속성들을 출력

※ getter와 setter의 의미는 하단에 나온다.
 
[참조 공유]
여기에 s1이라는 인스턴스를 생성하고 t1을 대입해주고 출력하면

s1 = t1
s1.show()

과 같이 t1 인스턴스의 속성값과 동일한 값이 출력된다.
그렇다면 둘은 값뿐만 아니라 모두 동일할까? 이를 확인하는 좋은 방법은 is(또는 is not)을 조건문에 써서 출력해보는 것이다.

print(id(t1))
print(id(s1))

if s1 is t1:
    print("2개의 변수는 동일한 객체를 참조하고 있습니다.")
if s1 is not t1:
    print("2개의 변수는 서로 다른 객체를 참조하고 있습니다.")

▶ 2개의 변수는 동일한 객체를 참조하고 있다.
 
[객체 함수 호출]
setSilentMode() 함수는 인스턴스를 매개변수로 입력받아 해당 매개변수의 볼륨을 2로 줄이는 함수이다.
t2 라는 인스턴스를 생성하고 거기에 setSilentMode() 함수에 넣고 출력하게 되면

def setSilentMode(t):
    t.volume = 2

t2 = Television(15, 7, True)

# setSilentMode() 호출하여 객체의 인스턴스 변수를 변경
setSilentMode(t2)
t2.show()

▶ t2의 볼륨이 2로 줄어든 것을 확인할 수 있다.
 
[클래스 변수]
앞서 만든 Television 클래스 하단에 serialNumber 라는 클래스 변수를 생성하고,
생성자(__init__)에 Television.serialNumber+=1 / self.number = Television.serialNumer 를 입력한 뒤,

class Television:
    serialNumer = 0 # 클래스 변수, 모든 인스턴스들이 공유
    def __init__(self, channel, volume, on):
        self.channel = channel
        self.volume = volume
        self.on = on
        Television.serialNumer += 1
        self.number = Television.serialNumer

    def setChannel(self, channel):
        self.channel = channel

 
하단의 show() 메서드에 self.number 값을 출력하도록 설정했다.

    def show(self):
        print(self.channel, self.volume, self.on, self.number)

 
그리고나서 t3, t4, t5의 인스턴스를 생성한 뒤 show() 메서드를 호출하면

t3 = Television(20, 1, False)
t3.show()

t4 = Television(10, 3, True)
t4.show()

t5 = Television(2, 6, True)
t5.show()

show() 메서드 출력값이 이렇게 하나 더 늘어나게 되는데, 이 개념이 바로 클래스 변수이다.
즉,

  • Television.serialNumber+=1: Television 클래스의 인스턴스가 추가될 때마다 serialNumber가 1씩 증가
  • self.number = Television.serialNumer: self.number는 Television 클래스의 serialNumber 속성
  • show() 메서드에서 self.number: show() 메서드 호출 시 number 출력

이라는 의미를 갖고 있다.


비공개 속성

 
예를 들어, 아래와 같이 Student 클래스가 있는데, 해당 클래스에 이름과 나이 속성을 부여한 후, obj 라는 인스턴스를 생성한 뒤, 각 인스턴스에 name과 age를 호출하면

class Student:
    def __init__(self, name=None, age=0):
        self.name = name 
        self.age = age    

obj = Student("Jane", 23)
print(obj.name)
print(obj.age)

위와 같이 각 출력이 잘 된다. 이를 클래스 바깥에서도 직접 접근할 수도 있다고 표현한다.
 
만약 name과 age 속성 앞에 '__' 를 붙이게 되면 해당 속성을 클래스 바깥에서 접근할 수 없고 클래스 내에서만 사용할 수 있게 비공개 속성(private)이 된다. 비공개 속성은 클래스 안의 메서드에서만 접근할 수 있다.

class Student:
    def __init__(self, name=None, age=0):
        self.__name = name # __변수는 비공개 속성 (외부에서 변경 금지)
        self.__age = age   # __변수는 비공개 속성 (외부에서 변경 금지)

obj = Student("Jane", 23)
print(obj.name)
print(obj.age)

이전과 같이 해당 속성을 클래스 밖에서 직접 접근하려고 하면,

AttributeError: 'Student' object has no attribute 'name'
> 속성 오류: 'Student' 개체에 속성 'name'이 없습니다

라는 오류가 발생한다.
그렇다면, 아래와 같이 접근을 한다면 출력이 될까?

print(obj.__name)
print(obj.__age)

역시 같은 오류가 발생한다.
 
이 비공개 속성에 접근하기 위해서 필요한 것이 바로 setter 와 getter 라는 개념이다.
 
[getter와 setter]
- Getter
Getter는 클래스의 특정 속성 값을 '가져오는' 메서드이다. 이는 외부에서 클래스의 속성 값을 직접적으로 액세스하지 않고 안전하게 읽을 수 있게 해준다. 예를 들어, @property 데코레이터를 사용하여 getter 메서드를 정의할 수 있다. 이 데코레이터를 사용하면 특정 값을 바로 가져올 수 있다.

 
- Setter
Setter는 클래스의 특정 속성 값을 '설정하는' 메서드이다. 이를 통해 속성에 새로운 값이 할당될 때 유효성 검사나 추가적인 처리를 수행할 수 있다. 예를 들어, @속성명.setter 데코레이터를 사용하여 setter 메서드를 명시적으로 정의해야 한다. 이 데코레이터를 사용하면 해당 속성에 값을 할당할 때 setter 메서드가 호출되어, 값의 할당이 가능해진다
 
아래와 같이

  • setter: setName(), setAge() 메서드
  • getter: getName(), getAge() 메서드

를 정의한 다음 접근하게 되면

class Student:
    def __init__(self, name=None, age=0):
        self.__name = name # __변수는 비공개 속성 (외부에서 변경 금지)
        self.__age = age   # __변수는 비공개 속성 (외부에서 변경 금지)

    def setName(self, name):
        self.__name = name
    
    def setAge(self, age):
        self.__age = age

    def getName(self):
        return self.__name
    
    def getAge(self):
        return self.__age

obj = Student("Jane", 23)
print(obj.getName())
print(obj.getAge())

Student 클래스 밖에서 obj의 속성에 접근할 수 있게 된다.
 
또한, setName() 메서드와 setAge()에 다른 값을 준 뒤, getter 를 호출하면

obj.setName("홍길동")
obj.setAge(15)

print(obj.getName())
print(obj.getAge())

이름과 나이가 변경된 것을 확인할 수 있다.
 
비공개 속성은 클래스 바깥으로 드러내고 싶지 않은 값에 사용한다. 즉, 중요한 값인데 바깥에서 함부로 바꾸면 안될 때 비공개 속성을 주로 사용한다. 비공개 속성을 바꾸는 경우는 클래스의 메서드로 한정한다.


클래스 다중 상속

 
클래스를 한 번에 여러 개 상속 받을 수도 있다. 그렇게 하기 위한 문법은 아래와 같다.

class 새로운클래스명(상속받을 클래스1, 클래스2,..,클래스n)

(가능한 개수 제한은 없다고 한다 - Perplexity 답변)

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        print(self.name, self.age)

class Student:
    def __init__(self, id):
        self.id = id
    
    def getId(self):
        return self.id

class CollegeStudent(Person, Student):
    def __init__(self, name, age, id):
        Person.__init__(self, name, age)
        Student.__init__(self, id)

obj = CollegeStudent('Kim', 22, '100001')
obj.show()
print(obj.getId())

상수: 변하지 않는 값

 
상수는 변하지 않는 값을 의미하며, 보통 대문자로 작성한다.
아래와 같이 Monster 클래스를 생성한 뒤, WEAK, STRONG, VERRY_STRONG 이라는 상수 속성을 생성한 뒤, 그 안에 특정 값을 부여한다.
 
또한,

  • 생성자
  • eat() 메서드: 식량을 먹으면 HP가 STRONG으로 바뀜(강해짐, HP증가)
  • attack() 메서드: 공격을 받으면 HP가 WEAK로 바뀜(약해짐, HP감소) 
  • getHealth() 메서드: 현재의 체력(HP)를 보여줌

그리고 ork(오크)라는 몬스터(인스턴스)를 생성한 뒤, 

출처: 나무위키

 
ork 인스턴스에 각 메서드를 호출해본 뒤, HP를 출력해보면

class Monster:
    # 상수 선언 (보통 대문자로 작성)
    WEAK = 0
    NORMAL = 10
    STRONG = 20
    VERRY_STRONG = 30

    def __init__(self):
        self.__health = Monster.NORMAL # __health는 10을 준 것과 같다

    def eat(self):
        self.__health = Monster.STRONG # 밥먹으면 강해짐

    def attack(self):
        self.__health = Monster.WEAK # 공격 받으면 약해짐

    def getHealth(self):
        return self.__health
    
ork = Monster()
print(f"오크의 HP: {ork.getHealth()}")
ork.eat() # 식량 먹음
print(f"오크의 HP: {ork.getHealth()}")
ork.attack() # 공격 받음
print(f"오크의 HP: {ork.getHealth()}")

이렇게 해당 상수에 설정한 값이 출력되는 것을 알 수 있다.


다음 내용
 

[파이썬] 파이썬 기초 - 클래스 보완 (은행 계좌, ATM 프로그램 만들기)

이전 내용 [파이썬] 파이썬 기초 - 클래스 보완클래스 이전 내용 [파이썬] 파이썬기초: 클래스 - 1클래스(Class) 와 객체(object) 클래스: 똑같은 무언가를 계속 만들어 낼 수 있는 설계 도면객체: 클

puppy-foot-it.tistory.com


[참고]
나무위키
https://dojang.io/mod/page/view.php?id=2374

728x90
반응형