Python - list, tuple, dictionary, set (컨테이너), Numpy
▶▶
>>> 리스트는 대괄호 "[ ]"로 가변(C배열도 []를 쓰고 가변이지.), // 행렬로 쓰임
>>> 튜플은 괄호"( )"로 고정("고정"의 o 생각해),
>>> 딕셔너리는 중괄호"{ : }"로 짝지어져.. (중괄호와 콜론 ":")
// 파이썬에서 가변성은(mutable) 불가변(고정)은 immutable로 칭함.
>>>> 세트(집합)은 중괄호이지만 키만으로 이루어져서 콜론( : )이 없음.
<-- 리스트, 튜플, 딕셔너리, 세트등을 컨테이너라고 호칭함
list1 = [1,2,3,4] <- list
tuple1 = (1,2,3,4) <- tuple , 또는 tuple1 = 1,2,3,4 도 동일. (괄호 없이 튜플가능. 함수의 return 에서 다수 값을 돌려줄때 등)
dict1 = { key1: value1, key2:value2 } <- dictionary (일명 hash, associated array)
set1 = {key1, key2, key3 }
그리고 문자열도 수정불가능하다. (const char[]로 생각하면 됨)
list : 수정 가능... 즉 C 배열로 생각하면 됨. C배열도 "[ ]"를 쓰지~
tuple : 수정 불가능. 튜플은 괄호"( )"를 씀.
>> 시도시 이런 에러//
>> TypeError: 'tuple' object does not support item assignment
주의. a = (1)의 의미는??? 정수 1이 할당됨. --> type(a)를 해보면 int로 나옴
Q. 요소가 한개인 tuple을 설정하는 방법은?
A. 끝에 ","를 넣는 것
예) a = (1) // 정수 1을 a에 할당 -- type(a) --> <type 'int'>
b = (1,) // 정수 1을 요소로 가진 튜플을 b에 할당 -- type(b) --> <type 'tuple'>
▶▶자료형을 아는 방법 : type 함수
>>> t1 = (1)
>>> t2 = (1,)
>>> type(t1)
<type 'int'>
>>> type(t2)
<type 'tuple'>
▶▶ 각각의 리스트의 셰이프를 아는방법 :
--- 일반 리스트에는 없음 - numpy를 사용해야 함. ( numpy.ndarry.shape )
예)
>>> a=numpy.array([[1,2],[3,4], [5,6]])
>>> a.shape
(3, 2) <--- 안쪽부터 [1,2]로 2개, 바깥쪽 [[ ], [ ] , [ ]]로 3개
>>> a.ndim <--- 2 : 몇차 배열인가 (numpy의 attribute)
>>> type(a)
numpy.ndarry <-- 그냥 리스트가 아님!
>>> a[0]
array([1,2])
>>> len(a) --> 3
>>> len(a[0]) --> 2
>>> type(a[0]) ---> numpy.ndarry
>>> type(a[0][0]) --> numpy.int32
>>> 만약 일반 리스트라면?
>>> b = [[11,12],[13,14], [15,16]]
>>> b.shape // 지원되지 않음
>>> type(b) --> list
>>> len(b) --> 4
>>> b[0] --> [11,12]
>>> type(b[0]) --> list
>>> len(b[0]) --> 2 // 엘리먼트가 2개 (정수 2개라서가 아님, 실수2개라도 역시 len은 2)
>>> type(b[0][0]) --> int32
>>> len(b[0][0]) // 에러! (int형에 len은 안됨)
▶▶ 슬라이스 (start:end:step)
-- 모든 index는 0부터 시작한다. 인덱스가 마이너스이면 뒤쪽끝에서부터 계산한다.
-- step을 마이너스 값으로 주면 거꾸로 읽어오는 등의 조작도 가능하다!! (예 7:5:-1 <-- 7부터 5까지 -1씩해가면서... 즉 7,6번째 값~)
▶▶ 리스트의 조작
- append(), extend(), insert() : append()는 끝에 추가, extend()는 다른 리스트를 병합, insert()는 중간에 넣기.
- del, remove(), pop() : 삭제는 del 구문(함수가 아닌 구문), remove() 함수, pop()은 항목을 가져오면서 삭제
- index() : 값으로 항목의 offset을 찾기.
- in : 존재여부를 확인하는 구문
- count() : 특정값이 얼마나 있는지를 세는 함수
- join(), split() : join()은 리스트를 문자열로 만드는 메서드, split()은 문자열을 리스트로 만드는 메서드
예)
>>> birthday = '1971/12/09'
>>> birthday.split('/')
['1971', '12', '09']
>>> aaa = birthday.split('/')
>>> aaa
['1971', '12', '09']
>>> '-'.join(aaa)
'1971-12-09'
- sort(), sorted() : 리스트의 정렬 - sort()는 리스트내부 정렬, sorted는 정렬된 복사본!
- 할당 vs copy: '='는 할당, copy()함수는 복사본을 만듬.
▶▶ 리스트에는 strip()이 지원되지 않는다. 따라서 당연히 리스트에서 객체를 뽑아낸 후(문자열이 되면) strip 을 해야 한다.
예) words = ['apache\n', 'decal\n', 'did\n', 'neep\n', 'noon\n', 'refer\n', 'river']
# words = words.strip() <-- 불가능!
for word in words:
word = word.strip()
▶▶ 리스트의 행렬연산은 별도 참조 (numpy 라이브러리)
▶▶주의. set(집합)도 있음. --- 집합연산에 유용
set = {'a', 'b', 'c'} // "중괄호{ }"를 쓰지만 "key : val"형태가 아님! 중복도 허용하지 않음.
예) s2 = set("Hello")
결과는 set(['H', 'e', 'l', 'o'])
// 중복된 l은 하나만.
▶▶ 세트(set, 집합)
- list와 비슷하지만 중복요소는 안됨. // 그래서 멤버십테스트. 중족요소 제거 등의 용도로 사용됨.
- 키만 남은 딕셔너리 (각 키는 유일해야 함) // 즉 중복되지 못함 (딕셔너리와 동일한 특성)
- 딕셔너리처럼 중괄호 "{"를 사용함 [딕셔너리는 키:값이 있지만 세트는 키만 존재]
- 구성요소는 unodered로 순서를 보장하지 않음.
- 세트는 []로 특정요소를 출력할수 없음!!! (딕셔너리와의 차이점)
- 세트안에 세트를 사용할수 없음
- 집합연산 (|, &, -, ^)이 사용가능함.
// | union(합집합, OR), ==> 동일 표현식은 set.union(a, b)
// & intersection(교집합, AND), ==> set.intersection(a, b)
// - difference(차집합), ==> set.difference(a, b)
// ^ symmetric difference(대칭차집합, XOR) ==> set.symmetric_difference(a, b)
// |= 또는 set.update()
// & = 또는 set.intersection_update()
// -= 또는 set.difference_update()
// ^= 또는 set.symemetric_difference_update()
- 그외연산 : issubset(), issuperset(), a.add(), a.remove(), a.discard(), a.pop(), a.clear() 등
예)nums = {1, 2, 1, 3, 1, 4, 5, 6}
print(nums)
nums.add(-7)
nums.remove(3)
print(nums)
>>>
{1, 2, 3, 4, 5, 6}
{1, 2, 4, 5, 6, -7}
>>> 중복된 1은 안보임!!!!
예) set1 = set('apple') --> 결과는 p는 중복되서 하나만 나옴!!!
만약 list('apple')이라면??
a1 = list('apple pie!') --> ['a', 'p', 'p', 'l', 'e', ' ', 'p', 'i', 'e', '!']
a2 = tutple('apple pie!') --> ('a', 'p', 'p', 'l', 'e', ' ', 'p', 'i', 'e', '!')
a3 = set('apple pie!') --> {' ', '!', 'a', 'e', 'i', 'l', 'p'}
a4 = dict('apple pie!') --> ValueError
예)
>>> a = {{1, 2}, {3, 4}}
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
a = {{1, 2}, {3, 4}}
TypeError: unhashable type: 'set'
▶▶ a = {} 는 딕셔너리일까? 세트일까?
--> 빈 딕셔너리로 간주됨. 세트 아님! 빈 세트를 만드는 방법은 a = set() 뿐임.
▶▶ 딕셔너리를 정의할때 키값만으로 정의하며 순서는 없는데, 이를 ordered로 정의하려면 OrderdDict를 사용한다. (from collections import OrderedDict 해야 함)
예) dic1 = {'d':1, 'b':2, 'c':3, 'a':4}
print(dic1)
dic2 = OrderedDict([('d',1), ('b',2), ('c',3), ('a',4)]) <-- 이 형태가 기본 [ ] 안에 (, )로
print(dic2)
dic3 = OrderedDict({'d':1, 'b':2, 'c':3, 'a':4} ) <-- 이 형태 정의도 동작함 (기존의 딕셔너리 형태)
print(dic3)
이들의 차이점은 print(dic.keys())와 같이 출력해보면 차이가 보임.
일반 딕셔너리, 오더드딕셔너리는 아래와 같이 명칭이 다르게 나옴.
dict_keys(['d', 'b', 'c', 'a'])
odict_keys(['d', 'b', 'c', 'a'])
odict_keys(['d', 'b', 'c', 'a'])
[주의] OrderedDict()에서 value도 같다고 착각하지 말 것.(비교연산에서)
참조 : https://code.i-harness.com/ko/q/20b91e2
▶▶ 리스트를 만드는 함수 - list()
예) list('hello') --> ['h', 'e', 'l', 'l', 'o']
예) list(range(10)) --> [0, 1, 2, ..생략, 9]
--- 주의. range()함수는 인자로 float를 줄수 없다!!!!!
▶▶ 리스트의 할당과 복사에 유의
예) a = [0, 0, 0, 0, 0]
b = a
b[2] = 99
a?
b?
---이때 결과는 a, b 모두 [0, 0, 99, 0, 0]임. 왜? b=a라는 동작은 할당이지 복사가 아님.
만약 b = a.copy()를 하면 복사로 다른 결과가 나옴
a는 [0,0,0,0,0]이 그대로 나올 것임
▶▶ 리스트 컴프리헨션 (== 축약식/표현식으로 이해하면 됨)
- 리스트 / 튜플 / 딕셔너리 / 세트 모두 동일한 방식으로 선언가능함
● [식 for 변수 in 리스트]
● list(식 for 변수 in 리스트)
조건을 추가 하면
● [식 for 변수 in 리스트 if 조건식]
● list(식 for 변수 in 리스트 if 조건식)
예)
>>> a = [i for i in range(10) if i % 2 == 0] # 0~9 숫자 중 2의 배수인 숫자(짝수)로 리스트 생성
>>> a
[0, 2, 4, 6, 8]
>>> b = [i + 5 for i in range(10) if i % 2 == 1] # 0~9 숫자 중 홀수에 5를 더하여 리스트 생성
>>> b
[6, 8, 10, 12, 14]
▶▶ 딕셔너리의 생성을 dict()로 할당하려고 하면 키에 따옴표를 쓰지 말아야 함.
예)
>>> x1 = dict(a=10, b=20, c=30) # 키=값 형식으로 딕셔너리를 만듦
>>> x1
{'a': 10, 'b': 20, 'c': 30}
▶▶ 다양한 딕셔너리 생성법
딕셔너리 = dict(키1=값2, 키2=값2)
딕셔너리 = dict(zip([키1, 키2], [값1, 값2]))
딕셔너리 = dict([(키1, 값1), (키2, 값2)])
딕셔너리 = dict({키2: 값1, 키2: 값2})
예)
>>> x1 = dict(a=10, b=20, c=30) # 키=값 형식으로 딕셔너리를 만듦
>>> x2 = dict(zip(['a', 'b', 'c'], [10, 20, 30])) # zip을 이용하여 리스트 두 개를 딕셔너리로 만듦
>>> x3 = dict([('a', 10), ('b', 20), ('c', 30)]) # (키, 값) 형식의 튜플로 딕셔너리를 만듦
>>> x4 = dict({'a': 10, 'b': 20, 'c': 30}) # dict 안에서 중괄호로 딕셔너리를 만듦
응용예) 표현식으로 생성하기
>>> x = dict(zip(range(1, 11), [2 ** i for i in range(1, 11)]))
>>> x
{1: 2, 2: 4, 3: 8, 4: 16, 5: 32, 6: 64, 7: 128, 8: 256, 9: 512, 10: 1024}
▶▶ 딕셔너리의 키 개수 측정은 len함수 : 예) n = len(dict_name)
▶▶ 키, 값을 입력받아 딕셔너리로 출력하는 예제
예)
keys = input().split()
values = input().split() #주 - 만약 value가 문자가 아니면 map으로 다시 변환 해야 함
dict1 = dict(zip(keys, values))
print(dict1)
▶▶ 딕셔너리(세트) 내용을 출력하는 예 ( *.items(), *.keys(), *.values())
예1) for x in dict_name:
print(x)
<-- 여기서는 키 값들만 출력됨
예2) for x, y in dict_name.items():
print(x,y)
<-- 키와 값이, for에서 .items()를 붙여서 동작함
예3) for x, y in dict_name:
print(x,y) <-- 에러남 (왜???? items()가 없음)
예4) for x in dict.keys():
print(x) <-- 키값들이 출력됨 // 만약 dict.values()로 하면 됨
예5) while로 하되 next()를 이용하는 방법(+예외처리 필요)
▶▶ 딕셔너리에서 특정값 삭제 방법 (키를 기준으로 삭제하는 것)
- 키를 기준으로 삭제하려면 .del 연산자를 사용하면 됨.(주의: del() 메서드가 아님), 그려면 값을 기준으로 삭제하려면???
- 그런데 for 루프로 조건을 비교하면서 돌리면 런타임에러 발생함(for 갯수가 바뀌어서)
- 따라서 다음 조건문으로 if에 의해서 딕셔너리 표현식으로 제거하도록 처리함.
예)
>>> x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
>>> x = {key: value for key, value in x.items() if value != 20} <-- != 로 되어 있음!!!
>>> x
{'a': 10, 'c': 30, 'd': 40}
예2) for 루프로 돌리려함 (실패!)
x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
for key, value in x.items():
if value == 20: # 값이 20이면
del x[key] # 키-값 쌍 삭제
print(x)
----> RuntimeError: dictionary changed size during iteration
| 중국이 ML에 두각을 내는 이유가 한자와 입력기 때문이다? (autocomplete) (0) | 2023.05.19 |
|---|---|
| [ML] 생각하지 않는 사람들 - 2 (0) | 2023.05.08 |
| GAN의 위험성(?) (0) | 2023.04.12 |
| re : 파이썬 정규식 라이브러리 (0) | 2022.03.17 |
| 파이썬 리스트의 LIFO, FIFO 사용법 (0) | 2022.03.11 |