오늘로 교육 시작한지 3주차 3일이 되었습니다.
충격적이게도 블로그 작성 후 완료 버튼을 눌렀는데 본문 내용이 싹 사라지고
아무 내용이 없는 상태로 포스팅되었습니다.
처음 경험이라 마음의 상처(?)가 크네요.
더 까먹기 전에 빠르게 글을 다시 써 보겠습니다.


오늘은 어제 완료하지 못했던 반복문과 대망의 class를 배웠습니다.
class는 아리송한 부분들이 있어서 이해 하는데 시간이 꽤 많이 걸렸습니다.
제가 이해한 나름대로 정리해보도록 하겠습니다.


반복문, break, continue

import os

while True:
    userinput = input('>')

    if userinput == 'pwd':
        # print('현재 위치 출력')
        # print('\\'.join(_file_.split('\\')[:-1]))
        print(os.getcwd())
    elif userinput == 'dir' or userinput == 'ls':
        # print('현재 폴더에 폴더와 파일명 출력')
        print(os.listdir(os.getcwd()))
    elif userinput == 'exit'        :
        print('안녕히 가세요')
        break

위의 코드는 while문 이고 조건이 True 이기 때문에 무한루프 라고 볼 수 있습니다.
쉘처럼 > 에 명령어를 입력하면 조건에 따라 동작을 하게 됩니다.
반복문을 빠져 나올 수 있는 구문은 break 입니다.
위의 코드에서는 입력창에 exit를 입력하면 break 구문이 실행되어
while문을 빠져나올 수 있습니다.

for i in range(10):     # 0~9까지
    if i % 2 == 0:      # 짝수인 경우에만 코드 블럭을 실행
        continue        # 짝수인 경우에는 실행한 구문이 continue -> 짝수일때 -> 다시 반복문 다음 순서로 이동!
        print(i)
    print(i)            # for문 안에 if문 실행 된후에 차례대로 print(i)

위의 코드는 0 부터 9까지의 정수중에 홀수만 출력하는 코드입니다.
for문의 순회하는 동안 내부에 if문이 있는데 i값을 2로 나눈 나머지가 0일 경우만 continue 문이 실행됩니다.
결국 짝수일 경우에는 for문으로 바로 올라가 버리고, if문 내부로 진입하지 않는 홀수는 print문을 통해 출력됩니다.
break 는 반복문을 즉시 종료! 하고 continue는 반복문의 나머지 부분을 건너 뛰어 반복문의 다음 반복으로 즉시 이동합니다.

try:
    for i in range(2, 10):
        for j in range(1, 10):
            if j == 3:
                raise StopIteration
            print(f'{i} X {j} = {i*j}')
except StopIteration:
    print("Done")

다음과 같이 예외처리로 해결할 수도 있습니다. raise문을 사용해서 2단 2개만 출력하고 빠져나옵니다.


클래스

어디서부터 어떻게 써야할지 막막하네요ㅎ

class Car:
    kinds = []
    speed = 300

    def add_kinds(self, name):
        self.kinds.append(name)     # append -> 리스트(name) name(임시이름) 값을 추가한다.
        pass
    def change_speed(self, speed2):
        self.speed = speed2

modelx = Car()
modely = Car()


modelx.add_kinds('x')
modely.add_kinds('y')

modelz = Car()
modely.add_kinds('z')

Car.speed = 150

modelx.change_speed(500)
# modely.change_speed(250)
Car.speed = 50

print(f'modelx.kinds: {modelx.kinds}')
print(f'modely.kinds: {modely.kinds}')
print(f'modelz.kinds: {modelz.kinds}')
print(f'modelx.speed: {modelx.speed}')
print(f'modely.speed: {modely.speed}')
print(f'modelz.speed: {modelz.speed}')

