👨🏻‍💻

ch1 - 1. 파이썬 구조 및 기초 - 1

1.1 설정하기

Index

  • 구름IDE환경설정(계속)
  • 구름IDE로 파이썬 실행하기
  • 주석처리하기

1.1 구름IDE환경설정(계속)

구름IDE 환경설정을 해보도록 하겠습니다. 아래 화면을 보시면서 빨간색 네모를 따라 그대로 따라하시면 됩니다.
notion imagenotion image

https://ide.goorm.io/

 
회원가입을 해야 합니다. 무료계정도 컨테이너 5개를 사용할 수 있는 강력한 서비스입니다. 회원가입을 하면 자동적으로 대시보드에 들어갑니다. 만약 메인화면으로 나오셨다면 대시보드를 눌러주세요.
notion imagenotion image

다음은 대시보드 화면입니다. 새 컨테이너 생성을 누르셔서 컨테이너를 생성해 주세요. 하나의 컨테이너는 하나의 컴퓨터를 세팅하는 것과 같습니다. Python을 선택하신 다음 생성하기를 눌러주세요.
notion imagenotion image

컨테이너가 만들어지고 있다는 화면이 나오고 곧 컨테이너 생성이 완료되었다고 뜹니다. 컨테이너 실행을 누르셔서 컨테이너 안으로 들어가주세요. 만약 모르고 닫으셨다면 대시보드에서 해당 컨테이너 실행을 누르시면 됩니다.
notion imagenotion image

컨테이너가 로딩되는 화면입니다. 주로 구름에 TIP이나 유명인사의 명언이 나옵니다.
notion imagenotion image

 
notion imagenotion image
1. 폴더 구조를 볼 수 있는 공간입니다. 우측 상단에 보시면 새로고침 버튼이 있어요. 콘솔창에서 뭔가 작업을 했는데 보이지 않는다면 새로고침을 해보시길 바랍니다.
2. txt, html, py파일 등 다양한 파일을 edit 할 수 있는 공간입니다.
3. 협업을 위한 공간이에요. 이 책에서는 사용하지 않는 기능입니다. 채팅 등 협업을 위한 다양한 기능을 제공합니다.
4. 콘솔창입니다. 우리는 대부분의 명령어를 이곳에 입력하게 됩니다.

1.2 구름IDE로 파이썬 실행하기

 
앞에서 구름 IDE 환경설정을 끝냈는데 이제는 구름 IDE를 이용해서 파이썬을 실행시키는 예제를 해 보겠습니다.
 
  1. 먼저 구름IDE에서 위에서 만든 컨테이너 안에 python 폴더를 하나 만들어 줍니다.
notion imagenotion image
 
2. 그후 cd 명령어를 통해 python 디렉터리 경로를 이동시켜줍니다.
notion imagenotion image
명령어를 실행시키면 디렉터리의 경로가 변경되어있습니다.
 
3. 다음 python폴더 안에 test01.py 파일을 하나 만들어 줍니다.
notion imagenotion image
notion imagenotion image
 
4. 마지막으로 작성된 test01.py 파일 안에 코드를 작성한 후 실행시켜줍니다.
notion imagenotion image
 
※ 실행이 안될 때 TIP
대부분 사람들이 실수로 저장을 누르지 않아서 실행을 하면 결과값이 출력이 안나옵니다.
notion imagenotion image
이런 식으로 * 모양이 나오면 X모양이 바뀌도록 저장하기를 누르거나 ctrl + s 단축키를 눌러줍니다.
 

1.3 주석처리하기(계속)

#행 단위 주석입니다. """ 큰 따옴표로 세번 묶거나 작은따옴표로 세번 묶으면 열단위 주석이 됩니다. """
Code의 양이 많거나 복잡하여 짧은 시간 내 이해하기 힙들 때 이해를 돕기 위해 주석이 필요합니다. 주석은 코드를 설명할 때에도 쓰이지만 코드를 잠시 보류하는 용도로도 사용합니다. 주석처리된 문장은 실행되지 않습니다.
 

