본문 바로가기
Always Awake/python 기본 정리(19.12.23~20.01.12)

20.01.09 정리

by 욕심많은알파카 2020. 1. 9.

1. 리스트로 스택과 큐 만들기

 

스택 : 후입선출구조 (선입후출구조)

큐 : 선입선출구조 

 

append()와 pop()이 리스트 끝부분에 요소를 추가시키고 삭제하므로 이를 통해 간단한 스택구조를 만들수 있음.

큐의 경우는 좀더 효율적인 사용을 위해서 deque(double ended queue) 자료형을 제공한다. 덱은 양쪽 끝에서 추가/삭제가 가능한 구조. 사용 방법은 from collections import deque로…

deque 자료형의 경우는 appendleft() 메서드와 popleft() 메서드를 제공한다. 따라서 append와 popleft의 조합, appendleft와 pop의 조합을 이용하여 양쪽방향으로 큐를 활용할 수 있다.

 

2. sort 함수와 sorted 함수의 차이

 

sort()와 sorted() 두 함수 모두 리스트를 정렬할 수 있는 함수이다.

이 두 함수의 차이점은

 

sort : 리스트의 요소들을 정렬한 채로 저장한다. 즉, 사용한 리스트의 요소 순서가 바뀐다. 반환값은 None

sorted : 리스트의 요소들을 정렬한 새로운 객체를 반환해준다. 그러나 함수를 호출한 리스트 요소의 원래 순서는 바뀌지 않는다.

 

3. 리스트의 할당과 복사

a = [1,2,3,4,5]
b = a

 

위와 같이 [1,2,3,4,5]객체를 변수 a에 할당하고, 변수 a를 다시 b에 할당했다고 하자.

이때 b는 a가 가리키는 [1,2,3,4,5]를 복사해온 객체를 담은 변수가 아니다.

파이썬의 변수 할당은 하나의 객체를 여러개의 변수가 가리킬 수 있게 되어있다.

즉, a와 b는 모두 [1,2,3,4,5]라는 하나의 객체를 가리키고 있는 변수이다.

 

그렇다면 b가 a와 같은 객체를 가리키도록 하지 않으면서 [1,2,3,4,5]를 복사한 새 객체를 가리키도록 하는 방법은 무엇일까?

 

b = a.copy()

 

위와 같이 a를 복사한 새 객체를 반환하는 copy메서드를 사용하여 할당하면 된다.

 

만약 2차원 이상의 다차원 리스트를 사용하고 있다면, copy메서드만으로 리스트의 복사가 불가능하다.(copy해서 할당해도, 내부의 리스트는 똑같은 객체를 할당받게된다)

이때는 copy모듈에 있는 deepcopy메서드를 사용하면 다차원 리스트를 복사한 새 객체를 할당받을 수 있다.

 

import copy
b = copy.deepcopy(a)

 

이처럼 다차원 리스트를 복사하는 데에 얕은 복사(shallow copy, 여기서는 copy메서드를 사용한 카피)가 불가능한 이유는,

일반적인 copy메서드가 리스트 내부의 리스트까지 완전히 복사해오지는 않기 때문이다.

즉, 바깥쪽의 리스트만 새 객체로 바꿀 뿐이지 내부의 리스트는 원래의 바깥리스트 객체 내부에 있던 그 리스트 객체라는 것.

