[4일차] 입출력, 연산자, 컬렉션타입(리스트)

2026. 5. 26. 09:18KDT/1. Python

# input 함수

  • input 함수는 사용자로부터 키보드 입력을 받는 데 사용되는 내장 함수
  • 프로그램 실행 중 사용자가 값을 입력하면, 입력한 값이 문자열로 반환되어 변수에 저장하거나 처리 가능

# print 함수

  • print 함수는 콘솔에 출력을 표시하는 가장 기본 함수
  • 프로그램 실행 중 생성된 값을 사용자에게 보여주거나 디버깅할 때 매우 유용
print(10, 20, 30, 40)		# ,가 한 칸 띄어쓰기

print(10, 20, 30, 40, sep='😎')	# sep 속성 : 기본값은 띄어쓰기. 띄어쓰기 대신 채워줄 내용을 담을 수 있음
print(10, 20, 30, 40, sep=' ')

print('Hello', end='')		# end 속성 : enter도 띄어쓰기도 없이 붙여서 출력

# 이스케이프 문자 (Escape Character)

  • 이스케이프 문자는 특별한 의미를 가지며, 문자열 내에서 특수한 기능을 수행하도록 하는 문자
  • 백슬래시(\)로 시작하며, 그 뒤에 이어지는 문자가 특정 기능을 수행함
  1. \n : 줄바꿈
  2. \t : 탭문자
  3. \\ : 백슬래시 자체
  4. \" 또는 \' : 큰따옴표 또는 작은따옴표 자체
  5. \r : 캐리지 리턴. 문자열 출력 후 커서를 줄의 처음으로 이동
  6. \b : 백스페이스. 문자열 내에서 한 글자 삭제

# 출력서식 지정

  • print() 함수에서 서식 지정(formatting)은 변수를 문자열 내에 삽입하거나, 숫자의 출력 형식을 지정하는 방법

1. % 서식 지정자

  1. %s : 문자열
  2. %d : 정수
  3. %f : 실수
  4. %x : 16진수
print("문자열 출력: %s" % name)        # %s
print("여러 값 출력: %s %d %.2f" % (name, num, pi))  # 여러 값

 

2. str.format() 메서드

  • { } : 중괄호 안에 변수나 표현식을 넣어 값을 출력
  • {:d} : 정수 출력
  • {:f} : 부동 소수점 숫자 출력
  • {:s} : 문자열 출력
  • {:x} : 정수를 16진수로 출력
  • {:0n} : n 자리 정수를 0으로 채워서 출력
  • {:n.mf} : 전체 길이 n과 소수점 이하 자리수 m을 지정하여 부동 소수점 숫자 출력
print("0 채움 정수: {:05d}".format(42))           # 0 채움 정수: 00042
print("소수점 자리 지정: {:.2f}".format(pi))      # 소수점 자리 지정: 3.14
print("전체 길이 + 소수점: {:10.2f}".format(pi))  # 전체 길이 + 소수점:       3.14

 

3. f-string

  • f-string은 가장 직관적이고 간편한 방식
name = "김사과"
age = 20

print(f"이름은 {name}이고 나이는 {age}입니다.")	# 이름은 김사과이고 나이는 20입니다.

a = 10
b = 20
pi = 3.14159

print(f"{a} + {b} = {a + b}")	# 10 + 20 = 30
print(f"{pi}를 소수 둘째자리까지 표현 {pi:.2f}")	# 3.14159를 소수 둘째자리까지 표현 3.14
더보기

* 아래로 갈수록 진화(?)

print("기본 출력: " + name)

print("기본 출력: {}".format(name))

print(f"기본출력: {name}") 


# 1. 산술 연산자

  • 주로 수치 데이터 유형에 대한 기본 산술 연산을 수행
  • 피연산자 중 실수가 존재하면 결과가 정수더라도 실수
  1. +
  2. -
  3. *
  4. /
    결과가 무조건 실수
  5. // : 몫 (정수 나누기)
  6. % : 나머지
  7. ** : 지수 (거듭제곱)

# 2. 비교 연산자

  • 비교 연산자는 주로 두 값을 비교하는 데 사용되며, 그 결과는 항상 bool(True or False) 값
  1. == : 동등
  2. != : 동등하지 않음
  3. < : 작음
  4. <= : 작거나 같다
  5. > : 크다
  6. >= : 크거나 같다

# 3. 할당 연산자

  • 변수에 값을 할당하는데 사용
  1. = : 할당
  2. +=
  3. -=
  4. *=
  5. /=
  6. //=
  7. %=
  8. **=

# 4. 비트 연산자

  • 비트 연산자는 정수를 이진 비트로 표현했을 때 사용. 각 연산자는 정수의 비트 단위로 동작
  1. & : 비트 단위 AND
  2. | : 비트 단위 OR
  3. ^ : 비트 단위 XOR
  4. ~ : 비트 단위 NOT
  5. << : 왼쪽 시프트
  6. >> : 오른쪽 시프트
