파이썬 특강 1부

들여쓰기

C, Java, Javascript 등 많은 언어에서 코드의 단락을 구분하기 위해 중괄호({})를 사용한다. 반면에 파이썬은 들여쓰기를 사용하여 코드단락(code block)을 구분한다. 또한 문장 구조의 복잡성을 들여쓰기의 정도로 구분하여 가독성과 코드단락의 시작과 끝을 명확히 한다.

예를 들어, 중첩된 for 반복문은 다음과 같이 작성한다. 들여쓰기에 주의하라.

줄바꿈

소괄호(())와 대괄호({}) 안에서는 공백문자(whitespace)가 무시된다. 따라서 다음과 같은 긴 계산을 할 때 줄바꿈을 이용할 수 있다.

줄바꿈을 괄호가 없을 경우 사용하려면 백슬래시(backslash)을 사용한다.

주의사항

책의 설명과 달리 빈 줄을 사용해도 오류가 발생하지 않는다. 아마도 파이썬이 업드레이드 되면서 달라진 요소로 보인다.

반면에 들여쓰기 일정하지 않을 경우 오류가 발생하기 때문에 단락별 들여쓰기를 일정하게 유지해야 한다.

아래 코드에서 print(i) 명령문이 한 단계 더 들어가 있으며, 결과적으로 인덴테이션에러(IndentationError), 즉, 들여쓰기 오류가 발생한다.

모듈과 패키지

파이썬을 실행할 때 기본적으로 사용할 있는 기능 이외의 것들을 사용하려면 관련 모듈과 패키지를 추가로 설치하거나 불러와야 한다.

모듈 불러오기

예를 들어, sin, cos, log, ceil, floor 등 다양한 수학 함수들을 사용하려면 math 모듈을 다음과 같이 불러와야 한다.

이제 math 모듈에 포함된 log 함수를 활용할 수 있다.

즉, 특정 모듈에 포함된 함수나 변수를 사용하려면 아래 형식으로 호출한다.

모듈이름.함수이름(변수,...)

모듈 별칭 사용하기

모듈이름으로 별칭(alias, 에일리어스)을 사용할 수 있다. 별칭을 사용하는 이유는 주로, 이름을 간단하게 하기위해서이거나 이름이 중복되지 않게 하기 위해서이다.

별칭예제 1: math 모듈을 예를 들어 m 이라는 별칭으로 부를 수 있다. 단, 별칭을 사용하면 반드시 별칭으로만 사용해야 한다.

관습적 별칭

자주 사용되는 모듈에 대한 별칭은 커뮤너티에서 관습적으로 사용하는 별칭이 있다. 별칭에 대한 규정이 있지는 않지만 관습을 따르는 것이 혼동을 방지하며, 소스코드의 가독성과 협업의 효율성을 증대시킨다.

주의: math 모듈은 굳이 별칭을 사용하지 않는다. 앞에서는 별칭을 사용할 수 있다는 것을 보여주기 위함이었다.

별칭예제 2: 데이터를 시각화할 때는 맷플롯립(matplotlib) 패키지에 포함된 파이플롯(pyplot)이라는 모듈을 많이 사용하며, 관습적으로 plt라는 별칭을 사용한다.

아래 그래프는 대한민국 1인당 국민총소득(GNI)의 변천사를 1960년부터 5년 단위로 보여준다.

출처: 한국은행,「국민계정」, 통계청,「장래인구추계」

패키지와 모듈

모듈은 파이썬 소스코드 파일을 가리키며 확장자가 py이다. 반면에 패키지는 여러 개의 모듈을 담고 있는 디렉토리, 즉 폴더를 가리킨다. 단, 폴더 안에 __init__.py 라는 특수 역할을 수행하는 파이썬 파일이 포함되어 있어야 한다.

예를 들어, matplotlib 패키지 (폴더) 안에는 pyplot 이외에 path, patches, date 등 사용 기능별로 구분된 함수와 변수들을 담은 모듈들이 포함되어 있다.