1) 행 단위 주석(#)

#행 단위 주석입니다.
행 앞에 #을 추가하면 뒷 문장은 주석처리가 됩니다.앞서 말씀드린 것처럼 주석은 실행되지 않기 때문에 결과값에 영향을 끼치지 않습니다.

2) 열 단위 주석(''',""")

""" 큰 따옴표로 세번 묶거나 작은 따옴표로 세번 묶으면 열단위 주석이 됩니다. """
큰 따옴표나 작은 따옴표 3개로 감싸진 부분은 주석처리 됩니다. 열 단위 주석은 코드를 잠시 보류하는 용도로도 많이 사용합니다.
※ TIP. 원하는 코드를 블록시킨후 Ctrl + / 버튼을 누르면 주석처리 됩니다.

 

1.2 변수

Index

  1. 입력함수_input
  1. input_print
  1. 출력함수_print
  1. 변수의 type
    1. 4.1 변수
      4.2 변수의 자료형
      4.3 숫자 자료형
      4.4 문자 자료형
      4.5 문자열의 활용
  1. 형변환

1. 입력함수_input

입력
a = input("a를 입력하세요:")
 
출력
a를 입력하세요: 10
input() 함수는 사용자에게 숫자나 문자를 입력할 수 있도록 만들어주는 함수입니다.
앞에 a는 변수이며 사용자에 입력 받은 값을 a라는 변수에 저장하게 됩니다.
괄호 안에 문구는 실행될 때 콘솔창에 'a를 입력하세요:'라고 출력됩니다.
여기에 10을 입력하면 a에 10이 저장되는 것이죠.
여기서 10은 숫자가 아니라 문자열 10입니다. 이 내용은 type에서 자세히 다루도록 하겠습니다.
 

2. input과 print

입력
age = input('age를 입력하세요:') lastname = input('lastname을 입력하세요:') firstname = input('firstname을 입력하세요:') print('당신의 이름은 ', lastname + firstname, '입니다.') print('당신의 나이는 ', age, '입니다.')
 
출력
age를 입력하세요: 22 last name을 입력하세요: hong firstname을 입혁하세요: gildong 당신의 이름은 honggildong 입니다. 당신의 나이는 22 입니다.
앞서 다루었던 input함수로 입력을 받은 값을 출력해주는 프로그램을 만들어 보도록 하겠습니다. age에는 22를, lastname이라는 변수에는 kim을, firstname이라는 변수에는 kyeongnam을 입력하여 온전한 이름을 출력하고 나이를 출력하는 프로그램을 만들어 보았습니다. 눈으로 보고 이해하셨다고 넘어가시지 마시고 손으로 직접 써보거나 키보드로 타이핑 해보시기 바랍니다. 코딩 실력은 물리적 코딩 시간에 비례합니다.
 
 

3. 출력함수 print

입력
age = 22 name = 'honggildong' print('1. 제 이름은 ', name, '입니다. 제 나이는 ', age, '입니다') print('2. 제 이름은 {}입니다. 제 나이는 {}입니다.'.format(name, age)) print('3. 제 이름은 %s입니다. 제 나이는 %d입니다.'%(name,age))
 
출력
1. 제 이름은 honggildong입니다. 제 나이는 22입니다. 2. 제 이름은 honggildong입니다. 제 나이는 22입니다. 3. 제 이름은 honggildong입니다. 제 나이는 22입니다.
1번은 콤마로(,) 연결하는 방법입니다. 콤마의 단위는 오브젝트입니다. age, name 모두 오브젝트의 한 단위이고 ‘1. 제 이름은’, ‘입니다. 제 나이는’ 등의 문자열도 모두 오브젝트입니다.
2번은 .format을 이용한 문자열 포매팅입니다. 중괄호({})로 변수의 자리를 비워놓고 .format에 괄호 안에 넣고 싶은 오브젝트를 넣어주는 방법입니다. 역시 변수는 콤마로 구별해 넣습니다.
3번은 포맷코드를 이용한 문자열 포매팅입니다. 넣고 싶은 오브젝트는 %뒤에 오고 있습니다. 넣을 값에 맞춰서 알맞은 자료형에 대한 포맷코드를 선택해야 합니다. 위에서의 예시에서는 str형인 ‘leehojun’을 넣기 위해 %s를, int형인 나이를 넣기 위해 %d를 쓰고 있습니다. 자료형은 뒤에 type에서 배울 것이니 print가 다양한 방법으로도 쓰일 수 있다는 것만 이해하고 넘어가시기 바랍니다.
 
notion imagenotion image
포맷코드를 이용하여 다양한 포매팅이 가능합니다.
 

4. 변수의 type

입력
a = 10 b = 10.1 c = -1 d = True e = 'good' f = '10' g = 'kim' h = 'honggildong' i = 'example' j = 10 + 2j k = 0b110 l = 0o56 m = 0xAC print('type(10) : ', type(a)) print('type(10.1) : ', type(b)) print('type(-1) : ', type(c)) print('type(True) : ', type(d)) print('type(\'good\') : ', type(e)) print('\'10\' + \'10\' : ', f + f) print('\'10\' * 3', f * 3) print('\'hong\' + \'gildong\'', g + h) print('type(\'gildong\') : ', type(h)) print('type(\'gildong100!!\') : ', type(i)) print('type(10 + 2j) : ', type(j)) print('type(0b110) : ', type(k)) print(k) print('type(0o56) : ', type(i)) print(i) print('type(0xAC) : ', type(m)) print(m)
 
출력
type(10) : <class 'int'> type(10.1) : <class 'float'> type(-1) : <class 'int'> type(True) : <class 'bool'> type('good') : <class 'str'> '10' + '10' : 1010 '10' * 3 101010 'hong' + 'gildong' honggildong type('gildong') : <class 'str'> type('gildong100!!') : <class 'str'> type(10 + 2j) : <class 'complex'> type(0b110) : <class 'int'> 6 type(0o56) : <class 'int'> 46 type(0xAC) : <class 'int'> 172
 
자료형에 관한 중요한 예제입니다. Python에서 가장 중요한 부분 중 한 부분이기도 합니다. 이 튜토리얼에서 살펴볼 자료형은 숫자, 문자, 부울, 2진수(0b, bin), 8진수(0O, oct)16진수(0x, hex)입니다. 순서대로 살펴보도록 하겠습니다.
 

4.1. 변수

변수는 '변할 수 있는 수', '변할 수 있는 정보'라는 뜻입니다.
프로그램을 만드는 데 필요한 숫자나 문자와 같은 데이터를 보관할 공간이 필요한데, 물건을 잠시 보관하는 상자 같은 역할을 하는 것이 변수입니다.
또한, 변수는 ‘변할 수 있는 수’이므로 저장된 값을 계속 바꿀 수 있습니다.
notion imagenotion image
 

4.2 변수의 자료형

우리가 인터넷으로 물건을 주문하면 주문한 물건의 크기에 걸맞는 택배상자에 담아서 오게 됩니다. 이와 같이 변수도 그 크기에 맞는 형식을 가지고 있습니다.
 
notion imagenotion image
변수의 자료형은 다양한 데이터를 용도에 맞게 쓰기 위해서 입니다. 보통 언어에서는 변수의 자료형과 함께 변수를 선언하지만 파이썬은 자료형을 함께 쓸 필요가 없습니다. 파이썬은 변수에 저장된 값을 스스로 판단하여 자료형을 알아내기 때문입니다. 상자에 물건을 담으려면 알맞은 상자를 알아내어 써야 하는데 자동으로 골라주고 포장까지 해주는 것이죠. 편리하죠?
 

4.3 숫자 자료형

notion imagenotion image
입력
A = 486 B = 0b100 C = 0o56 D = 0xAC E = 3.14 F = 4-4j print(type(A)) print(type(B)) print(type(C)) print(type(D)) print(type(E)) print(type(F))
출력
<class 'int'> <class 'int'> <class 'int'> <class 'int'> <class 'float'> <class 'complex'>
숫자 자료형은 크게 정수형, 실수형, 복소수형으로 나뉩니다.
 

4.4 문자 자료형

작은따옴표(‘ ’)나 큰따옴표(“ ”) 또는 삼중따옴표(“““ ”””, ‘‘‘ ’’’)로 둘러싸서 나타냅니다. 삼중따옴표를 사용할 경우에는 줄단위의 문자열을 나타낼 수 있습니다. 이러한 문자열은 시퀀스 자료형에 해당됩니다.
  • 시퀀스 자료형이란 무엇일까요?
Sequence 즉, 순서가 있는 자료형이라는 뜻으로 각 요소들은 해당하는 Index 값을 갖습니다. 파이썬에서 가장 많이 사용되는 형태의 자료형이며, 시퀀스 자료형이 가지는 특성을 통하여 인덱싱, 슬라이싱, 반복 등 여러 연산으로 그 활용범위가 넓습니다. 파이썬에서는 문자열, 리스트 그리고 튜플이 시퀀스 자료형에 해당됩니다. 여기에 딕셔너리는 포함되지 않으니 주의해주세요.
 
입력
valString = 'abc' valList = [1, 2, 3] valTuple = (1, 2, 3) print(valString[0]) print(valString[1]) print(valString[2]) print(valList[0]) print(valList[1]) print(valList[2]) print(valTuple[0]) print(valTuple[1]) print(valTuple[2])
출력
a b c 1 2 3 1 2 3

4.5 문자열의 활용

문자열 인덱싱
임의의 문자열에서 설정한 인덱스의 문자만 추출해낼 수 있습니다. 인덱스는 항상 0부터 시작하므로 G를 출력하게 됩니다.
notion imagenotion image
 
입력
name = 'Guido van Rossum' print(name[0])
출력
G
문자열 슬라이싱
임의의 문자열에서 설정한 인덱스의 범위에 따라 원하는 부분만을 추출해낼 수 있습니다.
notion imagenotion image
인덱스가 start 인 지점에서 end 미만인 지점까지 추출합니다.
start 를 생략했을 경우 문자열의 시작지점, end 를 생략했을 경우 문자열의 끝지점이 설정됩니다.
[i:j:k]와 같은 형식으로 사용도 가능합니다. 이 경우 순회가능한 객체에 i부터 j만큼의 범위에서 k만큼 건너뛰는 데이타를 말합니다.
입력
birth = "1994.08.13" year = birth[:4] month = birth[5:7] day = birth[8:] print("태어난 연도 : ", year) print("태어난 월 : ", month) print("태어난 일 : ", day)
출력
태어난 연도 : 1998 태어난 월 : 01 태어난 일 : 2

5. 형 변환

입력
print(type(int(3.5))) print(int(3.5)) print(type(float(3))) print(float(3)) print(type(str(3)) print(str(3))
출력
<class 'int'> 3 <class 'float'> 3.0 <class 'str'> 3
기존에 자료형에서 다른 자료형으로 바꾸는 것을 형변환이라고 합니다.
 
입력
x = input('Insert the number.') y = input('Insert the number.') print(x + y) print(type(x)) print(type(y))
출력
Insert the number.4 Insert the number.56 456 <class 'str'> <class 'str'>
 
파이썬에서의 형변환은 아주많은 방법들이 있지만 내장함수를 이용해서 아주 쉽게 할 수 있습니다. 어떤식으로 쓰이는지 간단한 예시를 통해 같이 한번 살펴봅시다.
 
notion imagenotion image
 
int로 형변환
입력
num = '123' print(type(num)) print(type(int(num))
출력
<class 'str'> <class 'int'>
 
string으로 형변환
입력
string = 123 print(type(string)) print(type(str(string)))
출력
<class 'int'> <class 'str'>
 
bool형으로 형변환
입력
print("bool('test') : ", bool('test')) print("bool(1) : ", bool(1)) print("bool(0) : ", bool(0)) print("bool(-1) : ", bool(-1)) print("bool(' ') : ", bool(' ')) print("bool('') : ", bool('')) print("bool(None) : ", bool(None))
출력
bool('test') : True bool(1) : True bool(0) : False bool(-1) : True bool(' ') : True bool('') : False bool(None) : False
bool()함수는 인자값(아규먼트)을 Boolean 자료형으로 형변환 하게 됩니다. 부울 값은 True와 False로 나뉩니다. 부울 값은 직접 입력된 값일 수도 있고 부울 연산에 의해 나온 결과값일 수도 있습니다. 예를 들어 x = 10일 때 x > 100은 False이죠. 또한 이미 Python 내에서 규정한 부울 값일 수도 있습니다. 예를 들어 0은 False, 0을 제외한 다른 숫자는 True입니다.

1.3 연산

연산

연산자에 대해 알아보겠습니다.
 
연산자의 종류에는 산술연산자, 대입연산자(할당연산자), 비교연산자, 논리연산자, 비트연산자, 멤버연산자, 식별연산자가 있습니다. 종류가 상당하기 때문에 처음 보신다면 양이 많아 어려움을 느낄 수도 있습니다.
 
이 연산자들을 한번에 알려고 하는 것은 당장에는 큰 의미가 없습니다. 필요할 때 사용해보면서 익히는 것이 가장 중요하기 때문입니다. 연산자에 익숙하지 않다면 이 장에서는 이런 연산자가 있구나 정도만 알아가시고, 실제 사용할 때 다시 찾아보면서 사용하며 익히는 것이 좋습니다.
 
이 연산자들은 기본적으로는 수의 계산을 위해 존재합니다.
하지만 파이썬을 포함한 일부 프로그래밍 언어에서는 문자열 등과 같은 것들의 연산일 일부 지원해줍니다.
 
연산자는 아래 예시와 같은 형태로 사용할 수 있습니다.
 
a = 9 b = 2 print('a + b = ', a + b) print('a - b = ', a - b) print('a * b = ', a * b) print('a ** b = ', a ** b) print('a / b = ', a / b) print('a // b = ', a // b) print('a % b = ', a % b)
[OUTPUT] a + b = 11 a - b = 7 a * b = 18 a ** b = 81 a / b = 4.5 a // b = 4 a % b = 1
 
notion imagenotion image
 
산술연산자는 가장 많이 접할 수 있고, 자주 사용하는 연산자입니다. 사칙연산부터 제곱, 나머지 등을 구할 수 있는 연산자 등이 있습니다.
보통의 다른 프로그래밍 언어에서는 문자열의 경우 덧셈 연산자만을 지원하지만 파이썬의 경우에는 덧셈 연산자와 곱셈 연산자도 지원합니다.
 
파이썬은 앞서 말한 것과 같이 // 기호를 통해 몫을 계산해주는 기능을 지원하고 있어 편리합니다.
 
numA = 25 numB = 40 print("numA // numB:", numA // numB) print("numA / numB:", numA / numB)
[OUTPUT] # 몫이기 때문에 정수로 나오며 0입니다. numA // numB: 0 # 나눈 결과이기 때문에 소숫점까지 나옵니다. numA / numB: 0.625
 
다른 프로그래밍 언어에서 연산자를 이미 학습하신 분들은 눈치채셨을 수도 있으시겠지만, 파이썬에는 전/후위 연산자가 존재하지 않습니다! (++, --) 이 부분에 대한 설명은 전/후위 연산자를 모르시는 분은 이해하기 조금 어려울 수 있기 때문에 다음 대입연산자로 넘어가시는 편이 좋습니다.
 
전/후위 연산자는 퍼포먼스 면에서 아주 조금 더 낫긴 하지만, 어느 방향에 쓰느냐에 따라서 결과값이 다르게 나오기 때문에 혼란을 줄 우려가 있습니다. 이는 일관성과 가독성을 매우 중요하게 여기는 파이썬의 철학에 어긋나기 때문에 사용할 수 없도록 한 것입니다.
 
실제로 airbnb javascript convention guide의 경우, 자바스크립트는 전/후위 연산자를 사용할 수는 있지만, 결과값이 달라질 수 있다는 이유와 정확한 값을 명시하는 것이 좋다는 이유로 전/후위 연산자를 금지하고 있습니다.
 

 
notion imagenotion image
 
대입 연산자는 산술 연산의 코드를 축약해서 사용할 수 있도록 지원하는 기능입니다.
피연산자를 한번만 사용하기 때문에 대입 연산자를 잘 활용한다면 코드를 좀더 간결하게 사용할 수 있다는 장점이 있습니다.
 
처음 익숙하지 않고, 혼란의 여지가 있을 경우에는 그냥 사칙 연산자인 형태로 쓰셔도 됩니다.
실질적으로 연산 내용은 동일하기 때문에 상관 없습니다.
하지만 간결한 코드를 중요하게 여겨지는 순간이 온다면 그 때 대입연산자로 활용하는 훈련을 조금씩 하면 됩니다.
물론 함께 일하는 팀의 컨벤션 등이 정해진다면 그것에 따르는 것이 좋습니다.
 
numA = 10 numB = 20 numA += numB print("numA:", numA) print("numB:", numB)
[OUTPUT] # numA와 numB가 더해져서 numA는 30이 됩니다. numA: 30 # numB는 변화가 없습니다. numB: 20
 

 
notion imagenotion image
 
비교 연산자는 왼쪽 피연산자와 오른쪽 피연산자의 값을 비교하여 boolean 값으로 반환해주는 역할을 합니다.
간단히 말하면 값을 비교하여 참과 거짓을 구분합니다.
if 조건문과 함께 가장 많이 사용됩니다.
 

 
notion imagenotion image
논리 연산자는 boolean과 함께 쓰이며, 결과값으로 boolean을 반환합니다.
앞서 나왔던 비교연산자와의 조합을 통해 좀더 조건을 까다롭고 명확하게 작성할 수 있습니다.
 
notion imagenotion image
 
비트연산자는 고급 레벨의 코드를 작성할 때 실제 사용할 일이 많이 없기 때문에 당장에 어려움을 느끼신다면 이 부분은 넘어가셔도 좋습니다.
 
비트연산자는 진수 체계로 이루어진 숫자들(2진수, 8진수, 10진수, 12진수 등)로 계산하는 것이 아닙니다.
2진수로 이루어진 32비트의 0과 1로 이루어진 집합으로 표현을 하는 연산입니다.
 
물론 값을 넣을 때는 숫자를 넣습니다.
그리고 위의 말이 조금 이해하기 어렵다면 2진수로 논리 연산을 하신다고 생각하시면 됩니다.
 
a = 2 b = 3 print(a & b)
[OUTPUT] 0
 
위에서 2와 3을 가지고 계산을 했습니다. 이것의 계산 과정을 살펴보겠습니다.
 
# a의 값 2를 2진수로 풀어줍니다. 0010 # b의 값 3을 2진수로 풀어줍니다. 0011 # 위아래로 붙여보겠습니다. 0010 0011 # & 연산의 경우 위와 아래 한짝씩 맞춰 and 비교를 해봅시다. # 이때 1 = True, 0 = False 입니다. 0010 0011 ---- 0010 # 결과값을 다시 10진수로 변환합니다. 2
 
이번에는 | 연산을 해보도록 하겠습니다.
 
a = 7 b = 8 print(a | b)
[OUTPUT] 15
 
# a의 값 7을 2진수로 변환합니다. 0101 # b의 값 8을 2진수로 변환합니다. 1000 # 위아래로 붙여보겠습니다. 0101 1000 # 연산의 경우 위와 아래 한짝씩 맞춰 or 비교를 해봅니다. # 이때 1 = True, 0 = False 입니다. 0101 1000 ---- 1101 # 결과값을 다시 10진수로 변환해줍니다. 15
 
비트연산자의 연산의 전개 과정은 다음과 같습니다.
 
  1. 10진수를 2진수로 변환
  1. 2진수에서 비트연산을 전개
  1. 결과값을 다시 10진수로 변환
 
XOR보수연산 또한 설명 대로 전개하면 되기에 생략하도록 하겠습니다.
 
왼쪽 쉬프트 연산을 한 번 해보겠습니다. 이 때 주의할 점은 왼쪽 쉬프트 연산의 오른쪽 값은 2진수로 바꾸는 용도가 아닙니다. 그만큼 비트 이동을 하겠다는 의미입니다.
 
a = 7 b = 2 print(a << b)
[OUTPUT] 28
# a의 값 3을 2진수로 바꿉니다. 0111 # b 만큼 이동할 것이기 때문에 b는 바꾸지 않음 # a의 값들(집합)을 왼쪽으로 b만큼 이동시키고 뒤에 0을 붙임 011100 # 결과 값을 10진수로 다시 변환합니다. 28
 
이번에는 오른쪽 쉬프트 연산을 해보도록 하겠습니다.
a = 7 b = 2 print(a >> b)
[OUTPUT] 1
# a의 값 7을 2진수로 바꿉니다. 0111 # b만큼 이동할 것이기 때문에 b는 바꾸지 않음 # a의 값들(집합)을 오른쪽으로 b만큼 이동시키고 넘어간 것을 잘라냄 0001(11) # ()는 넘어간 것을 의미합니다. 이것들은 잘라내어 버립니다. 0001 # 결과 값을 10진수로 다시 변환합니다. 1
 
notion imagenotion image
 
멤버 연산자는 원하는 값이 배열에 들어있는지 확인하는 기능입니다.
결과값이 참이면 True를, 거짓이면 False를 반환합니다.
 
a = [1, 2, 3, 4, 5] print(1 in a)
[OUTPUT] True
a = [1, 2, 3, 4, 5] print(0 not in a)
[OUTPUT] True
 

 
notion imagenotion image
 
식별 연산자는 해당 값이 들어있는 값이 들어있는 주소를 비교하는 연산자입니다. C, C++ 언어를 학습하신 분이라면 포인터로 이해하시면 됩니다.
 
그렇지 않으신 분을 위해 간단히 설명하자면, 변수를 선언해서 값을 저장할 때 그 값을 저장하는 공간이 필요한데 그 공간의 위치를 주소라고 합니다. 저희들이 사용하는 주소와 비슷한 개념이라고 보시면 됩니다. 서울시 OO구 OO동 같은 주소 체계를 컴퓨터에서도 가지고 있는 것입니다.
 
coffee 라는 회사에서 일하고 있는 Brand 라는 사람이 있다고 가정합시다.
orange 라는 회사에서 일하고 있는 Brand 라는 사람이 있는 이 둘이 동일 인물인지 확인해봅시다.
coffee = "Brand" orange = "Brand" print(coffee is orange) print(coffee == orange)
[OUTPUT] True True
 
같다면 동일인물이라는 것을 알 수 있습니다.
즉 이 두 회사에 다니고 있는 Brand 라는 이름을 가진 사람은 서울시 OO구 OO동 XX번지에서 살고 있는 동일인물이라고 생각하면 됩니다. (물론 실제로 컴퓨터 내에서의 주소는 이런 주소가 아닌 0012FF64 와 같은 16진수 주소 체계를 가집니다.)
 
이때 그럼 ==와 차이가 뭔지 궁금해할 수 있습니다. == 비교 연산자는 값이 같은지 찾는 것입니다.
위의 예시로 보자면 같은 Brand 라는 이름을 가졌는지를 보는 것입니다.
다음 예시를 보면서 확인해 보겠습니다.
a = [1, 2, 3] b = [1, 2, 3] c = a print('a == b', a == b) print('a == c', a == c) print('a is b', a is b) print('a is c', a is c)
[OUTPUT] a == b True a == c True a is b False a is c True
 
위에서는 Brand 라는 문자열을 예시로 들었습니다. 파이썬의 경우 동일한 문자열이 있다면 해당 문자열을 가진 주소를 그대로 참조하게 되어있습니다. 그렇기 때문에 동일한 문자열을 생성하는 경우에는 동일한 주소를 보고 있게 됩니다. (항상 그런 것은 아닙니다.)
 
배열과 같은 객체는 문자열과 달리 새로 생성할 때 새로운 주소에 담습니다. 따라서 값은 동일하더라도 다른 주소를 가지게 될 수 있습니다.
 
따라서 위의 예시와 같이 a, b, c의 값을 비교하는 것은 True로 나오지만 주소를 비교했을 때는 다르게 나오는 것을 볼 수 있습니다.
 

 
notion imagenotion image
 
연산자의 우선순위는 조금 중요합니다. 하지만 이것을 모두 보고 익히기에는 어렵습니다.
 
먼저, 사칙연산의 우선순위는 대부분 다 아실 것입니다. ( + , - , * , / )
곱셈과 나눗셈이 우선이고, 덧셈과 뺄셈이 그 다음 순위입니다.
그 외에 나머지는 천천히 사용하면서 익혀보며 혼란이 있을 경우에는 괄호()를 이용하여 묶어서 처리하는 것이 더 직관적일 수 있습니다.
 

1.4 함수

Index

  • 들여쓰기
  • function
  • function 연습
  • global
  • function 응용
  • 연산자 우선순위

 

들여쓰기

 
#들여쓰기 def printnum(): print('1') print('2') print('3') printnum()
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
1 2 3
 
def printnum(): print('1') print('2') print('3') printnum()
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
3 1 2
Python은 들여쓰기(intend)로 함수의 범위를 정합니다. 함수의 범위를 규정하는 것을 화이트스페이스(공백)입니다. 탭으로 한번에 들여 쓸 수 있지만 파이썬 개발 제안서(DEP 8)에서는 스페이스 4번으로 하기로 약속했으니 스페이스로 써주세요.
 

 

function

 
def finction(x,y) z = x + y return z print("function(5,7) = ", function(5,7))
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
function(5,7) = 12
 
이처럼 입력과 기능 및 연산, 출력 값이 있는 것을 '함수'라고 말합니다. 함수의 모든 요소가 필요충분조건인 것은 아닙니다. 예를 들어 input이 없는 함수도 있고, return 값이 없는 함수도 있으며(자동으로 None이 할당됩니다.) function이 없는 함수도 있습니다. 함수를 선언하였다면 호출해야만 함수가 작동하게 됩니다. 위 예제에서는 function(5,7)이라는 문장으로 함수를 호출합니다.
 
notion imagenotion image
 

 
def function(x,y): #Input z = x + y #Function print(z) #Output? print("function(5,7) = ", function(5,7))
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
12 function(5,7) = None
가끔 print와 return을 헷갈려 하시는 분들이 계셔서 참고내용으로 넣었습니다. print는 또다른 함수입니다. 위의 예제에서 function(5,7)을 호출한 값을 출력해 보았더니 None이 출력됩니다. 이는 이 함수의 return 값이 없기 때문입니다.
 

function 연습

 
PI = 3.14 def circle(r,inputpi): z = r*r*inputpi return z result = circle(10, PI) print(result)
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
result : 314.0
 
c언어에서는 define이라는 문장을 사용하여 상수를 정의합니다. 상수(Constatnt)란 변경할 수 없는 수 입니다. Python에서는 이러한 상수를 선언하는 문법이 없습니다. 다만 일반적으로 이름 전부를 대문자로 선언하면 상수라고 이해합니다. 여기서는 PI(원주율) 3.14가 상수가 됩니다. 한번 더 주의 깊게 보아야 할 내용은 circle 함수에서 인자값으로 받는 원주율의 변수가 PI가 아니라 inputpi라는 것입니다. 이 개념에 대해서는 다음장 지역변수와 전역 변수를 다루며 말씀드리도록 하겠습니다.
 

 
π = 3.14 def circle(r, inputpi): z = r*r*inputpi return z result = circle(10,π) print(result)
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
result : 314.0
이처럼 특수문자로도 사용이 가능합니다. 같은 원리로 한글 코딩도 가능합니다. 한글 코딩의 장점으로는 고유명사를 표현하기 좋으며, 교육용으로도 주목받고 있습니다. HTML, CSS, Javascript등 다양한 분야에서 한글코딩이 주목받고 있으며 자세한 내용은 김대현 대표님의 '한글코딩.org'에서 확인할 수 있습니다. 아래는 한글코딩 예시입니다.
 
def 한글코딩(글자): print(글자) 한글코딩('안녕, 세상아.')
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
안녕, 세상아
 

 

전역변수 global

 
x = 10 def addx(): global x x = x + 1 return x result = addx() print("result : " , result)
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
result : 11
 

 
지역변수는 함수 내부에서만 사용되는 변수입니다. 함수가 호출되는 동안에만 효력을 발휘하고 함수가 끝나는 동시에 소멸됩니다. 전역변수는 프로그램 어디에서나 접근이 가능한 변수이며 함수 내에서 global를 입력하면 전역변수가 됩니다.
 
지역변수와 전역변수를 왜 나누어 놓았나요?
예를 들어 휴대폰 제조회사에 들어가 휴대폰 앱을 개발하는 업무를 하게 되었다고 가정해 보겠습니다. A라는 사람은 카메라 앱을 개발하는데 x라는 변수를 사용하고 B라는 사람은 음악감상 앱을 개발하는데 변수 x를 사용하는데 이 변수를 자신이 만든 프로그램이 아닌 다른 프로그램에서 조작이 되어진다면 프로그램을 만드는 과정에서 혼선이 생길 수 있어요. 따라서 이러한 혼선을 막기 위해서 프로그래밍 언어에서는 함수 내에서 선언된 변수와 구현 내용을 외부에서 만지지 못하도록 지원하고 있어요.
 
# global 사용전 a = 100 def f(): a = a + 1 f()
# global 사용후 a = 100 def f(): global a a = a + 1 f()
 
함수 안에서 함수 밖에 있는 함수를 만지지 못합니다. 이를 위해 global이라는 함수를 사용하여 모든 함수에서 사용 가능하도록 만들 수 있어요. 그러나 프로그래밍에서 전역변수는 권장하지 않습니다. 연산을 하고 싶다면 함수에 아규먼트(함수의 input)를 대입하여 return으로 받는게 객체 지향 프로그래밍에 적합합니다.
 

 

function 응용

 

함수안에 함수 만들기

 
def 함수이름1(): 코드 def 함수이름2(): 코드
 
이번에는 위 코드처럼 함수 속에 함수를 만드는 방법입니다. 위와 같이 def 로 함수를 만들고 그 안에 다시 def 로 함수를 만들면 됩니다.
 
def print_text(): text = 'Python 기초 배우기!' def print() print(text) print() print_text()
위에 있는 코드를 실행시키면 아래와 같이 출력이 됩니다.
Python 기초 배우기!
함수 print_text 안에서 다시 def로 함수 print를 만들었습니다. 그리고 print_text안에서 print( )처럼 함수를 호출했습니다. 하지만 아직 함수를 정의만 한 상태이므로 아무것도 출력되지 않습니다.
두 함수가 실제로 동작하려면 바깥쪽에있는 print_text를 호출해주어야 합니다. 즉, print_text → print 순으로 실행됩니다.

연산자 우선순위

 
수학계산에서 +와 -보다 ×와÷가 먼저 수행이 되는 것 처럼 파이썬에서도 연산자의 순서가 있습니다.
 
다음은 파이썬의 연산자 우선순위 입니다.
 
notion imagenotion image

 

1.5 자료형

자료형 Type

  1. List
  1. Tuple
  1. Set
  1. Dictionary
 

List

 
리스트는 순서를 가진 데이터들의 집합입니다.
 
리스트는 순서를 가진 데이터들의 집합(Sequence)을 의미합니다.
다른 프로그래밍 언어를 사용하신 분들이라면 배열(Array)이라는 이름으로 더 친숙할 것입니다.
number = [ 0, 1, 2, 3, 4, 5] coffee = [ "Espresso", "Espresso Ristretto", "Espresso Lungo", "Americano" ]
 
파이썬은 하나의 리스트에 다른 타입의 값들을 입력하는 것을 허용합니다.
숫자와 문자열, 그리고 또 다른 리스트가 공존할 수 있는 것을 보실 수 있습니다.
messed_list = [ 100, "Study Python", 300, "Whatever", ["Complex", 50 ] ]
 

접근 (Access)

 
리스트에서 데이터를 꺼내올 때에는 숫자 인덱스를 활용하여 접근할 수 있습니다.
일반적인 프로그래밍 규칙에 따라 인덱스 번호는 0부터 시작합니다.
 
numbers = [ 0, 1, 2, 3, 4, 5] coffee = [ "Espresso", "Espresso Ristretto", "Espresso Lungo", "Americano" ] print("numbers:", numbers[0]) print("coffee:", coffee[1])
[OUTPUT] numbers: 0 coffee: Espresso Ristretto
 
만약 리스트의 인덱스 범위를 초과하는 숫자가 들어가게 된다면 에러가 발생합니다.
 
coffee = [ "Espresso", "Espresso Ristretto", "Espresso Lungo", "Americano" ] print(coffee[10])
[OUTPUT] Traceback (most recent call last): File "/studyLab.py", line 3, in <module> print(coffee[10]) IndexError: list index out of range
 
음수를 인덱스로 사용하면 리스트의 끝에서부터 반대로 접근할 수 있습니다.
 
coffee = [ "Espresso", "Espresso Ristretto", "Espresso Lungo", "Americano" ] print(coffee[-1]) print(coffee[-2]) print(coffee[-3])
[OUTPUT] Americano Espresso Lungo Espresso Ristretto
 
파이썬은 리스트 슬라이싱을 통해 리스트에 접근할 수 있는 특별한 방식을 제공합니다.
이때, 주의해야할 점은 마지막 종료를 알리는 인덱스 번호는 원하는 인덱스보다 하나 더 큰 수를 넣어야 합니다.
 
coffee = [ "Espresso", "Espresso Ristretto", "Espresso Lungo", "Americano" ] # 1. 리스트 전체를 호출 하는 경우 print(coffee) print(coffee[:]) # 2. 리스트 인덱스 1 ~ 3 까지를 출력하고 싶을 경우 print(coffee[1:3]) # 3. 리스트 인덱스 1부터 끝까지 출력하고 싶은 경우 print(coffee[1:]) # 4. 리스트 인덱스 처음부터 2까지를 출력하고 싶을 경우 print(coffee[:3]) # 5. 리스트의 처음부터 시작하여 2만큼 건너뛰면서 호출하고 싶은 경우 print(coffee[::2]) # 6. 리스트 인덱스 처음부터 리스트 인덱스의 범위를 넣어가는 숫자를 넣을 경우 print(coffee[0:5])
[OUTPUT] # 1. 리스트 전체를 호출 하는 경우 ['Espresso', 'Espresso Ristretto', 'Espresso Lungo', 'Americano'] ['Espresso', 'Espresso Ristretto', 'Espresso Lungo', 'Americano'] # 2. 리스트 인덱스 1 ~ 2 까지를 출력하고 싶을 경우 ['Espresso Ristretto', 'Espresso Lungo'] # 3. 리스트 인덱스 1부터 끝까지 출력하고 싶은 경우 ['Espresso Ristretto', 'Espresso Lungo', 'Americano'] # 4. 리스트 인덱스 처음부터 2까지를 출력하고 싶을 경우 ['Espresso', 'Espresso Ristretto', 'Espresso Lungo'] # 5. 리스트의 처음부터 시작하여 2만큼 건너뛰면서 호출하고 싶은 경우 ['Espresso', 'Espresso Lungo'] # 6. 리스트 인덱스 처음부터 리스트 인덱스의 범위를 넣어가는 숫자를 넣을 경우 ['Espresso', 'Espresso Ristretto', 'Espresso Lungo', 'Americano']
 
notion imagenotion image
 
리스트에 있는 데이터는 추가, 수정, 삭제를 할 수 있습니다.
 

추가

 
리스트는 연산을 활용하여 데이터를 추가할 수 있습니다. 리스트에서 가능한 연산은 덧셈과 곱셈입니다.
덧셈 연산을 이용하여 데이터를 추가해 보겠습니다.
 
coffee = [ "Americano" ] # 뒤에 삽입하고 싶은 경우 coffee = coffee + [ "Espresso" ] print(coffee) # 앞에 삽입하고 싶은 경우 coffee = [ "Ristretto" ] + coffee print(coffee) # 앞, 뒤 한번에 하고 싶은 경우 coffee = [ "Lungo" ] + coffee + [ "Cappuccino" ] print(coffee)
[OUTPUT] # 뒤에 삽입하고 싶은 경우 ['Americano', 'Espresso'] # 앞에 삽입하고 싶은 경우 ['Ristretto', 'Americano', 'Espresso'] # 앞, 뒤 한번에 하고 싶은 경우 ['Lungo', 'Ristretto', 'Americano', 'Espresso', 'Cappuccino']
 
이번에는 곱셈 연산을 이용해 데이터를 추가해보겠습니다.
곱셈 연산으로 데이터를 추가하는 것은 많은 양의 더미 데이터를 만들 때에 유용합니다.
 
coffee = [ "Espresso", "Americano" ] double_coffee = coffee * 2 print(double_coffee)
[OUTPUT] ['Espresso', 'Americano', 'Espresso', 'Americano']
 
리스트 내장함수인 append를 활용하여 추가할 수도 있습니다.
 
coffee = [ "Americano" ] coffee.append("Cafe Latte") print(coffee)
[OUTPUT] [ 'Americano', 'Cafe Latte' ]
 
리스트 내장함수인 extend를 활용하여 추가할 수도 있습니다. extend는 동일한 자료형인 리스트를 뒤로 추가해주는 역할을 합니다.
 
coffee = [ "Americano" ] coffee.extend([ "Cafe Mocha", "Ristretto" ]) print(coffee) other_menu = [ "Ice tea", "Green Tea" ] coffee.extend(other_menu) print(coffee)
[OUTPUT] ['Americano', 'Cafe Mocha', 'Ristretto'] ['Americano', 'Cafe Mocha', 'Ristretto', 'Ice tea', 'Green Tea']
 
리스트 내장함수인 insert를 활용하여 추가할 수도 있습니다. insert는 원하는 인덱스 자리에 원하는 값을 추가해주는 역할을 합니다.
이때 원하는 인덱스의 숫자가 리스트의 범위를 초과하면 리스트의 마지막 인덱스로 추가됩니다.
 
coffee = [ "Americano" ] coffee.insert(1, "Maxim Mocha Gold") coffee.insert(2, "Strawberry Yogurt Blended") coffee.insert(10, "More Info") print(coffee)
[OUTPUT] ['Americano', 'Maxim Mocha Gold', 'Strawberry Yogurt Blended', 'More Info']
 

수정

리스트의 데이터를 수정할 때는 인덱스로 접근하여 수정할 수 있습니다.
 
coffee = [ "Espresso", "Espresso Ristretto", "Espresso Lungo" ] coffee[1] = "Ristretto" coffee[2] = "Lungo" print(coffee)
[OUTPUT] [ 'Espresso', 'Ristretto', 'Lungo' ]
 

삭제

리스트의 데이터를 삭제할 때에는 del 이라는 예약어를 사용하여 삭제할 수 있습니다.
 
coffee = [ "Espresso", "Cafe Mocha", "Espresso Ristretto", "Espresso Lungo" ] # "Cafe Mocha" 문자열을 삭제하고 싶습니다. del coffee[1] print(coffee)
[OUTPUT] ['Espresso', 'Espresso Ristretto', 'Espresso Lungo']
 
혹은 원하는 데이터를 삭제하고 싶을 때는 리스트의 remove 라는 내장함수를 활용하여 삭제할 수 있습니다.
하지만 remove 는 원하는 데이터 값을 넣었을 때 리스트 안에서 발견된 첫번째 데이터만 삭제합니다.
이것을 확인하기 위해 "Cafe Mocha"를 두 번 넣어보도록 하겠습니다.
 
coffee = [ "Espresso", "Cafe Mocha", "Cafe Mocha", "Dolce Latte" ] coffee.remove("Cafe Mocha") print(coffee)
[OUTPUT] ['Espresso', 'Cafe Mocha', 'Dolce Latte']
 
위와 같이 "Cafe Mocha" 문자열이 하나 남아있는 것을 볼 수 있습니다. 따라서 remove를 사용할 때에는 주의할 필요가 있습니다.
 
그 외에 리스트의 다른 내장함수들을 살펴보도록 하겠습니다.
 

정렬

리스트의 내장함수인 sort를 활용하여 요소들을 정렬할 수 있습니다.
sort는 기본적으로 오름차순으로 정렬합니다.
반대로 내림차순으로 정렬하고 싶은 경우에는 reverse=True 인자를 삽입해 줍니다.
 
coffee = [ "Espresso", "Cafe Mocha", "Cafe Mocha", "Dolce Latte" ] # 오름차순 정렬 coffee.sort() print(coffee) # 내림차순 정렬 coffee.sort(reverse=True) print(coffee)
[OUTPUT] # 오름차순 정렬 ['Cafe Mocha', 'Cafe Mocha', 'Dolce Latte', 'Espresso'] # 내림차순 정렬 ['Espresso', 'Dolce Latte', 'Cafe Mocha', 'Cafe Mocha']
 
정렬에는 조금 주의해야할 사항이 있는데 숫자가 앞에 오는 문자열을 정렬을 할 때입니다.
리스트의 데이터가 숫자 타입으로 되어 있을 경우에는 별로 문제가 되지 않지만, 숫자가 앞에 오는 문자열인 경우에는 조금 주의가 필요합니다.
 
cafe_menu = [ "1.Espresso", "2.Cafe Mocha", "3.Cafe Mocha", "11.Dolce Latte", "12.Ice tea", "13.Green Tea" ] cafe_menu.sort() print(cafe_menu)
[OUTPUT] ['1.Espresso', '11.Dolce Latte', '12.Ice tea', '13.Green Tea', '2.Cafe Mocha', '3.Cafe Mocha']
 
숫자는 크기로 비교가 가능하지만 문자열은 가장 첫번째 글자부터 비교를 하기 때문에 위와 같이 원하지 않는 결과가 나올 수도 있음을 염두에 두어야 합니다.
 

반전

리스트의 내장함수인 reverse를 활용하여 리스트를 반전시킬 수 있습니다.
 
coffee = [ "Espresso", "Espresso Ristretto", "Espresso Lungo", "Americano" ] coffee.reverse() print(coffee)
[OUTPUT] ['Americano', 'Espresso Lungo', 'Espresso Ristretto', 'Espresso']
 
슬라이싱을 활용하여 리스트를 반전시켜 출력할 수도 있습니다.
coffee = [ "Espresso", "Espresso Ristretto", "Espresso Lungo", "Americano" ] print(coffee[::-1])
[OUTPUT] ['Americano', 'Espresso Lungo', 'Espresso Ristretto', 'Espresso']
 

원하는 데이터 개수 세기

리스트의 내장 함수인 count를 활용하여 원하는 데이터의 개수를 확인할 수 있습니다.
 
coffee = [ "Espresso", "Cafe Mocha", "Cafe Mocha", "Dolce Latte" ] print(coffee.count("Cafe Mocha"))
[OUTPUT] 2
 

Tuple

 
튜플(Tuple)은 리스트와 거의 비슷한 형태입니다.
다만 리스트는 변경이 가능(mutable)하고 튜플은 변경이 불가능(immutable)하다는 차이가 있습니다.
 
number_list = [1, 2, 3] number_tuple = (1, 2, 3) number_list[1] = 4 print(number_list) number_tuple[1] = 4 print(number_tuple)
# number_list [1, 4, 3] # number_tuple Traceback (most recent call last): File "/study.py", line 7, in <module> tuple[1] = 4 TypeError: 'number_tuple' object does not support item assignment
 
튜플은 변경이 불가능하다는 속성이 있기 때문에 변경되어서는 안될 내용들을 담아두면 좋습니다.
또한 리스트는 변경이 가능해야 하기 때문에 요소를 추가/수정하는 동작을 수행하기 위해 추가적인 공간을 보유하고 있지만, 튜플은 변경이 불가능하기 때문에 굳이 그럴 필요가 없어 불필요한 공간이 없습니다.
따라서 튜플이 리스트에 비해 공간적으로도 더 효율적입니다.
 

Set

 
집합 자료형은 중복을 허용하지 않으며, 순서가 없는 자료형입니다.
 
number_set = set([1, 1, 2, 2, 3, 3, 4]) print(number_set)
[OUTPUT] {1, 2, 3, 4}
 
위의 예제를 보면 같은 숫자들은 다 제거되고 하나만 남은 것을 볼 수 있습니다.
 
number_set = set('apple coffee') print(number_set)
[OUTPUT] {'o', 'e', 'c', ' ', 'l', 'f', 'p', 'a'}
 
문자열을 넣었을 경우 실행할 때마다 순서가 계속 달라지는 것을 볼 수 있습니다.
 
집합 자료형에 값을 추가할 때는 add를 사용합니다.
menu = set(['americano', 'cafe latte']) menu.add('ice coffee') print(menu)
[OUTPUT] {'cafe latte', 'ice coffee', 'americano'}
 
값을 여러 개를 추가할 때에는 update를 사용합니다.
menu = set(['americano', 'cafe latte']) menu.update(['ice coffee', 'ice tea', 'green tea']) print(menu)
[OUTPUT] {'ice coffee', 'green tea', 'americano', 'ice tea', 'cafe latte'}
 
특정 값을 제거하고 싶을 때에는 remove를 사용합니다.
menu = set(['americano', 'cafe latte']) menu.remove('cafe latte') print(menu)
[OUTPUT] {'americano'}
 
집합 자료형은 집합이라는 이름에 맞게 교집합, 합집합, 차집합을 구할 수 있습니다.
 
교집합은 & 혹은 intersection 함수를 사용하여 구합니다.
my_cafe = set(['americano', 'water', 'yogurt strawberry blended', 'cafe latte']) other_cafe = set(['americano', 'water', 'green tea']) print(my_cafe & other_cafe) print(my_cafe.intersection(other_cafe))
[OUTPUT] {'water', 'americano'} {'water', 'americano'}
 
합집합은 | 또는 union 함수를 사용하여 구합니다.
my_cafe = set(['americano', 'water', 'yogurt strawberry blended', 'cafe latte']) other_cafe = set(['americano', 'water', 'green tea']) print(my_cafe | other_cafe) print(my_cafe.union(other_cafe))
[OUTPUT] {'americano', 'green tea', 'cafe latte', 'yogurt strawberry blended', 'water'} {'americano', 'green tea', 'cafe latte', 'yogurt strawberry blended', 'water'}
 
차집합은 - 또는 difference 함수를 사용하여 구합니다.
my_cafe = set(['americano', 'water', 'yogurt strawberry blended', 'cafe latte']) other_cafe = set(['americano', 'water', 'green tea']) print(my_cafe - other_cafe) print(my_cafe.difference(other_cafe))
[OUTPUT] {'yogurt strawberry blended', 'cafe latte'} {'yogurt strawberry blended', 'cafe latte'}
 

Dictionary

 
사전형은 Key와 Value 가 하나의 묶음으로 이루어진 자료 체계입니다.
다른 프로그래밍 언어에서는 Hash, Map 등 이라고도 불립니다.
 
{ key : value }
 
위의 형태가 기본 형태입니다.
여러가지의 키와 값이 들어갔을 때는 다음과 같습니다.
 
teammate_age = { 'Kevin': 15, 'Dean': 20, 'Berra': 17 }
 
다음 예제처럼 value에 리스트를 넣을 수도 있습니다.
menu = { coffee : ['americano', 'cafe latte', 'mocah latte'], tea: ['green tea', 'black tea'], fruits: ['orange juice', 'pineapple juice'] }
 
사전형에 값을 추가할 때는 키값을 []안에 넣고, 값을 할당해줍니다.
my_score = { 'korean': 90, 'english': 80, 'math': 100 } my_score['science'] = 95 print(my_score)
[OUTPUT] {'korean': 90, 'english': 80, 'math': 100, 'science': 95}
 
사전형에 요소를 삭제하고 싶을 때는 del 키를 사용합니다.
my_score = { 'korean': 90, 'english': 80, 'math': 100 } del my_score['english'] print(my_score)
[OUTPUT] {'korean': 90, 'math': 100}
 
사전형은 KeyValue가 매칭되어 있기 때문에 어떤 값을 찾아오는데에 굉장히 편리합니다.
# 국어 성적을 알고 싶은 경우 my_score = { 'korean': 90, 'english': 80, 'math': 100 } print(my_score['korean']) # get 함수를 이용하여 가져올 수도 있습니다. print(my_score.get('korean')) # 다만 해당하는 키가 없을 때 # 키값만을 이용하여 가져오는 경우에는 오류가 발생하며 get을 사용할 때에는 None을 리턴합니다. # 오류에 대한 예외처리가 있는 안전한 get을 사용하는 것이 바람직해 보입니다.
[OUTPUT] 90 90
 
다만 사전형에서의 Key 값은 고유한 값이기 때문에 동일한 이름으로 사용할 수 없습니다.
my_score = { 'korean': 90, 'english': 80, 'math': 100, 'math': 90 } print(my_score)
[OUTPUT] {'korean': 90, 'english': 80, 'math': 90}
 
일반적으로 생각해도 Key 값을 기준으로 값을 찾아야 하기 때문에 고유할 수 밖에 없습니다.
Key 값으로 리스트를 사용할 순 없지만, 튜플은 키값으로 사용할 수 있습니다. Key가 고유하다는 점을 생각해보면 변할 수 있는 리스트는 사용해서는 안되겠지요.
map_check = { (1, 3): 10293, (1, 2): 39492, (1, 1): 49377, (1, 4): 12375 } print(map_check)
[OUTPUT] {(1, 3): 10293, (1, 2): 39492, (1, 1): 49377, (1, 4): 12375}
my_check = { [1, 3]: 10293, [1, 2]: 39492, [1, 1]: 49377, [1, 4]: 12375 } print(my_check)
[OUTPUT] Traceback (most recent call last): File "/study.py", line 5, in <module> [1, 4]: 12375 TypeError: unhashable type: 'list'
 
사전 자료형에 있는 Key 값들을 가져오려면 keys 함수를 사용합니다. 이때 반환되는 것은 dict_keys 객체입니다. 이 객체는 리스트와 비슷하게 반복문을 사용할 수 있습니다.
map_check = { (1, 3): 10293, (1, 2): 39492, (1, 1): 49377, (1, 4): 12375 } print(map_check.keys())
[OUTPUT] dict_keys([(1, 3), (1, 2), (1, 1), (1, 4)])
 
사전 자료형에 있는 value 값들을 가져오려면 values 함수를 사용합니다. 이때 반환되는 것은 dict_values 객체입니다. 이 객체는 리스트와 비슷하게 반복문을 사용할 수 있습니다.
map_check = { (1, 3): 10293, (1, 2): 39492, (1, 1): 49377, (1, 4): 12375 } print(map_check.values())
[OUTPUT] dict_values([10293, 39492, 49377, 12375])
 
사전 자료형에 있는 KeyValue를 리스트의 형태로 얻기 위해서는 items 함수를 사용합니다. 이때 반환되는 것은 dict_items 객체입니다. 이 객체는 리스트와 비슷하게 반복문을 사용할 수 있습니다.
map_check = { (1, 3): 10293, (1, 2): 39492, (1, 1): 49377, (1, 4): 12375 } print(map_check.items())
[OUTPUT] dict_items([((1, 3), 10293), ((1, 2), 39492), ((1, 1), 49377), ((1, 4), 12375)])
 
자료 사전형 안에 원하는 Key가 있는지 찾아볼 때에는 in 을 활용할 수 있습니다.
my_score = { 'korean': 90, 'english': 80, 'math': 100 } print('math' in my_score) print('science' in my_score)
[OUTPUT] True False

1.6 클래스

클래스

클래스는 데이터와 기능을 가지고 있는 인스턴트 객체를 생성하기 위한 역할을 합니다.
파이썬은 대표적인 객체지향 프로그래밍 언어입니다.
클래스는 일종의 설계도면입니다.
파이썬은 이 설계도면을 보며 하나의 인스턴스 객체를 만들어 냅니다.
그리고 그 인스턴스 객체를 사용할 수 있게 됩니다.
 
class Car(object): MaxSpeed = 300 MaxPeople = 5 def move(self, x): print(x, '의 스피드로 움직이고 있습니다.') def stop(self): print('멈췄습니다.') k5 = Car() k3 = Car() k5.move(10) k5.stop() k3.move(5) k3.stop() print(k5.MaxSpeed) print(k3.MaxSpeed)
[OUTPUT] 10 의 스피드로 움직이고 있습니다. 멈췄습니다. 5 의 스피드로 움직이고 있습니다. 멈췄습니다. 300 300

클래스 변수

class Car(object): # 클래스 변수 위치 (파이썬 규약에 따라 indent로 결정) kinds = [] MaxSpeed = 300 MaxPeople = 5 def move(self, x): print(x, '의 스피드로 움직이고 있습니다.') def stop(self): print('멈췄습니다.') k5 = Car() Car.kinds.append('k5') k3 = Car() Car.kinds.append('k3') print(k5.kinds)
[OUTPUT] ['k5', 'k3']
 
클래스 변수는 다른 클래스 메서드의 위치와 동등한 클래스 바로 하위에 자리하고 있는 변수들 입니다.
이 클래스 변수는 위의 예시와 같이 클래스 이름을 통해서 접근할 수 있습니다.
(주의: 변수 이름으로 접근하지 않음)
 
이 클래스 변수는 해당 클래스를 통해 만들어진 모든 인스턴스 객체들이 공유하는 변수 값입니다.
각 인스턴스 객체들 각자가 관리하고 있는 변수는 인스턴스 변수라고 합니다.
 
위의 예시에서는 인스턴스를 생성할 때마다 어떤 인스턴스가 만들어졌는지 확인하기 위해서 생성할 때마다 Car.kinds 에 접근하여 해당 배열에 어떤 자동차가 추가되었는지를 표시하고 있습니다.
 
하지만 이렇게 처음 시작시에 일일이 메서드를 호출해서 하는 것은 너무 불편하고 실수가 생길 수 밖에 없는 작업입니다. 이런 불편을 해소하기 위해 __init__ 메서드가 있습니다.
 
이 클래스 변수를 다룰 때는 조금 주의해야 할 것이 있습니다.
 
주소나 포인터의 개념에 대해 아직 익숙하지 않다면 해당 부분에서는 클래스 변수에 접근할 때는 인스턴스 객체의 변수명이 아닌 클래스명을 통해 접근해야 한다는 것만 알고 넘어가도 좋습니다.
 
class Car(object): kinds = [] speed = 300 def add_kinds(self, name): self.kinds.append(name) def change_speed(self, speed): self.speed = speed k5 = Car() k3 = Car() k5.add_kinds('k5') k3.add_kinds('k3') k5.change_speed(500) k3.change_speed(250) print('k5.kinds:', k5.kinds) print('k3.kinds:', k3.kinds) print('k5.speed:',k5.speed) print('k3.speed:',k3.speed)
[OUTPUT] k5.kinds: ['k5', 'k3'] k3.kinds: ['k5', 'k3'] k5.speed: 500 k3.speed: 250
 
클래스 변수를 다룰 때는 클래스 자체(예시에서는 Car 객체)를 이용하여 다루어야 하지만, 위의 예시에서는 각 인스턴스 객체들이 각각 자신의 메서드를 통해 접근해서 다루고 있습니다.
 
kinds 는 원래 기대했던 클래스 변수처럼 결과가 나왔고, speed는 그렇지 않는 것을 볼 수 있습니다. 이 차이는 kinds는 배열이고, speed는 값이기 때문입니다.
 
kinds 배열의 경우에는 각 인스턴스 객체가 해당 배열의 주소를 참조하고 있기 때문에, 그 배열의 주소에 접근하여 조작해서 마치 클래스 변수와 동일하게 동작을 하게된 것입니다. 반면에 speed 의 경우에는 단순히 값이기 때문에 주소가 따로 없으므로 각 인스턴스 객체가 값만을 가지고 있습니다. 따라서 변화를 시도했을 경우에 각 인스턴스 객체들의 값이 따로 변하게 됩니다.
 

__init__ 함수

class Car(object): kinds = [] MaxSpeed = 300 MaxPeoeple = 5 def __init__(self, name): Car.kinds.append(name) def move(self, x): print(x, '의 스피드로 움직이고 있습니다.') def stop(self): print('멈췄습니다.') k5 = Car('k5') k3 = Car('k3') print(k5.kinds) print(k3.kinds)
[OUTPUT] ['k5', 'k3']
 
__init__ 메서드는 다른 프로그래밍 언어에서의 생성자(constructor) 역할을 하는 클래스 메서드입니다.
이 메서드는 인스턴스 객체를 생성시에 자동으로 실행합니다.
 

인스턴스 변수

인스턴스 객체들이 모두가 공통으로 공유하는 값이 클래스 변수라면, 인스턴스 변수는 각 인스턴스 객체들 각자가 가지고 있는 값입니다.
class Car(object): # 클래스 변수 max_speed = 300 def __init__(self, name): # 인스턴스 변수 self.kinds = [] self.auto_drive = False self.kinds.append(name) def add_auto_drive(self): self.auto_drive = True my_car = Car('mini') your_car = Car('big') print('my_car.kinds:', my_car.kinds) print('your_car.kinds:', your_car.kinds) print('my_car.auto_drive:', my_car.auto_drive) my_car.add_auto_drive() print('my_car.auto_drive:', my_car.auto_drive) print('your_car.auto_drive:', your_car.auto_drive)
[OUTPUT] my_car.kinds: ['mini'] your_car.kinds: ['big'] my_car.auto_drive: False my_car.auto_drive: True your_car.auto_drive: False
 
인스턴스 변수는 __init__ 메서드 안에서 선언을 해주어야 합니다. 이곳에서 선언된 변수들은 각 인스턴스 객체들의 변수로 활동할 수 있습니다.
 

상속

class Car(object): maxSpeed = 300 maxPeople = 5 def __init__(self, name): self.kinds = [] self.kinds.append(name) def move(self, x): print(x, '의 스피드로 움직이고 있습니다.') def stop(self): print('멈췄습니다.') class HybridBigCar(Car): battery = 1000 batteryKM = 300 maxPeople = 7 def electronic_power(self): print('전기를 생산합니다') my_car = Car('mini') my_second_car = HybridBigCar('e-big') print(my_second_car.kinds) print(my_second_car.battery) print(my_second_car.maxPeople) my_second_car.electronic_power()
[OUTPUT] ['e-big'] 1000 7 전기를 생산합니다
 
클래스를 상속하는 방법은 위의 예시처럼 새로운 클래스의 ()안에 상속할 클래스명을 적어주는 것입니다.
HybridBigCar 클래스는 기존의 Car 클래스가 사용하던 데이터와 기능들을 모두 사용할 수 있으며, 추가적인 기능을 만들었습니다.
또한 maxPeople 의 데이터를 새로 덮어씌워 자기 자신만의 클래스 변수를 새로 정의할 수 있습니다.
 
여기에서 상속을 하는 Car를 부모 클래스(슈퍼 클래스)라고 부르고 HybridBigCar를 자식 클래스(서브 클래스)라고 부릅니다.
 

다중 상속

 
여러 클래스를 상속받을 때는 아래와 같이 사용하면 됩니다. 상속을 받는 법은 비슷합니다.
 
class Car(object): maxSpeed = 300 maxPeople = 5 def __init__(self, name): self.kinds = [] self.kinds.append(name) def move(self, x): print(x, '의 스피드로 움직이고 있습니다.') def stop(self): print('멈췄습니다.') class MaxWheel(object): wheel = 19 class MiniWheel(object): wheel = 15 class LargeCar(Car, MaxWheel): pass class CompactCar(Car, MiniWheel): pass my_car = LargeCar('big') your_car = CompactCar('mini') print(my_car.wheel) print(your_car.wheel)
[OUTPUT] 19 15
 
여기에서 다중 상속을 할 때에 상속을 하는 것에 대한 우선 순위를 보도록 하겠습니다.
 
class Car(object): maxSpeed = 300 maxPeople = 5 def __init__(self, name): self.kinds = [] self.kinds.append(name) def move(self, x): print(x, '의 스피드로 움직이고 있습니다.') def stop(self): print('멈췄습니다.') class MaxWheel(object): wheel = 19 def move(self, x): print(x, '의 스피드로 큰 차가 이동 중입니다.') class MiniWheel(object): wheel = 15 maxSpeed = 250 def move(self, x): print(x, '의 스피드로 작은 차가 이동 중입니다.') class TestWheel(object): def move(self, x): print(x, '의 스피드로 테스트 차가 이동 중입니다.') class LargeCar(Car, MaxWheel): pass class CompactCar(Car, MiniWheel): pass class TestCar(Car, MaxWheel, TestWheel): pass my_car = LargeCar('big') your_car = CompactCar('mini') test_car = TestCar('test') print(my_car.wheel) print(your_car.wheel) print(your_car.maxSpeed) your_car.move(100) test_car.move(100)
[OUTPUT] 19 15 300 100 의 스피드로 움직이고 있습니다. 100 의 스피드로 움직이고 있습니다.
 
위의 예제에서 볼 수 있듯이 먼저 매개변수로 오는 것의 데이터와 메소드가 우선순위가 되는 것을 볼 수 있습니다.
TestCar를 예로 들면 같은 데이터, 메소드가 있을 경우 다음과 같은 우선 순위를 가지게 됩니다.
 
TestCar > Car > MaxWheel > TestWheel
 

특별 메소드(magic method)

 
class Cafe(object): def __init__(self, name): self.name = name def rename(self, name): self.name = name def __getattr__(self, item): print(item + '속성은 존재하지 않습니다.') my_cafe = Cafe('Dutch') print(my_cafe.name) print(my_cafe.menu)
[OUTPUT] Dutch menu속성은 존재하지 않습니다. None
 
파이썬에서의 클래스에는 기본적으로 내장하고 있는 특별 메소드들이 있습니다.
파이썬에서는 이런 내장하고 있는 특별 메소드들을 쉽게 재정의하여 사용할 수 있게 되어있습니다.
마치 마법처럼 간단하게 수정할 수 있다고 해서 매직 매소드라고 부릅니다.
혹은 더블 언더바(__)를 쓰고 있는 점에서 줄여서 던더(dunder) 메소드라고도 부릅니다.
 
위의 예시에서 __init____getattr__이 특별 메소드입니다. 예시에서 보는 바와 같이 파이썬에 내장되어 있는 특별 메소드들을 쉽게 재정의하여 사용할 수 있습니다.
 
특별 메소드들의 종류를 자세하게 알고 싶다면 파이썬 공식 홈페이지를 참고바랍니다.