a = 60  # 111100
b = 13  # 001101

print(a & b)  # 12, 즉 1100
print(a | b)  # 61, 즉 111101
print(a ^ b)  # 49, 즉 110001
print(~a)      # -61
print(a << 2)  # 240, 즉 11110000
print(a >> 2)  # 15, 즉 1111

# 비트 연산자 자체가 중요한 건 아니지만 이진수 전환할 줄 알기 ⭐

# 5. 논리 연산자

  • 파이썬에서의 논리 연산자는 주로 Boolean 값을 조작하기 위해 사용
  • 그러나 파이썬의 논리 연산자는 다른 언어와 다르게, 연산의 결과로 항상 True, False만 반환하는 것은 아님
  1. and : 논리 AND
  2. or : 논리 OR
  3. not : 논리 NOT
# ⭐
# and
print(True and 3)      # 3      and 연산에서 
print(3 and 5)         # 5      앞의 값이 True면 뒤의 값이 나감
print(0 and 5)         # 0      앞의 값이 False면 뒤의 값을 판단할 필요없으므로 앞의 값이 나감

# or
print(False or 3)      # 3      or 연산에서 
print(3 or 5)          # 3      앞의 값이 True면 뒤의 값을 판단할 필요없으므로 앞의 값이 나감
print(0 or 5)          # 5      앞의 값이 False면 뒤의 값이 나감

# not
print(not True)        # False  
print(not 0)           # True   False로 판별되는 값은 -> True
print(not 3)           # False  True로 판별되는 값은 -> False

# 파이썬에서 Boolean으로 평가되는 주요 값⭐

1. True로 평가되는 주요 값

  • 0이 아닌 모든 숫자 (양수, 음수 모두 포함)
  • 비어 있지 않은 문자열, 비어 있지 않은 리스트, 비어 있지 않은 튜플, 비어 있지 않은 세트, 비어 있지 않은 딕셔너리
  • True

2. False로 평가되는 주요 값

  • 0
  • False
  • 빈 문자열, 빈 리스트[ ], 빈 튜플 ( ), 빈 세트 set( ), 빈 딕셔너리 { }
  • None

# 컬렉션 타입

  • 여러 개의 데이터 항목을 하나의 단위로 관리할 수 있게 해주는 데이터 구조
  • 여러 개의 데이터를 하나의 변수에 저장하고, 관리
  • 파이썬에서는 리스트, 튜플, 세트, 딕셔너리 등이 기본적인 컬렉션 타입

# 리스트 list

  • 리스트는 여러 개의 데이터를 하나의 변수에 순서대로 저장할 수 있는 파이썬의 대표적인 컬렉션 자료형
  • 대활호 [ ]
  • 각 요소는 인덱스를 통해 접근 가능
  • 서로 다른 자료형의 값을 함께 저장 가능
  • 요소의 추가, 수정, 삭제가 가능한 mutable(변경 가능한) 구조
  • 데이터를 묶어서 관리하거나 반복 처리할 때 매우 유용하게 사용
// PyObject_HEAD
// C언어로 구현된 파이썬 인터프리터 (CPython)의 구조체(struct)에 포함된 매크로
// 파이썬 객체라면 반드시 거쳐야하는 공통 필드 정의

typedef struct {
    PyObject_HEAD         // 공통 필드: 참조 횟수, 타입 정보 포함!
    Py_ssize_t ob_size;   // 리스트의 길이
    PyObject **ob_item;   // 실제 아이템 배열 포인터
    Py_ssize_t allocated; // 할당된 배열 용량
} PyListObject;

 

1. 리스트 만들기

li1 = [1, 3, 5, 7, 9]
print(li1)
print(type(li1))

li2 = list([1, 3, 5, 7, 9])
print(li2)
print(type(li2))

li3 = ['김사과', '반하나', '오렌지', '이메론']
print(li3)

li4 = [1, 50.5, '김사과', True]      # 각자 타입이 다른 데이터를 저장
print(li4)
print(type(li4))

print(li4[0])
print(type(li4[0]))
print(li4[1])
print(type(li4[1]))
print(li4[2])
print(type(li4[2]))
print(li4[3])
print(type(li4[3]))
# print(li4[4]) # IndexError: list index out of range

 

2. 리스트 인덱싱

  • 리스트의 각 항목은 위치(인덱스)를 가지고 있으며, 인덱스를 사용하여 접근 가능
  • 인덱스는 0부터 시작
    • 인덱싱은 리스트에서 '하나의 요소'를 꺼내는 것
    • 결과는 -> 꺼낸 하나의 값(값 자체)
    • 대괄호로 감싸지지 않음