모듈의 특정 기능만 불러오기

모듈에 포함된 기능들 중에서 특정 기능 몇 개만 불러올 경우 해당 기능만 명시해서 불러올 수 있다.

아래 코드는 컬렉션즈(collections) 모듈에서 디폴트딕트(defaultdict) 함수와 카운터(Counter) 클래스만 불러온다.

주의: 모듈에서 특정 기능만 불러올 경우 모듈의 이름을 명시하지 않는다.

디폴트딕트(defaultdict) 함수와 카운터(Counter) 클래스의 활용은 이후에 자세히 살펴볼 예정이다.

좋지 않은 습관:

특정 모듈에 포함된 모든 기능을 한꺼번에 불러오는 것은 매우 좋지 않은 습관이다. 이유는 서로 다른 모듈에 동일한 이름의 중복되어 사용될 수도 있고 또 기존에 사용된 이름을 덮어쓰는 위험이 도사리기 때문이다.

아래 예제는 매치(match)라고 이미 선언된 변수가 정규표현식 모듈 re에 포함된 match 라는 다른 기능의 함수에 의해 덮어씌어지는 문제를 보여준다.

주의: 프로그래밍 언어에서 별표(*)는 일반적으로 모든 것(all)을 의미한다.

함수

임의의 개수의 인자를 받아 결과를 반환하는(return, 리턴) 일종의 규칙을 함수라 부르며, 파이썬에서는 데프(def)라는 키워드를 사용하여 함수 선언을 명시한다.

입력 인자 개수는 함수 선언에서 사용되는 매개변수의 개수로 지정된다. 아래에서 선언되는 함수 double은 매개변수를 x 하나만 사용한다. 즉, 인자를 하나 입력 받아 그 인자의 두 배를 반환하는 함수인 더블(double)을 선언한다.

주의:

문서화 문자열(docstring)

함수 선언 본체(body)에 사용된 세 개의 큰따옴표는 주석을 지정할 때 사용되며, 함수의 기능을 설명하는 설명서 역할을 수행한다. 전문 용어로 문서화 문자열(docstring, 독스트링)이라 불리며, 소스코드의 구성과 구현과 관련된 내용을 문서화를 할 때 매우 유용하게 사용되는 기능이다.

예를 들어 double 함수에 대한 정보를 요구할 때 큰따옴표 안의 설명이 보여지며, 이를 위해 헬프(help) 함수를 이용한다.

제1종 객체와 함수

파이썬에서 다루는 대상 중에 제1종 객체(first-class objects)는 변수에 할당되거나 함수의 인자로 사용될 수 있는 대상을 가리킨다.

파이썬의 경우 다루는 모든 대상이 제1종 객체이다. C 언어의 함수, Java 언어의 메소드(함수)는 제1종 객체가 아니다. 반면에 파이썬, 자바스크립트(Javascript) 언어에서 함수는 제1종 객체이다.

예를 들어, 아래에 정의된 함수 어플라이-투-원(apply_to_one)은 임의의 함수 f를 인자로 받아 f(1)의 값을 반환한다. 즉, 함수 f(1)을 실행한 결과값을 반환한다.

따라서 apply_to_one(my_double)my_double(1), 즉 2를 반환한다.

람다(lambda) 함수

함수를 정의할 때 def라는 키워드를 사용해서 함수의 이름과 함수의 본체를 이용하여 함수를 선언하였다. 하지만 익명 함수, 즉 이름이 없는 함수를 선언할 수도 있으며, 이를 위해 람다(lambda) 기호를 사용한다.

람다 함수를 정의하는 형식은 다음과 같다.

lambda x1, x2, ..., xn: 반환값

위 정의는 n개의 인자를 받는 함수를 정의하며 def 키워드를 사용하면 아래 정의에 해당한다.

def 아무이름(x1, x2, ..., xn):
    return 반환값

예를 들어,

lambda x: x+4

는 숫자 하나를 입력 받으면 4를 더한 값을 반환한다.

