[코테][Python] 파이썬 문법 정리 1편

wns20826·2022년 1월 10일
4

파이썬

목록 보기
1/2
post-thumbnail

_여수 케이블카

 

💻💻💻

 

  코딩 공부를 계속 하고 있는데, 공부하는 내용을 블로그에 정리해보려 합니다. 그 첫 걸음으로, 오늘은 제가 직접 보기위해 파이썬 문법 정리하는 글을 올리고자 합니다. 너무 길어지면 추가로 게시글을 올릴 수도 있고, 내용이 추가되거나 수정될 수 있습니다.

  주로 실질적으로 코딩에서 사용되는 문법 위주로 정리를 하려 하니, 두서가 없을 수 있습니다. 혹시 틀린 부분이 있거나 알려주고 싶은 꿀팁이 있으시면 댓글로 알려주세요.

  최근엔 나동빈 님의 '이것이 취업을 위한 코딩 테스트다 with 파이썬' 이라는 책으로 공부를 하고 있는데, 앞으로의 코딩 공부 게시글은 주로 이 책을 참고하여 작성하게 될 것 같습니다.


1. 자료형

파이썬에서는 변수에 값을 넣어주면, 자동으로 자료형이 결정됩니다. C 언어에서 처럼 변수의 자료형을 처음에 선정해주지 않아도 됩니다.

- 무한대 값 설정

  최단 경로 문제에서, 도달할 수 없는 노드에 대하여 최단거리를 무한(INF)로 설정하곤 합니다. 경로 값이 10억 미만의 범위로 항상 존재할 때, 무한(INF)을 표현할 때 10억을 이용할 수 있습니다.

a = 1e9
print(a)
1000000000.0

- round( ) 함수로 소수점 반올림하기

  round( )합수의 첫 번째 인자는 실수형 데이터이고, 두 번째 인자는 '반올림하고자 하는 위치 -1'입니다. round(0.346, 2) 라고 작성하면 결과는 0.35가 됩니다. 두 번째 인자 없이 round( ) 함수를 호출하면 결과는 소수점 첫째 자리에서 반올림됩니다.

print(round(32.1461,3))
print(round(32.1461))
32.146
32