li1 = [1, 3, 5, 7, 9]
print(li1)		# [1, 3, 5, 7, 9]
print(li1[0])	# 1
print(li1[-1])	# 9
print(li1[0] + li1[-1])		#10

li2 = [1, 2, '파이썬', ['김사과', '오렌지']]
print(li2)		# [1, 2, '파이썬', ['김사과', '오렌지']]
print(type(li2))	# <class 'list'>
print(li2[1])		# 2
print(type(li2[1]))	# <class 'int'>
print(li2[3])		# ['김사과', '오렌지']
print(type(li2[3])) # <class 'list'>
print(li2[3][1])	# 오렌지
print(type(li2[3][1]))	# <class 'str'>

li3 = [1, 2, 3, ['김사과', '오렌지', '반하나', ['🍟','🌭','🥩','🍗']]]
print(li3)	# [1, 2, 3, ['김사과', '오렌지', '반하나', ['🍟', '🌭', '🥩', '🍗']]]
print(li3[2])	# 3
print(li3[-1])	# ['김사과', '오렌지', '반하나', ['🍟', '🌭', '🥩', '🍗']]
print(li3[-1][-2])	# 반하나
print(li3[-1][-1][-2])	# 🥩
print(li3[-1][-1][-1])	# 🍗

 

3. 리스트 슬라이싱

  • 리스트의 일부분만 추출 가능
  • '여러 개 요소'를 잘라서 새로운 리스트로 만드는 것
  • 결과는 -> 잘라낸 "리스트" (대괄호로 감싸진 새로운 리스트)
리스트[start:end:step]

    start: 어디서 시작할지 (포함)
    end: 어디까지 갈지 (끝 인덱스는 포함하지 않음)
    step: 몇 칸씩 이동할지
li1 = [10, 20, 30, 40, 50]
print(li1)		# [10, 20, 30, 40, 50]
print(li1[0:3])	# [10, 20, 30]

li2 = li1       # 리스트 객체도 ref count를 가짐
print(li2)		# [10, 20, 30, 40, 50]
li2[0] = 100
print(li2)		# [100, 20, 30, 40, 50]
print(li1)		# [100, 20, 30, 40, 50]

li3 = [1, 2, 3, ['김사과', '오렌지', '반하나', ['🍟','🌭','🥩','🍗']]]
print(li3[2:3])     # [3] 슬라이싱은 그 데이터를 복사하기 때문에 list 형태로 나오는 것임. 차원을 유지.
print(li3[3][:2])	# ['김사과', '오렌지']

 

4. 리스트의 항목 추가 / 변경 / 삭제

li4 = [10, 20, 30, 40, 50]
# 슬라이싱을 이용하여 요소를 추가한 경우 리스트에 데이터만 포함 ⭐
li4[1:2] = ['😁','😂','😎','😍']
print(li4)		# [10, '😁', '😂', '😎', '😍', 30, 40, 50]

li4 = [10, 20, 30, 40, 50]
# 인덱싱을 이용하여 요소를 추가한 경우 리스트 안에 리스트를 만들고 포함 ⭐
li4[1] = ['😁','😂','😎','😍']
print(li4)		# [10, ['😁', '😂', '😎', '😍'], 30, 40, 50]

li4 = [10, 20, 30, 40, 50]
print(li4[1:3])		# [20, 30]
li4[1:3] = [] # 빈 리스트를 슬라이싱을 통해 저장하면 해당 요소가 삭제됨
print(li4)			# [10, 40, 50]

li4 = [10, 20, 30, 40, 50]
print(li4[1:2])		# [20]
print(li4[1])		# 20
li4[1] = []	
print(li4)		# [10, [], 30, 40, 50]

li4 = [10, 20, 30, 40, 50]
print(li4)			# [10, 20, 30, 40, 50]
del li4[1]			# 요소 삭제
print(li4)			# [10, 30, 40, 50]

 

5. 리스트의 결합 및 반복

  • + 연산으로 리스트 결합
  • * 연산으로 리스트 반복
li5 = [10, 20, 30]
li6 = [40, 50, 60]
print(li5 + li6)		# [10, 20, 30, 40, 50, 60]
print(li6 + li5)		# [40, 50, 60, 10, 20, 30]

li5 = [10, 20, 30]
li6 = li5 + [40, 50, 60] # [10, 20, 30] + [40, 50, 60]
print(li6)		# [10, 20, 30, 40, 50, 60]

li6 = [10, 20, 30]
li6 += [40, 50, 60] # li6 = li6 + [40, 50, 60]
print(li6)		# [10, 20, 30, 40, 50, 60]

li6 = [10, 20, 30]
print(li6 * 3)		# [10, 20, 30, 10, 20, 30, 10, 20, 30]

 