따라서 이 함수를 apply_to_one 함수의 인자로 사용하면 5를 결과로 얻는다.

두 개 이상의 인자를 받는 람다 함수의 예제는 다음과 같다. 아래 함수

lambda x y: (x + y)/2

는 인자 두 개를 입력받아 두 값의 평균값을 반환한다.

람다 함수에 인자를 입력하여 호출하는 방식은 다음과 같다.

(람다 함수)(인자1, 인자2, ..., 인자n)

예를 들어, 2와 4의 평균값을 다음과 같이 구할 수 있다.

함수를 인자로 사용할 때 주의점

파이썬에서 함수 역시 제1종 객체이기 때문에 다른 함수의 인자로 사용할 수 있다. 다만 함수를 정의할 때 사용되는 매개변수의 자료형에 주의하면서 사용해야 하듯이 함수를 인자로 사용할 때 주의할 점이 두 가지 있다.

예를 들어, apply_to_one 함수에 인자를 두 개 이상 받는 다변수 함수를 입력하면 오류가 발생한다. 이유는 하나의 인자만 받는 함수에 대해서만 정의되어 있기 때문이다.

또한 인자를 하나 받는 단변수 함수를 인자로 사용하더라도 해당 단변수 함수의 매개변수가 숫자가 아닌 값을 대상으로 할 경우 역시 오류가 발생한다.

위에서 오류가 발생하는 이유는 (lambda s: len(s))(1)를 호출하다 보면 len(1)를 실행해야 하는 데 len 함수는 문자열의 길이를 반환하는 함수이며, 숫자 1은 문자열이 아니기 때문에 자료형오류(TypeError)가 발생하기 때문이다.

람다 함수의 이름 지정

람다 함수를 변수에 저장할 수도 있지만 그럴바엔 애초부터 def 키워드를 사용해서 이름을 지정하는 것이 바람직하다.

매개변수와 인자

함수를 선언할 때 입력받을 인자들을 저장하는 역할을 수행하는 변수를 매개변수(parameter)라 한다. 즉, 매개변수는 함수의 본체로 들어오는 값들의 입구들의 이름 역할을 수행한다. 반면에 인자(argument, 아규먼트)는 함수를 호출할 때 해당 함수의 매개변수를 통해 함수 본체에 전달되는 값을 가리킨다. 즉, 매개변수는 일종의 변수이고, 인자는 매개변수에 저장될 구체적인 값을 가리킨다.

앞서 설명한 제1종 객체가 함수의 인자로 사용될 수 있으며, 여기에 함수 자료형 자체도 포함된다.

키워드 인자(keyword argument)와 기본값

함수의 매개변수에 기본값을 지정할 수 있으며, 그런 인자를 키워드 인자라 부른다. 이렇게 하면 특정 매개변수에 대한 인자를 지정하지 않은 채 함수를 호출할 수 있으며, 그럴 경우 기본값으로 지정된 키워드 인자가 해당 매개변수의 인자로 사용된다.

다음 my_print 함수의 둘째 매개변수 message의 키워드 인자는 "hello!" 이다.

주의:

함수를 호출할 때 매개변수 이름을 함께 사용해도 된다.

문자열 자료형

문자열은 말 그래도 문자들을 나열해 놓은 것이며 아무런 의미를 갖지 않는다. 즉, 파이썬은 문자열을 보면 아무런 해석을 하지 않으며 그냥 명령에 따라 주어진 문자열을 조작한다. 물론 이런 문자열들을 잘 조작하여 필요한 정보를 얻어내는 것이 데이터 분석의 기본 목표이다.

