복습으로 시작해서 튜플, 딕셔너리, 집합까지 자료형을 모두 만났고,
조건문과while반복문으로 코드의 흐름을 제어하기 시작한 날이다.
학습 두 번째 날이다. 오늘 배운 내용은 이렇다.
id, copy, is)if/elif/else, in/not in, passwhile, break, continue, while ~ elsestr1 = 'Python'
str2 = 'How are you?'
str3 = '''Thank you'''
str4 = """Nice to meet you"""
print(type(str1), type(str2), type(str3), type(str4)) # 전부 <class 'str'>
print(len(str1)) # 6
str5 = ''
print(type(str5), len(str5)) # <class 'str'> 0
str6 = str() # str5 = '' 와 같다 (list1 = list() 와 같은 원리)
int1 = int(5.6) # 5.6을 정수형 객체로 형 변환
print(int1) # 5 (소수점 이하가 버려진다)
float1 = float(4) # 4를 실수형 객체로 형 변환
print(float1) # 4.0
str(), int(), float(), list()처럼 클래스 이름 뒤에 괄호를 붙이면 객체를 만들거나 변환한다. 인자 없이 쓰면 빈 값이 만들어진다.
ex_str1 = 'Do you have a \"Python\"?'
print(ex_str1) # Do you have a "Python"?
t_str1 = 'Py\tthon' # 탭만큼 띄우기
print(t_str1)
t_str2 = 'New line \n Python' # 줄바꿈(개행)
print(t_str2)
str_1 = 'Apple'
str_2 = 'Banana'
str_4 = 'Grape'
print(3 * str_1) # AppleAppleApple (3번 반복)
print(str_1 + str_2) # AppleBanana (문자와 문자를 연결, 같은 타입끼리만 가능)
print('p' in str_1) # True (in: 앞의 값이 뒤의 문자열에 들어 있는가)
print('g' in str_2) # False
print('A' in str_4) # False (대소문자를 구분한다)
print(type(str(33))) # <class 'str'>
print(type(str(3.4))) # <class 'str'>
print(type(str(True))) # <class 'str'> (전부 str로 변환)
in은 문자열이 포함되어 있는지를 True/False로 알려 준다. str()로는 숫자, 불린도 문자열로 바꿀 수 있다.
Day.1에서 배운 %, format을 다시 연습했다.
print('%s %s' % ('first', 'second'))
print('{}{}'.format('five', 'six'))
print('%10s' % ('python')) # 10칸, 오른쪽 정렬
print('{:>10}'.format('python')) # 위를 format으로 바꾼 것
print('%-10s' % 'grape') # 왼쪽 정렬
print('{:<10}'.format('grape'))
print('{:*<10}'.format('python')) # 10칸, 왼쪽 정렬, 빈칸은 *
print('{:*^10}'.format('python')) # 10칸, 가운데 정렬, 빈칸은 *
절삭은 .숫자로 글자 수를 제한한다.
print('%.3s' % ('파이썬자바')) # 파이썬
print('{:.5}'.format('파이썬자바스크립트')) # 파이썬자바
print(f'{"파이썬자바스크립트":_>10.3}') # _______파이썬 (3글자만 나오지만 칸은 10칸)
숫자의 칸 수는 서식 문자 앞에 숫자를 넣는다.
print('%d %d %d' % (2, 3, 4)) # 2 3 4 (%d는 정수)
print('%4d' % (12)) # ' 12' (4칸에 정수 12)
print('{:4}'.format(12)) # 위 값을 format으로 바꾼 것
print('%f' % (3.12312389379)) # 3.123124 (6자리까지 출력, 7번째에서 반올림)
%3d처럼 쓰는 숫자는 최소 칸 수지, 최대 길이를 제한하는 것이 아니다.
print('%3d' % (12312354596990)) # 12312354596990 (3칸보다 길어도 전부 출력)
print('%3s' % ('자바바바 스크립트')) # 전부 출력
print('%-3s' % ('그러면 이것도 될까')) # 전부 출력
print('%3s' % ('안녕')) # ' 안녕' (최소 3칸 확보, 왼쪽에 한 칸 비어서 출력)
print('%4.2f' % (3.234212345)) # '3.23' (4칸 확보, 소수점 둘째 자리까지)
print('%5.2f' % (3.234212345)) # ' 3.23' (5칸 확보라 왼쪽에 한 칸 비어 있다)
%5.2f에서 5칸은 소수점(.)도 한 칸으로 센다. 3.23이 4글자라서 앞에 한 칸이 남는 것이다. 반대로 %4.2f는 4칸이 딱 맞아서 공백이 없다.
튜플의 특징은 순서 o, 중복 o, 수정 x, 삭제 x다. 리스트와 거의 같은데 바꿀 수 없다.
tu1 = () # tu1 = tuple() 과 같다
tu1 = 1, # 요소가 1개일 때는 쉼표(,)로 마무리해야 튜플이 된다
tu3 = (1, 2, 3, 4)
tu4 = (2, 3, '사과', 'app')
tu5 = 2, 3, ('사과', 'apple', 'grape') # 괄호 없이도 튜플
print(type(tu5)) # <class 'tuple'>
print(tu4[1]) # 3
print(tu1[0] + tu3[3]) # 5
print(tu5[-1][2]) # grape (-1은 뒤에서 첫 번째, 즉 마지막 요소)
# tu4[0] = 20 # 값 수정 불가, 에러 발생
# del tu4[0] # 값 삭제 불가, 에러 발생
print(tu4[2:]) # ('사과', 'app') (인덱스 2부터 끝까지)
괄호 ( )가 아니라 쉼표가 튜플을 만든다. tu1 = 1,은 요소 1개짜리 튜플이지만, 쉼표 없이 (1)로 쓰면 그냥 숫자 1이다.
print(tu3 + tu4) # (1, 2, 3, 4, 2, 3, '사과', 'app')
print(tu3 * 3) # (1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4)
print(str(tu3[0]) + 'hello') # 1hello (숫자를 문자열과 합치려면 str로 변환)
tu = (5, 2, 4, 4, 3)
print(tu.index(5)) # 0 (5의 위치 찾기)
print(tu.count(4)) # 2 (4의 개수 세기)
바꾸는 메소드(append, sort 같은)가 없고, 찾고 세는 index와 count만 있다.
# packing
tu22 = ('phone', 'book', 'computer', 'mouse')
print(tu22) # ('phone', 'book', 'computer', 'mouse')
# unpacking
(x, y, z, m) = tu22 # tu22의 값을 각각 x, y, z, m에 대입
print(x, y, z, m) # phone book computer mouse (괄호 없이 출력)
print(type(x), type(y), type(z), type(m)) # 전부 <class 'str'>
tu33 = 1, 2, 3 # 튜플 패킹
tu44 = 1,
x1, y1, z1 = tu33 # 튜플 언패킹
x2, x3, x4 = 4, 5, 6 # 패킹과 언패킹을 한 줄에
# y2, y3 = tu44 # 에러: 변수는 2개인데 값이 1개뿐
print(x1, y1, z1) # 1 2 3
print(x2, x3, x4) # 4 5 6
왼쪽 변수의 개수와 오른쪽 값의 개수가 같아야 한다. 다르면 ValueError: not enough values to unpack 오류가 난다. JS의 구조 분해 할당(Day.7, Day.8)과 비슷한 역할인데, Python에서는 x, y = ...처럼 괄호 없이 바로 쓰는 것이 일반적이다.
딕셔너리는 {key: value} 형태이고, 특징은 순서 x, 키 중복 x, 수정 o, 삭제 o다. (참고로 요즘 Python은 넣은 순서를 기억해서 출력하지만, 리스트처럼 [0]으로 위치를 지정해서 꺼내지는 못한다. "순서가 없다"는 말은 이 뜻으로 이해하면 된다.)
dic1 = {'name': 'Lee', 'phone': '010-0000-0000', 'birth': '000211'}
dic2 = {0: '파이썬'}
dic3 = {'ary': [1, 2, 3, 4]}
dic4 = {
'name': 'Tom',
'addr': 'Seoul',
'age': 25,
'grade': 'A',
'status': True
}
dic5 = dict() # {}
dic6 = dict([('name', 'Tom'), ('addr', 'Seoul'), ('age', 25), ('grade', 'A'), ('status', True)])
키는 문자열뿐 아니라 숫자(0)도 될 수 있고, 값에는 리스트도 넣을 수 있다.
dic6은 이런 순서로 만들어진다.
('name', 'Tom') 튜플 (키, 값)dict()가 그 리스트를 딕셔너리로 변환(a, b) 튜플 → 튜플들의 리스트 → dict() → {키: 값}
dict()는 인자를 1개만 받는 구조이기 때문이다.print(dic1['name']) # Lee
# print(dic1['name1']) # KeyError: 존재하지 않는 키
print(dic1.get('name1')) # None (키가 없으면 에러 없이 None)
print(dic1.get('name')) # Lee
print(dic2[0]) # 파이썬
print(dic2.get(0)) # 파이썬
print(dic3['ary']) # [1, 2, 3, 4]
print(dic3.get('ary')) # [1, 2, 3, 4]
print(dic4.get('age')) # 25
| 방법 | 키가 없으면 |
|---|---|
딕셔너리명['키'] | KeyError 발생 |
딕셔너리명.get('키') | None 반환 (에러 없음) |
a = {1: 'c', 1: 'a', 1: 'b', 1: 'tt'}
print(a) # {1: 'tt'}
같은 키를 여러 번 쓰면 마지막 값만 남는다. 키 하나에 값은 하나만 가질 수 있기 때문이다.
dic1['address'] = 'Seoul' # 딕셔너리명['추가할 키'] = 값
print(dic1)
dic1['score'] = [90, 30, 40] # 값으로 리스트를 추가
print(dic1.get('score')[0]) # 90
없는 키에 값을 대입하면 추가되고, 이미 있는 키에 대입하면 수정된다.
print(len(dic1), len(dic2), len(dic3), len(dic4), len(dic5), len(dic6))
# 5 1 1 5 0 5
딕셔너리의 len()은 키:값 한 쌍을 하나로 센다.
print(dic1.keys())
# dict_keys(['name', 'phone', 'birth', 'address', 'score'])
print(list(dic1.keys())) # 리스트로 변환해서 출력
print(dic1.values())
# dict_values(['Lee', '010-0000-0000', '000211', 'Seoul', [90, 30, 40]])
print(list(dic1.values())) # 리스트로 변환
print(dic3.items()) # dict_items([('ary', [1, 2, 3, 4])])
print(list(dic3.items())) # [('ary', [1, 2, 3, 4])] (키와 값이 튜플로 묶여 나옴)
| 메소드 | 설명 |
|---|---|
keys() | 키들만 모아서 반환 |
values() | 값들만 모아서 반환 |
items() | (키, 값) 튜플들을 모아서 반환 |
keys()와 values()의 결과는 리스트와 비슷하게 보이지만, 리스트 고유의 함수(append, insert, pop, remove, sort)는 쓸 수 없다. 필요하면 list()로 감싸서 리스트로 바꾼다.
print(dic1.pop('name')) # Lee (삭제한 키의 값을 돌려준다, 원본이 변경된다)
print(dic1) # name이 삭제됨
print(dic4.pop('addr')) # Seoul
print(dic4)
pop('키')는 그 키와 값을 지우고, 지운 값을 반환한다.
print('name' in dic1) # False (위에서 name을 pop으로 삭제했기 때문)
print('name' in dic6) # True
딕셔너리에 in을 쓰면 키를 기준으로 존재 여부를 확인한다. (필기에는 dict.in()이라고 적었는데, in은 메소드가 아니라 연산자다.)
집합은 순서 x, 중복 x다.
s1 = set() # 빈 집합 ({}는 빈 딕셔너리)
s2 = set([1, 2, 2, 3, 4, 5]) # 리스트 자료형을 집합 자료형으로 변환
print(len(s2)) # 5
print(s2) # {1, 2, 3, 4, 5} (중복된 2가 하나로)
s3 = set([1, 4, 6, 7])
s4 = set([1, 2, '사과', '망고', 'python'])
s5 = {'phone', 'computer', 'notebook', 'water', 'phone'} # 중복된 phone은 하나로
s6 = {12, 'mouse', (1, 2, 3), 3.14}
print(type(s1), type(s2), type(s3), type(s4), type(s5), type(s6))
# 전부 <class 'set'>
{ } 안에 키: 값 형태가 아니라 값만 나열하면 집합으로 판정된다.
print(tuple(s2), type(tuple(s2))) # (1, 2, 3, 4, 5) <class 'tuple'>
print(tuple(s2)[0], tuple(s2)[1]) # 인덱스 사용 가능
s3_list = list(s3)
s4_list = list(s4)
print(s3_list[2], s4_list[1:3])
집합은 순서가 없어서 인덱스를 쓸 수 없지만, 튜플이나 리스트로 바꾸면 인덱스를 쓸 수 있다. 다만 set으로 선언했을 때 순서가 유지되지 않아서, 특히 문자열이 섞인 집합은 실행할 때마다 s4_list[1:3]의 결과가 달라질 수 있다.
set1 = set([1, 2, 3, 4, 5, 6])
set2 = set([4, 5, 6, 7, 8, 9])
# 교집합: 둘 다 가진 값
print(set1 & set2) # {4, 5, 6}
print(set1.intersection(set2))
# 합집합: 중복은 하나로, 두 집합의 요소를 전부
print(set1 | set2) # {1, 2, 3, 4, 5, 6, 7, 8, 9}
print(set1.union(set2))
# 차집합: set1의 요소 중 set2와 겹치는 것을 뺀 나머지
print(set1 - set2) # {1, 2, 3}
print(set1.difference(set2))
| 연산 | 기호 | 메소드 | 의미 |
|---|---|---|---|
| 교집합 | & | intersection() | 공통 요소 |
| 합집합 | \| | union() | 모든 요소 (중복은 하나로) |
| 차집합 | - | difference() | 앞 집합에서 뒤 집합과 겹치는 것을 뺌 |
# 두 집합에 공통 요소가 없으면 True, 있으면 False
print(set1.isdisjoint(set2)) # False (4, 5, 6이 공통)
# set1이 set2의 부분집합인가? (set1의 모든 요소가 set2에 있는가)
print(set1.issubset(set2)) # False
# 만약 set2가 {1, 2, ..., 9}였다면 True
# set1이 set2의 모든 요소를 포함하는가? (위와 같은 의미, 순서만 반대)
print(set1.issuperset(set2)) # False (set1에 7, 8, 9가 없으므로)
a = set([1, 2, 3, 4]) # {1, 2, 3, 4}
a.add(5) # 하나의 값을 추가 (원본 변경)
print(a) # {1, 2, 3, 4, 5}
a.remove(2) # 값 2를 삭제
print(a) # {1, 3, 4, 5}
a.discard(3) # 값 3을 삭제
print(a) # {1, 4, 5}
a.clear() # 전부 제거 (구조는 남는다)
print(a) # set()
a.update([1, 2]) # 여러 값을 한꺼번에 추가
print(a) # {1, 2}
remove와 discard는 지우는 일은 같지만 없는 값을 지울 때 다르다.
| 메소드 | 없는 값을 지우면 |
|---|---|
remove(값) | KeyError 발생 |
discard(값) | 아무 일도 없이 넘어감 |
remove는 인자를 하나만 받아서 remove(2, 3)처럼 쓰면 에러가 난다. 여러 값을 한 번에 넣을 때는 update를 쓰고, 이때 update는 리스트처럼 순회할 수 있는 것을 받는다. 집합은 중복이 안 되어서 같은 값은 하나만 들어가고, 순서도 유지되지 않는다.
| 자료형 | 기호 | 순서 | 중복 | 수정 |
|---|---|---|---|---|
| 리스트 | [ ] | o | o | o |
| 튜플 | ( ) | o | o | x |
| 딕셔너리 | { : } | x | 키 x | o |
| 집합 | { } | x | x | o |
각 타입의 특징을 이해하고 상황에 맞게 골라 써야 한다.
None), 비어 있음({}, [], (), ''), 0, False참: '자바스크립트', ['파이썬'], (10), {'a': 3}, 1, {'aa'}
거짓: '', "", [], (), {}, 0, None
필기의 거짓 목록에
Null이 같이 적혀 있었는데, Python에는Null이 없고 "값 없음"은None이다. JS의null에 해당한다. 그리고 JS에서는 빈 배열[]이 참이었지만(Day.9에서 정리한 falsy 목록에 없다), Python에서는 빈 리스트가 거짓이다. 같은 모양인데 규칙이 다르다.
# a = [1, 2, 3]
# a는 리스트 [1, 2, 3]이 저장된 메모리 주소값을 가지고 있다 (reference)
n = 100
print(type(n)) # <class 'int'>
print(id(n)) # n이 가리키는 객체의 주소값
a = b = c = d = 100 # 동시에 여러 변수 선언 가능
n = 50 # 값을 덮어쓴다
print(n) # 50
id()는 객체의 주소값을 알려 준다. 변수는 값을 직접 품고 있는 상자가 아니라, 값(객체)이 있는 곳을 가리키는 이름표다.
a = 3
print(id(3))
print(id(a))
b = a
print(id(b)) # 세 개 모두 같은 값
a와 b는 같은 객체 3을 가리키고 있어서 id가 같다. 이때 b = a는 값을 복사하는 것이 아니라 같은 곳을 가리키게 하는 것이다.
x = 3
y = 5
x, y = (y, x) # y의 값을 x에, x의 값을 y에 대입
print(x, y) # 5 3
임시 변수 없이도 한 줄로 값을 맞바꿀 수 있다. 오른쪽에서 패킹이 일어나고 왼쪽에서 언패킹이 일어나는 구조다.
from copy import copy # from 모듈명 import 함수
a2 = [1, 2, 3]
b2 = copy(a2) # a2를 복사한 새로운 객체가 생성된다
# b2 = copy(a2) 는 b2 = a2[:] 와 같다
print(a2, b2) # [1, 2, 3] [1, 2, 3] (값은 같지만)
print(id(a2), id(b2)) # id가 다르다
print(a2 is b2) # False
is는 두 대상이 같은 객체인지(주소가 같은지) 확인한다. 값이 같은지를 묻는 ==와는 다르다. 위에서 a2 == b2는 True지만 a2 is b2는 False다. JS에서 new String('hi') 두 개를 ===로 비교하면 false였던 Day.5의 내용과 같은 문제다. 또 Day.8에서 본 스프레드 복사([...ary])에 해당하는 것이 Python의 copy()와 슬라이싱 [:]이다.
print(type(True)) # <class 'bool'>
print(type(False))
if True: # True를 조건으로 두면 무조건 참이라 항상 실행된다
print('참')
else:
print('거짓')
JS와 달리 조건에 소괄호가 필요 없고, 조건 뒤에 콜론(:), 실행할 코드는 들여쓰기로 구분한다. 중괄호가 없는 대신 들여쓰기가 곧 문법이다.
adr = '' # adr = False 와 같다
if adr:
print(adr)
else:
print('주소를 입력하세요') # 이 줄이 실행됨
adr = 'Seoul' # adr = True 와 같다
if adr:
print(adr) # Seoul
else:
print('주소를 입력하세요')
빈 문자열은 거짓이라 else로, 값이 있으면 참이라 if로 간다.
JS의 &&, ||, !가 Python에서는 and, or, not이다.
a, b, c = 85, 29, 20
print(a > b and b > c) # True (둘 다 맞으면 True)
print(a > b or b > c) # True (둘 중 하나라도 맞으면 True)
print(not a > b) # False (a가 b보다 크지 않으면 True)
print(not b > c) # False
print(not True) # False
print(not False) # True
print(3 + 2 > 7 + 3) # False
print(3 + 2 == 5 and not 7 + 3 > 0) # False (True and False → and는 둘 다 True여야 True)
| JavaScript | Python |
|---|---|
&& | and |
\|\| | or |
! | not |
in, not inx = [10, 20, 30] # list
y = {70, 80, 90, 100} # set
z = {'name': '파이썬', 'city': '서울', 'id': 'academy'} # dict
m = (10, 20, 24) # tuple
print(25 in x) # False (25가 x 안에 있는가)
print(25 not in x) # True (25가 x 안에 없는가)
print(90 in y) # True
print(20 not in m) # False
print('city' in z) # True (city라는 키가 z 안에 있는가)
print('academy' in z.values()) # True
딕셔너리에 in을 직접 쓰면 키만 검사한다. 값에서 찾으려면 z.values()와 함께 쓴다.
score = 82
if score >= 90:
print('A')
elif score >= 80:
print('B') # 이 줄이 실행됨
elif score >= 70:
print('C')
else:
print('F')
JS의 else if가 Python에서는 elif다.
pass는 아무 일도 하지 않고 넘어가는 문장이다. 문법상 코드 블록이 있어야 하는데 할 일이 없을 때 쓴다.
grade = 'A'
total = 85
if grade == 'A':
if total >= 90:
print('장학생')
elif total >= 80:
pass # 아무것도 하지 않고 넘어감 (출력 없음)
else: # total이 80 미만일 때
print('학생')
else: # grade가 A가 아닐 때
print('다시 시험을 봐야 한다')
grade가 'A'이고 total이 85이므로 elif total >= 80 쪽으로 들어가 pass가 실행되고, 출력은 아무것도 없다.
# 초기식, 조건, 증감
# while 조건:
# 반복할 실행 코드
num = 5
while num > 0:
print(num) # 5 4 3 2 1
num -= 1 # num = num - 1
JavaScript Day.4에서 정리한 초기식, 조건식, 증감식 세 가지가 while에서도 그대로 필요하다. 증감식을 빼면 무한 반복이 된다.
a = ['a', 'b', 'c']
while a: # 리스트에 값이 있으면 참, 비면 거짓
print(a.pop()) # c b a
리스트가 빌 때까지 pop()으로 꺼내며 출력한다. 앞에서 정리한 참/거짓 규칙(빈 리스트는 거짓)을 조건으로 쓴 것이다. while True:로 쓰면 무한 반복문이 된다.
break: 반복문을 완전히 빠져나간다.continue: 이번 반복의 남은 부분을 건너뛰고 처음(조건 검사)으로 돌아간다.num = 10
while num > 0:
print(num) # 10 9 8 7 6 5 4 3
num -= 1
if num == 2:
break # num이 2가 되면 반복문 종료
n = 10
while n > 0:
n -= 1
if n == 2:
continue # 2일 때만 건너뛰고 다음 반복으로
print(n) # 9 8 7 6 5 4 3 1 0 (2만 빠진다)
필기의 주석에는
continue가 "반복문 탈출"이라고 적혀 있었는데, 탈출은break다.continue는 탈출하지 않고 그 회차만 건너뛴다. 위 결과에서2만 빠지고1,0까지 계속 출력되는 것이 증거다.
continue 뒤에 print가 하나 더 있는 경우도 확인했다.
num = 10
while num > 0:
print(num)
num -= 1
if num == 2:
continue # num이 2일 때는 아래 print를 건너뜀
print(num)
# 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 1 1 0
한 회차에 print가 두 번 있어서 대부분의 값이 두 번씩 나온다. num이 2가 된 회차에서만 두 번째 print가 빠져서, 3이 두 번 나온 뒤 2가 한 번만 나온다.
i = 1
while i <= 10:
print(i) # 1 2 3 4 5
if i == 5:
break
i += 1
n = 10
while n > 0:
n -= 1
print(n)
if n == 5:
break
else:
print('final')
# 9 final 8 final 7 final 6 final 5
이 else는 while이 아니라 안쪽 if의 else다. 5에서 break가 되기 전까지 final이 반복해서 찍힌다.
while에도 else를 붙일 수 있다.
a1 = ['water', 'python', 'java', 'phone']
s1 = 'py'
i = 0
# 리스트 끝까지 'py'와 같은 값이 있는지 확인, 있으면 반복문 종료
while i < len(a1):
if a1[i] == s1:
break
i += 1
else:
print('hi') # hi
while ~ else의 else는 반복문이 break 없이 정상적으로 끝났을 때만 실행된다. 중간에 break로 끝나면 else는 실행되지 않는다. 위 코드는 'py'와 정확히 같은 요소가 없어서 끝까지 돌았고('python'은 'py'와 같지 않다), 그래서 hi가 출력된다. "끝까지 찾아봤는데 없었다"를 표현할 때 쓸 수 있다.
li = ['a', 'b', 'c']
while True: # 무한 루프 안에서
if not li: # 리스트가 비면 not li가 True가 되어
break # 반복문 종료
print(li.pop()) # c b a
값이 있을 때는 not li가 False라 break가 작동하지 않고, pop()으로 값이 다 사라지면 not li가 True가 되어 반복문이 끝난다. while li:로 쓴 앞의 코드와 같은 일을 하는 다른 모양이다.
문제:
[1, 2, 3]을 집합 자료형으로 바꾼다.
n_set = ([1, 2, 3]) # 오답
print(n_set) # [1, 2, 3] (집합이 아니라 괄호로 감싼 리스트)
정답은 set()으로 변환하는 것이다.
n_set = set([1, 2, 3])
print(n_set) # {1, 2, 3}
([1, 2, 3])의 괄호는 튜플이 아니라 그냥 묶음 괄호라서, 결과는 여전히 리스트다.{ } 모양이라고 해서 {[1, 2, 3]}으로 쓰면 에러가 난다. 리스트는 바뀔 수 있는 값이라 집합의 요소나 딕셔너리의 키가 될 수 없다(TypeError: unhashable type: 'list'). 집합에는 숫자, 문자열, 튜플처럼 바뀌지 않는 값만 들어간다.set(리스트)로 변환해야 한다.[ ]로 꺼내면 KeyError가 나지만 get()은 None을 돌려준다.&, |, -로 교집합, 합집합, 차집합을 구한다.None, '', [], (), {}, 0)은 거짓이다.==는 값이 같은지, is는 같은 객체인지를 비교한다.else if는 elif, &&/||/!는 and/or/not이다.while ~ else의 else는 break 없이 끝났을 때만 실행된다.Tags: Python 튜플 딕셔너리 집합 조건문 while 반복문 개발자 학습기록