- 수 자료형의 연산 - 나눗셈 관련 헷갈리는 연산자들

  나눗셈 관련 다양한 연산자들이 있는데, 은근히 다양하게 응용할 수 있으나 헷갈리는 경우가 많습니다. 먼저 가장 기본적인 나누기 연산자(/)는 파이썬에서 결과를 실수형으로 반환합니다. 나머지 연산자(%)는 나눗셈의 결과에서 몫 이외의 나머지 값을 반환하고, 코딩 테스트에서 자주 사용됩니다. 나눈 결과에서 몫 값을 얻으려면 몫 연산자(//)를 사용합니다.
추가로 거듭제곱 연산자(**)를 사용하면 x**y의 결과는 x의 y제곱 값과 같은 결과를 냅니다.

a = 5
b = 3
print(a/b)
print(a//b)
print(a%b)
print(a**b)
1.6666666666666667
1
2
125

 

2. 리스트 자료형 👨‍👩‍👧‍👦

리스트는 여러 개의 변수들을 연속적으로 담아 처리할 수 있습니다. 파이썬의 리스트 자료형은 내부적으로 배열(Array)를 채택하고, 연결 리스트 자료구조 기능을 포함하고 있어서 append( ), remove( ) 등의 메소드를 지원합니다.

- 리스트 만들기

  비어 있는 리스트를 선언하고자 할 때는 list( ) 혹은 간단히 대괄호( [ ] )를 이용하면 됩니다. 대괄호( [ ] ) 안에 원소를 넣어 초기화 할 수 있고, 쉼표(,)로 원소를 구분합니다.

  리스트를 지칭하는 변수의 뒤에서 원하는 원소의 인덱스(index)를 대괄호 속에 이어 붙여, 원하는 원소의 값에 접근할 수 있습니다. 리스트의 맨 첫 번째 원소는 인덱스가 0번 째 입니다. 예를 들어, a[2]의 경우, a라는 리스트의 세 번째 원소를 지칭합니다.

a = [1, 2, 3, 4, 5]
print(a)

print(a[3])

b = list()
c = []
print(b)
print(c)
[1, 2, 3, 4, 5]
4
[]
[]

- 크기가 N인 리스트 생성

  코딩 문제를 풀 때, 크기가 N인 1차원 리스트를 초기화 할 때, 다음 방식으로 편리하게 진행할 수 있다.

n = 5
a = [0] * n
print(a)
[0, 0, 0, 0, 0]

- 리스트의 인덱싱과 슬라이싱

  인덱스 값을 이용하여 해당 자리의 원소 값에 접근하는 것을 인덱싱이라고 한다. 인덱스는 양의 정수와 음의 정수를 전부 사용할 수 있다. 인덱싱을 할 때 양의 정수는, '리스트의 크기-1' 까지 사용할 수 있고, 음의 정수를 넣으면 원소를 거꾸로 탐색하게 된다. 예를 들어 인덱스에 -1을 넣으면 가장 마지막 원소가 출력된다. 리스트의 크기를 모르거나 크기가 변할 때, 마지막 원소나 뒤에서 n 번째 원소 등에 접근할 때 유용하다.

  인덱싱을 하여 해당 인덱스의 위치에 접근한 후, 리스트의 값을 변경할 수 있다. 이와 대조되어 튜플(tuple)이라는 자료형은 인덱싱을 통한 원소 값 변경이 불가능하다는 특징이 있다.

a = [3, 5, 7, 9, 11]

print(a[-1])
print(a[-2])

a[3] = 1
print(a)
11
9
[3, 5, 7, 1, 11]
a = [1, 3, 5]
print(a[3]) 
# 원소가 0, 1, 2번 째 인덱스위치밖에 없는데, 
# 3 이상의 양의 정수를 입력 시 오류가 발생한다.
IndexError: list index out of range

  리스트에서 연속적인 위치를 갖는 원소들을 가져와야 할 때는 슬라이싱(slicing)을 이용할 수 있다. 이때는 대괄호 안에 콜론(:)을 넣어서 시작 인덱스와 끝 인덱스를 설정할 수 있다. 콜론의 왼쪽에 값을 입력 시, 해당 인덱스의 원소부터 시작된다. 값을 입력하지 않으면, 0번 째 원소부터 시작되다. 콜론의 오른쪽에 값을 입력 시, 해당 인덱스로 지칭되는 원소의 직전까지 범위를 잡게 된다.

  예를 들어, a = [1, 2, 3, 4, 5] 라는 리스트에 대해 a[1:3]는 인덱스가 1인 원소부터 3인 원소 직전까지인 인덱스가 2인 원소까지를 범위로 잡겠다는 의미이다. 추가로, 슬라이싱 할 때 두 번째 입력값에는 리스트의 크기 이상의 양의 정수를 넣으면 범위를 그냥 끝까지로 잡게 된다.

  슬라이싱 시 콜론을 두 개를 써서, 세 번째 입력값을 설정할 수 있다. 이는 범위 내에서 원소를 뽑아낼 간격을 의미하며, 설정하지 않으면 기본적으로 1을 의미해서 범위 내의 원소들을 연속적으로 가져온다.

a = [1, 3, 5, 7, 9, 11, 13]
print(a)
print(a[:])
print(a[:3])
print(a[3:])
print(a[3:6])
print(a[:10])
print(a[-4:-1])
print(a[::2])
[1, 3, 5, 7, 9, 11, 13]  # print(a)
[1, 3, 5, 7, 9, 11, 13]  # print(a[:])
[1, 3, 5]                # print(a[:3])
[7, 9, 11, 13]           # print(a[3:])
[7, 9, 11]               # print(a[3:6])
[1, 3, 5, 7, 9, 11, 13]  # print(a[:10])
[7, 9, 11]               # print(a[-4:-1])
[1, 5, 9, 13]            # print(a[::2])

- 리스트 컴프리헨션

  리스트 컴프리헨션은 대괄호 내에서 조건문과 반복문을 사용하여 리스트를 초기화하는 방법이다. 원소가 될 계산식으로 대괄호 안을 시작하고, for 구절을 적어준다. 원하는 변수로 조건을 주고 싶으면 이후 if 문을 추가하여 설정해줄 수 있다. 일반적인 for문이나 if문으로 작성하는 것보다 간결하게 코드를 작성할 수 있다.

# 0부터 19까지의 수 중에서 홀수만 포함하는 리스트
a = [i for i in range(20) if i % 2 == 1]
print(a)

# 1부터 9까지의 수의 제곱 값을 포함하는 리스트.
b = [ i * i for i in range(1, 10)] 
# range(k)는 0부터 k-1까지, range(k,l)은 k부터 l-1까지의 자연수 리스트이다.
print(b)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
[1, 4, 9, 16, 25, 36, 49, 64, 81]

  리스트 컴프리헨션은 2차원 리스트를 초기화 할 때 매우 효과적이다. N x M 크기의 이차원 리스트를 초기화 할 때 리스트 컴프리 헨션을 사용하지 않고 아래 두 번째 방법으로 리스트에 정수를 곱해 진행한다면, 내부적인 문제가 발생한다. 2차원 리스트에서 인덱싱을 이용해 값을 변경 시 내부적으로 동일한 주소로 인식하여, 여러 개의 값이 바뀌는 문제가 생길 수 있다. 따라서, 정해진 크기의 2차원 리스트의 초기화에는 리스트 컴프리헨션을 기억하여 사용하자.

#리스트 컴프리헨션 사용
n = 3
m = 4
a = [ [0] * m for _ in range(n) ]
print(a)

a[1][1] = 5
print(a)
print() # 빈 줄 출력

#잘못된 방법으로 2차원 리스트 초기화
b = [ [0] * m] * n
print(b)

b[1][1] = 5
print(b)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 0, 0, 0], [0, 5, 0, 0], [0, 0, 0, 0]]