참조(https://blueshw.github.io/2016/01/20/shallow-copy-deep-copy/)

 

이렇게 되는 이유는 본질적으로 리스트 객체가 python에서 mutable 객체이기 때문이다. 

immutable객체는 객체 내부를 조작하여 수정할 수 없어 수정하려 한다면 새로운 객체로 대체해야한다. 

그러나 mutable객체는 내부의 조작이 가능하고, 따라서 굳이 내부의 객체를 똑같은 새 객체로 바꾸라고 요구(명시)하지않는 이상 바꿀 필요가 없다.

그래서 shallow copy시에 바꾸라고 명시된 외부의 리스트객체만 새로 만들어내고, 내부의 객체는 바꾸지 않는 것이다.

이러한 현상을 막기 위해 deepcopy메서드는 명시적으로 복합 객체 내의 모든 객체들을 새로 만들어 복사하라고 요구한다.

참조(https://webnautes.tistory.com/1181)

 

#python 특성에 deepcopy와 shallowcopy에 대해 따로 정리해놓겠다.

 

 

 

4.  리스트 컴프리헨션(list comprehension)

 

식을 이용하여 얻은 값들을 리스트로 잡아두는 것.

 

#리스트 컴프리헨션 예시
LCTest = [i*j for i in range(100) if i%10 == 5 for j in range(100) if i%10 == 3]

 

이 때 여러 개의 for문 중 뒤의 것부터 먼저 처리한다.

 

 

5. translate를 이용하여 문자열의 특정 문자 치환하기

 

maketrans와 translate를 사용하면 평문을 암호문으로 바꾸듯이 문자열 내의 문자 하나하나를 치환할 수 있다.

 

table = str.maketrans(‘aeiou’, ‘12345’)
print('always awake'.translate(table))
#결과
1lw1ys 1w1k2

 

table을 출력해보면 maketrans에서 두 문자열을 받아 전자를 키, 후자를 value값으로 하는 딕셔너리를 만드는 것을 볼 수 있다.

특히, 문자같은 경우에는 아스키코드로 저장된다.

translate는 이러한 딕셔너리(해쉬테이블)을 받아 바꿀 문자열 내의 문자 중 테이블 내에 존재하는 키와 동일한 문자가 있으면 value값으로 치환해준다.

 

 

6. find 함수와 index 함수의 차이

 

문자열 함수 중에서 특정 문자열의 위치인덱스를 찾아주는 함수는 find와 index가 있다.

find와 rfind, index와 rindex의 역할은 거의 동일하다.

이 두 함수의 차이점은 미발견시의 반환여부이다.

 

특정 문자열을 찾는 데에 실패할 경우 (해당 문자열에 찾는 문자열이 없을 경우)

 

find(),rfind() : -1 반환

index(), rindex() : 오류 발생

 

따라서 찾을 문자열이 해당 문자열에 반드시 존재하는 경우에는 index를 사용하여 확실하게 찾고,

존재하지 않아도 다음 코드가 실행되어야 한다면 find를 사용하여 반환시키는 것이 좋을 듯하다.

 

7. 딕셔너리에서 특정 '값'이 있는 키값쌍 삭제하기

 

딕셔너리에서 특정 값을 가진 키값쌍들을 골라내어 삭제하고싶다면 어떻게 해야할까?

딕셔너리 표현식을 이용해 해당 값을 가진 키값쌍을 제외한 다른 키값쌍들만 모아 새로 딕셔너리를 재할당하면 된다.

 

x={‘a’:1, ‘b’:2, ‘c’:3, ‘d’:4}

#x에서 값이 3인 키값쌍을 삭제하기
x={ key : value for key, value in x.items() if x[key] != 3}

 

마치 카톡 단톡방에서 누군가를 제외하고 싶다면 단톡방 내에서 그 사람이 아닌 구성원들을 가진 단톡방을 새로 파는것과 느낌이 비슷하다.(….)

 

딕셔너리에는 키값쌍을 없애는 pop함수 등도 있는데 왜 이렇게 해야할까?

이유는 딕셔너리에서 키값 없이는 특정 쌍을 삭제할 수 있는 방법이 없기 때문이다. del, pop등의 함수 모두 키값쌍을 삭제하려면 키가 필요하다.

그러나 키가 아니라 값만 아는 경우에는 키값쌍을 한번에 불러와 그중에 해당하는 값을 가진 녀석을 제외하고 새로 재할당하는 이런 편법을 사용해야 한다.

 

 

8. 프레임의 개념

 

프레임 :  메모리에서 함수와 함수에 속한 변수가 저장되는 독립적인 공간

 

전역 프레임은 파이썬 스크립트 전체에서 접근 가능하며 쭉 유지된다.

스택 프레임은 해당 함수 내에서 사용되는 변수들이 저장되는 공간으로, 함수 호출이 끝나면 사라진다.

 

#프레임의 개념에 대해서는 파이썬 특성에 나중에 다시 정리

 

9. 언패킹(unpacking)의 개념

 

인수를 순서대로 넣을때 리스트나 튜플을 사용하여 한번에 넣을수도 있다.

 

x=[10,20,30]
print_numbers(*x)

 

위와 같은 방식으로 프린트함수의 인자에 x의 인덱스를 하나하나 지정해주는게 아니라 *x를 사용하여 리스트x의 내용물을 풀어 하나하나씩 인자로 넣을 수 있다.

단, 이때 함수의 매개변수 개수와 리스트의 요소 개수가 같아야한다. 개수가 다르면 에러가 난다.

 

함수를 만들 때 인자의 개수가 가변적으로 변하게 만들고 싶다*args를 사용하는 이유도 그때문이다.

인자에 *args를 넣는다는 것은 args라는 이름의 리스트(또는 튜플)을 받는다는것과 같다.

리스트(또는 튜플)의 내부 요소 개수는 정해져있지 않으므로, 사실상 정해져있지 않은 n개의 인자를 받는다는 것과 같은 의미이다.

 

그런데 만약 고정 인수(개수가 정해져있는 인수)와 가변 인수를 한 함수에서 동시에 매개변수로 받고싶을때에는,

고정 매개변수를 먼저 지정한 후 가변 매개변수를 지정해놓으면 된다.

피로그래밍 수업 파이썬 부분 참조.

 

 

# 리스트/튜플 언패킹에 대해서는 파이썬 특성으로 나중에 정리.

 

 

12. 키워드 인수

 

파이썬에서 함수를 호출할 때 인수의 순서와 용도를 매번 기억하지 않아도 되도록 인수의 키워드를 활용할 수 있다.

함수를 만들 때 매개변수에 붙여진 이름을 키워드로 삼는다.

나중에 함수를 호출할 때 키워드=값 형식으로 키워드에 따른 값을 지정하여 전달할 수 있다.

이 때, 매개변수의 이름(키워드)에 용도를 적어놓으면 호출하면서 인수의 용도를 잊어버릴 일이 없다.

또한, 함수 호출 시 인수를 집어넣는 순서가 바뀌어도 키워드를 이용하여 정확히 지정하여 전달할 수 있기 때문에, 인수 전달 순서를 기억하지 않아도 된다.

 

 

13. 딕셔너리 언패킹

 

인수에 키워드를 지정하여 값을 넣는 방식과, 리스트(튜플)의 언패킹 방식이 합쳐진 느낌으로

딕셔너리의 경우 여러 매개변수에 값(value)들을 한번에 집어넣을 수 있다.

 

이 때 조건은,

 

1. 딕셔너리의 키가 반드시 문자열 형태여야 한다.

2. 딕셔너리의 키들과 함수 매개변수의 키워드가 각각 같아야 한다.

3. 매개변수 개수와 딕셔너리 키 개수도 같아야한다.

 

딕셔너리 언패킹을 이용해 매개변수를 받을때는 **x처럼 asterisk를 두번 사용하는데, 이유는 *한번으로는 딕셔너리의 키모음밖에 반환하지 못하기 때문이다. 따라서 *한번으로 딕셔너리의 키에 접근하고, 그 키에서 다시 *를 이용하여 값에 접근한다는 뜻으로 생각하면 된다.

 

# 딕셔너리 언패킹에 대해서는 나중에 파이썬 특성에 정리.

 

 

 

14. 람다(lambda)의 사용법

 

익명함수(anonymous function) 람다는 그 자체로는 그냥 함수에 불과하기 때문에 이름을 지정해서 사용하는것이 편하다.

람다의 선언과 사용 형식은 다음과 같다.

함수명 = lambda 매개변수 : 표현식

 

이때, 람다의 뒤에 매개변수는 없어도 되지만, 표현식부분에 최소한 리턴할 값은 반드시 지정되어있어야한다.

만약 이런식으로 함수명을 정하지 않고 람다를 바로 쓰고 싶을경우, 일반적으로 함수를 쓰는 방식의 함수명부분에 (람다식)을 집어넣으면 된다.

(lambda 매개변수 : 람다식)(전달할 인자)

 

이때 주의할 점은 람다식 내에서 변수를 선언할 수는 없다는 것이다. 변수를 선언하려면 람다가 아니라 함수를 사용해야 한다.

 

람다표현식의 이점은 다른 함수의 인수로 넣기가 편리하다는 데에 있다.

특정 함수의 인수를 넣을 인수를 어떤 함수식으로 가공하여 넣고 싶다면 해당 인수부분에 람다식을 넣으면 코드를 줄이는 도움이 된다.

 

 

----------------------------------------------------------

파이썬 코딩도장(https://dojang.io/course/view.php?id=7)을 참조했습니다.

 

'Always Awake > python 기본 정리(19.12.23~20.01.12)' 카테고리의 다른 글

20.01.12 기록  (0) 2020.01.13
20.01.06 정리  (0) 2020.01.07
20.01.05 기록  (0) 2020.01.06
19.12.26 기록  (0) 2019.12.27
19.12.25 기록  (0) 2019.12.26

댓글