위의 코드에서 제가 헷갈렸던 부분은 modelx.add_kinds('x') 입니다.
명시적으로 인스턴스 modelx 에 add_kinds 함수를 호출해서 값을 넣었는데 클래스변수인 리스트 kinds 가 변경되고,
modely, modelz 에 영향을 미친다는 것을 이해하지 못했습니다.
modelx.change_speed(500) 같은 경우에는 인스턴스 modelx의 speed 값이 변경되고, modely, modelz 에는 영향이 없습니다.


self.kinds 는 클래스 변수 kinds를 참조 합니다. 따라서 self.kinds.append(name) 했을 경우에는
Car 클래스의 모든 인스턴스에 반영됩니다. self.speed 도 처음에는 클래스변수 speed를 참조합니다.
하지만 change_speed 메소드 내에서 self.speed = speed2 할당이 이루어질때 speed는 인스턴스변수로 새롭게
생성됩니다. 그러므로 각 인스턴스는 다른 인스턴스나 클래스변수에 영향을 주지 않고 자신만의 speed값을
가지게 됩니다.


그럼에도 불구하고 의문은 완전한게 해소되지는 않았습니다.
계속 코드 변경해보고, chatGPT에 물어보고 확인하며 얻은 결론은?
리스트와 같은 변경 가능한(mutable) 객체가 클래스변수로 사용될 때 발생한다 입니다.
파이썬은 변경 가능한(mutable) 객체를 클래스변수로 사용할때 이와같은 특별한 동작을 합니다.


변경 가능한 자료형(mutable)은 리스트(List), 딕셔너리(Dictionary), 세트(Set)
그리고 사용자 정의 클래스의 인스턴스 입니다.
사용자 정의 클래스의 인스턴스는 우리가 만들 클래스에 내가 만든 다른 클래스의
인스턴스를 클래스변수로 사용할 경우에도 이런 동작이 발생할 수 있습니다.


변경 불가능한 자료형(immutable)은 정수(Integers), 부동 소수점(Floating point numbers),
문자열(Strings), 튜플(Tuples) 불리언(Boolean) 등이 있습니다.


변경 불가능한 자료형(immutable)은 클래스 변수로 사용될 때 각 인스턴스는 독립적인 값을 가질 수 있고,
한 인스턴스에서 이루어진 변경은 다른 인스턴스에 영향을 미치지 않습니다.
변경 가능한 자료형(mutable)을 클래스 변수로 사용할 때는 모든 인스턴스에 영향을 미치는 공유 상태임을
꼭 기억해야 할 것 같습니다.


클래스명.클래스변수 형태로 접근하면 클래스변수를 막 수정할 수 있습니다.
이렇게 클래스변수를 수정하면 해당 클래스의 모든 인스턴스에서 변경이 가능합니다.
해당 클래스의 모든 인스턴스에 영향을 미치기 때문에 예기치 않은 오류가 발생할 수 있습니다.


그 외 테스트 하면서 알게 된 것은

modelx = Car()
modely = Car()
modelz = Car()

Car.speed = 150

modelx.change_speed(500)
Car.speed = 50

print(f'modelx.speed: {modelx.speed}')
print(f'modely.speed: {modely.speed}')
print(f'modelz.speed: {modelz.speed}')

위처럼 코드 작성했을때 출력값은 500, 50, 50 입니다.
Car.speed = 50 으로 모든 인스턴스의 값이 변경됐을 거라고 생각했는데 modelx.change_speed(500) 에서 명시적으로
값을 변경했을때는 클래스변수값을 변경했을때 영향을 받지 않았습니다.
이건 또 왜? 이런 생각을 곰곰히 해봤는데 결국 modelx.change_speed(500) 에서 변경한 건
클래스변수의 값이 아니라 인스턴스변수 였다는 겁니다.^^
클래스의 세계는 오묘합니다.


글이 날아가 버려서 급하게 다시 작성했는데 요약본이 되었습니다.
너무 길게 작성했었나 봅니다. 더 심플하게 정리된것 같다는 생각이 들면서도 아까운건 어쩔 수 없네요.
자동저장이 왜 안됐는지 모르겠지만 중간중간 확인이 필요할 것 같습니다.
내일도 화이팅! 입니다.^^