[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[0, 5, 0, 0], [0, 5, 0, 0], [0, 5, 0, 0]] 
# 동시에 여러 원소의 값이 변경되는 문제 발생

- 리스트 관련 기타 메서드

  다음은 리스트 관련 주요 메서드이다.

메서드명사용법설명시간 복잡도
append( )변수명.append( )리스트의 마지막에 원소 하나를 삽입O(1)
sort( )변수명.sort( )기본 정렬 기능으로, 오름차순으로 정렬O(NlogN)
sort( )변수명.sort(reverse=True)내림차순으로 정렬O(NlogN)
reverse( )변수명.reverse( )리스트의 원소의 순서를 모두 뒤집어 놓음O(N)
insert( )변수명.insert(삽입할 위치 인덱스, 삽입할 값)특정한 인덱스 위치에 원소를 삽입할 때 사용O(N)
count( )변수명.(특정 값)리스트에서 특정한값을 가지는 데이터의 개수를 셀 때 사용O(N)
remove( )변수명.(특정 값)특정한 값을 갖는 원소를 제거하는데, 값을 가진 원소가 여러 개면 가장 앞의 인덱스의 원소만 제거O(N)

  이 중에서 insert(), append(), 그리고 remove() 함수를 더 살펴보자. 원소의 개수가 N인 리스트에 대해 insert() 메소드를 사용하면 시간 복잡도가 O(N)이다. append() 메소드가 O(1)인 것에 비해 시간이 더 걸린다는 것인데, 코드를 작성할 때, insert() 함수를 많이 사용하면 제한 시간이 있는 경우 문제가 생길 수 있다. remove() 함수도 마찬가지로 사용에 주의하여야 한다. remove() 함수는 특정 원소가 여러개 존재할 경우 앞 쪽의 한 개만 지워지게 되는데, 원하는 원소를 전부 지우고 싶을 때는 다음의 방법을 이용하면 가능하다.

a = [1, 2, 3, 4, 5, 5, 5]
remove_set = {3, 5}

result = [ i for i in a  if i not in remove_set ]
print(result)
[1, 2, 4]
profile
딥러닝을 학습하는 중

8개의 댓글

comment-user-thumbnail
2022년 1월 10일

파이썬이라고는 스타크래프트 밖에 몰랐던 제가 이 글을 읽고 파이썬에 눈을 떴어요! 감사합니다!!

1개의 답글
comment-user-thumbnail
2022년 1월 10일

혹시 코딩테스트 백준으로 준비하시나요!?

3개의 답글
comment-user-thumbnail
2022년 1월 10일

사진이 멋지네요^^ 잘 보고 갑니다.

1개의 답글