문자열은 작은 따옴표(') 또는 큰 따옴표(")로 감싸져야 한다. 다만 앞 뒤로 동일한 종류의 따옴표가 사용되어야 한다.

두 변수가 동일한 값을 저장하고 있다는 것을 확인할 수 있다.

주의: 위에서 사용된 기호 ==는 양측의 값이 동일함을 판단하는 함수이다. 즉, 양측의 (변수에 저장된) 값이 동일하면 참(True)을, 다르면 거짓(False)를 반환하는 함수이다.

특수 문자

파이썬에서 백슬래시(\)는 특별한 역할을 수행한다. 예를 들어 \t는 탭을 가리킨다. 여기서 탭은 탭 키를 눌렀을 경우 커서(cursor)가 지정된 크기만큼 움직이도록 하는 것을 가리킨다.

주의: 탭은 보통 스페이스 두 칸 또는 네 칸을 가리킨다. 언어마다 조금 다를 수 있다.

즉, 탭은 여기서는 스페이스 두 칸에 해당함을 알 수 있다.

백슬래시 자체를 문자열에 포함하고 싶을 때는 무가공 문자열(raw string, 로 스트링)이란 의미로 r 기호을 문자열 앞에 붙혀서 사용한다. 그러면 백슬래시의 특수성이 무시되면 하나의 문자로 인식된다.

여러 줄로 구성된 문자열

문자열을 여러 줄에 걸쳐서 작성하고 싶으면 세 개의 큰 따옴표(""")를 앞뒤로 감싼다.

파이썬 해석기에 내부에서는 사실 \n 이라는 특수 문자열이 추가되어 하나의 문자열로 저장된다. 여기서 \n 은 뉴 라인(new line, 줄바꿈)을 가리키는 특수 문자열이다. 역시 여기서도 백슬래시의 특수 기능이 활용된다.

포맷 문자열(format string)

문자열 내에 지정된 값을 삽입하여 보다 유연한 문자열을 생성할 수 있도록 도와주는 문자열을 포맷 문자열이라 부르며, 값을 인자로 입력받아 새로운 문자열을 생성하는 일종의 틀의 역할을 수행한다.

예를 들어, 성과 이름이 각각 last_namefirst_name 변수에 저장되어 있다.

그러면 다음과 같이 문자열 덧셈을 이용하여 '홍 길동'을 생성할 수 있다.

또한 포맷 문자열을 이용하여 좀 더 유연하게 문자열을 다룰 수 있다.

f-문자열(f-string)

하지만 파이썬 최신 버젼부터는 f-문자열이 제공되며 편리성이 보다 높으며, 이 강의에서는 f-만자열을 선호해서 사용할 것이다.

리스트 자료형

파이썬에서 제공하는 자료형 중에서 가장 기본적인 자료형이다. 리스트는 여러 개의 값을 하나의 모둠(collection)으로 묶는다. 또한 리스트에 포함된 값들 사이의 순서가 있으며, 순서는 인덱스(index)로 지정된다.

주의: 인덱스는 0번 부터 시작하며, 0, 1, 2, 3, ... 등으로 리스트 왼편에 위치한 항목부터 인덱스를 센다.

리스트 항목은 아무 자료형이나 섞어서 사용될 수 있다.

동일 자료형 리스트

섞인 자료형 리스트

중첩 리스트

리스트가 다른 리스트의 항목으로 사용될 수 있으며, 중첩 정도에 아무런 제한이 없다.

주의: []는 아무런 항목이 없는 공리스트(empty list)를 가리킨다.

리스를 활용하는 많은 도구들이 있다.

리스트 길이

len 함수는 리스트의 길이를 반환한다.

리스트 항목들의 덧셈

리스트 항목이 모두 숫자일 경우 모든 항목을 한꺼번에 더한 결과를 구할 수 있다.

인덱싱

리스트의 특정 인덱스에 위치한 값을 확인하거나 수정할 수 있으며, 이를 인덱싱이라 부른다. 기호는 대괄호([])를 사용한다.

주의:

슬라이싱(slicing)

슬라이싱은 두 인덱스 사이의 항목을 선택하여 활용할 때 사용된다.

0번부터 2번 인덱스 항목 선택, 즉, 왼편 끝 첫 3개 항목 선택

3번 부터 끝까지 모두 선택

1번부터 4번 항목까지 선택

오른쪽 끝에서 3번째 항목부터 모두 선택, 즉, 오른쪽 끝 3개 항목 선택

양끝 항목 제외한 나머지 선택

전체를 선택하여 다른 변수에 저장

슬라이싱과 스텝(step)

스텝인자를 추가로 사용하면 몇 개마다 하나씩 선택할 수 있다.

예를 들어, 2번부터 오른쪽 끝 마지막 원소 전까지 3개씩 건너뛰며 항목 선택하려면 다음과 같이 한다. 즉, 2번, 5번, 8번 인덱스 항목만 선택된다.

역순 슬라이싱도 가능하다. 스텝을 음수로 두면 된다. 아래 코드는 8번, 5번 인덱스 항목을 선택한다.

주의: 2번 인덱스 항목은 선택하지 않는다. 역순으로 2번 인덱스 이전 인덱스인 3번 인덱스까지만 해당되기 때문이다.

인(in) 연산자

in은 항목의 포함여부를 판단해 주는 연산자이다. 반환값은 True 또는 False이다.

주의: TrueFalse는 부울(bool) 자료형에 속하는 값들이다.

익스텐드(extend) 메소드

익스텐드(extend)는 기존 리스트에 새로운 리스트를 이어붙이도록 해주는 함수이다. 다만 리스트 자료형과만 함께 사용할 수 있으며, 이와 같이 특정 자료형에만 적용할 수 있는 함수를 메소드(method)라 부른다.

extend의 경우 리스트 자료형에만 사용하며, 따라서 리스트 메소드라 부른다.

주의: extend 메소드는 기존 리스트를 변형시킨다. 따라서 기존의 리스트를 건드리지 않으면서 새로운 리스트가 이어진 리스트를 생성하려면 리스트 덧셈 연산자를 활용해야 한다.

어펜드(append) 메소드

어펜드(append)는 기존 리스트에 새로운 항목을 하나씩 추가할 수 있도록 해주는 함수이다. extend처럼 append도 리스트 자료형과만 함께 사용할 수 리스트 메소드이다.

주의:

리스트 해체

리스트의 길이를 정확히 알고 있는 경우 각각의 항목을 따로따로 떼어내어 변수에 저장할 수 있다.

주의: 리스트의 길이와 변수의 개수가 다르면 오류가 발생한다.

리스트를 해체하면서 앞으로 사용하지 않고 버릴 항목은 굳이 이름을 주지 않아도 된다. 이를 위해 밑줄(underscore, 언더스코어) 기호를 사용한다.

튜플(tuple) 자료형

튜를 자료형은 리스트와 거의 같다. 다만 튜플 자료형은 한 번 생성되면 수정이 불가능하다. 즉, 앞서 리스트 인덱싱을 통해 기존 리스트의 항목을 수정할 수 있었지만 튜플의 경의 인덱싱을 통해 튜플의 항목을 확인하고 읽을 수만 있어서 수정은 불가능하다. 수정불가능성을 제외하고는 리스트와 기본적으로 동일하게 작동한다.

리스트 자료형을 나타내는 기호는 소괄호 '()'를 사용한다.

수정 가능성

리스트는 인덱싱을 통해 특정 인덱스의 항목 수정이 가능하다.

반면에 튜플의 경우 수정을 시도하면 오류가 발생한다.

인덱싱을 통해 항목을 확인하여 활용할 수는 있다.

소괄호 없이 쉼표(comma, 콤마)를 이용하여 항목을 나열해도 튜플로 인식된다.

함수 반환값과 튜플 해체

함수는 실행과정에서 하나의 값만 반환할 수 있다. 하지만 튜플을 사용하면 여러 개의 값을 동시에 반환할 수 있다.

변수 다중 할당

여러 개의 변수에 동시에 값을 할당하며 변수를 선언할 수 있다.

두 개 이상의 변수에 할당된 값들을 아래와 같이 교환할 수 있다.

주의: 위 교환방식은 파이썬과 최신 버전의 Javascript에서는 지원되지만 예를 들어 C, Java 에서는 지원되지 않는다.