6. 함수와 메서드

  • len( ) : 객체의 길이를 반환하는 파이썬의 기본 내장 함수
li6 = [10, 20, 30]
print(len(li6))			# 3

 

  • append( ) : 리스트 요소의 끝에 새로운 요소 추가
li6 = [10, 20, 30]
print(li6)			# [10, 20, 30]

li6.append(100)
print(li6)			# [10, 20, 30, 100]
# li6.append(200, 300)  # TypeError: list.append() takes exactly one argument (2 given)
li6.append([200, 300])
print(li6)			# [10, 20, 30, 100, [200, 300]]

 

  • extend( ) : 리스트 요소의 끝에 새로운 여러 요소 추가
li6 = [10, 20, 30]
print(li6)			# [10, 20, 30]

# li6.extend(100)   # TypeError: 'int' object is not iterable
li6.extend([100])
print(li6)			# [10, 20, 30, 100]
li6.extend([200, 300, 400])
print(li6)			# [10, 20, 30, 100, 200, 300, 400]

 

  • pop( ) : 리스트 마지막 요소를 삭제하고 삭제된 요소 반환
li6 = [10, 20, 30]
print(li6)			# [10, 20, 30]

# print(li6.pop())
temp = li6.pop()
print(li6)			# [10, 20]
print(temp)			# 30

 

  • index( ) : 리스트에서 특정 요소의 값 인덱스 반환
li6 = [10, 20, 30]
print(li6)			# [10, 20, 30]

print(li6.index(30))		# 2
# print(li6.index(100)) # 값이 없으면 에러  # ValueError: 100 is not in list

 

  • reverse( ) : 리스트 요소들의 순서를 반대로 설정
li7 = [100, 50, 70, 60, 20]
print(li7)		# [100, 50, 70, 60, 20]

li7.reverse()
print(li7)		# [20, 60, 70, 50, 100]

# 특징 : list 객체에 요소를 복사해서 리턴시키는 것이 아니고, 자신을 바꾸는 것! ⭐
#        tuple는 수정이 불가능하기 때문에 reverse, sort 같은 메서드는 없음.
#        sorted함수를 사용하면 정렬된 리스트를 반환하여 사용 가능

 

  • .

step이 음수인 경우, end의 기본값은 -1입니다. 하지만 리스트의 마지막 요소 역시 인덱스 -1이므로, 전체를 역순으로 출력할 때는 end를 생략하여 사용합니다.

li7 = [100, 50, 70, 60, 20]
print(li7[:])     # [100, 50, 70, 60, 20]
print(li7[0:5])
print(li7[::])    # step이 생략
print(li7[0:5:1]) # step의 기본값은 1

print(li7[0:5:2]) # [100, 70, 20] step을 2로 설정
# 슬라이싱을 사용하여 리스트의 요소들의 순서를 반대로 설정하는 방법
li7 = [100, 50, 70, 60, 20]
print(li7[::-1])
# step이 -1일 경우 start의 기본값은 length-1, end의 기본값은 -1으로 설정

print(li7[-1::-1])
print(li7[4::-1])
print(li7[4:None:-1])

 

  • sort( ) : 리스트의 요소를 오름차순으로 정렬
  • 특징 : 자기 자신을 바꾸는 것! (복사한 값을 사용하는 것이 아님) ⭐
li7 = [100, 50, 70, 60, 20]
print(li7)		# [100, 50, 70, 60, 20]

li7.sort()
print(li7)		# [20, 50, 60, 70, 100]

li7.sort(reverse=True)  # 리스트의 요소를 내림차순으로 정렬
print(li7)		# [100, 70, 60, 50, 20]

li8 = ['Apple', 'apple', 'orange', 'banana', 'melon']
li8.sort()
print(li8)		# ['Apple', 'apple', 'banana', 'melon', 'orange']

li9 = ['김사과', '오렌지', '반하나', '이메론', '배애리']
li9.sort()
print(li9)		# ['김사과', '반하나', '배애리', '오렌지', '이메론']

 

  • sorted( ) : 모든 요소를 정렬한 후 '리스트' 반환
  • 특징 : 복사한 값을 사용 ⭐
li7 = [100, 50, 70, 60, 20]
print(li7)		# [100, 50, 70, 60, 20]

result = sorted(li7)
print(li7)		# [100, 50, 70, 60, 20]
print(result)		# [20, 50, 60, 70, 100]
print(type(result))	# <class 'list'>

 

  • count( ) : 리스트에서 특정 요소의 개수 반환
li9 = [10, 20, 30, 50, 20, 40, 30, 20]
print(li9)		# [10, 20, 30, 50, 20, 40, 30, 20]

print(li9.count(20))	# 3
print(li9.count(100))	# 0

 

*최소 단위는 bit 지만 연산 최소 단위는 byte