학습 정리 - **, namedtuple, OrderedDict, frozenset, zip, sort (2025.01.16)

수아·2025년 1월 16일
0

학습 정리

목록 보기
13/51
post-thumbnail

회고 리스트

1. 네임드 튜플에 대하여 설명하시오.

from collections import namedtuple

Person = namedtuple('Person', ['name', 'age', 'height'])

person = Person('Sua', 100, 180)

print(person[0], person[1], person[2])              # 출력 : Sua 100 180
print(person.name, person.age, person.height)       # 출력 : Sua 100 180

Python의 collections 모듈에서 제공하는 튜플의 서브클래스이다.
필드 이름과 인덱스를 사용해서 데이터에 접근할 수 있는 튜플이다.
튜플처럼 가볍고 빠르지만 이름으로 데이터에 접근할 수 있어서 가독성이 좋다.
클래스처럼 사용 가능하지만 더 간단하게 선언할 수 있고 불변성을 유지한다.

2. 아래가 돌아 가도록 네임드 튜플을 사용하시오.

Tri = 네임드 튜플
t = Tri(3,7) # 네임드 튜플 객체 생성
print(t[0],t[1]) #일반 튜플과 동일한 방법으로 접근 가능하다.

print(t.width , t.height) #일반 튜플과 달리 이름으로도 접근이 가능하다.

from collections import namedtuple

Tri = namedtuple('Tri',('width', 'height'))

t = Tri(3,7) 

print(t[0],t[1])                # 출력 : 3 7 
print(t.width , t.height)       # 출력 : 3 7

3. 2번과 마찬가지로 아래를 완성하시오.

Cirlce = 네임드 튜플
circle = Cirlce(10)

print(circle[0]) #10
print(circle.radius) #10

from collections import namedtuple

Cirlce = namedtuple('Circle', ['radius'])
circle = Cirlce(10)

print(circle[0])        # 출력 : 10
print(circle.radius)    # 출력 : 10

4. 딕셔너리 만드는 4가지 케이스를 예를 들어 설명하시오.

dic1 = {'a' : 1, 'b' : 2, 'c' : 3}

dic2 = dict(a=1, b=2, c=3)

dic3 = dict(zip("abc",(1, 2, 3)))

dic4 = dict( [('a', 1), ('b', 2), ('c', 3)] )
# dic4 = dict( (('a', 1), ('b', 2), ('c', 3)) )     # 안쪽은 리스트, 튜플 둘 다 가능

print(dic1)         # 출력 : {'a': 1, 'b': 2, 'c': 3}
print(dic2)         # 출력 : {'a': 1, 'b': 2, 'c': 3}
print(dic3)         # 출력 : {'a': 1, 'b': 2, 'c': 3}
print(dic4)         # 출력 : {'a': 1, 'b': 2, 'c': 3}

5. zip 에 대하여 설명하시오.

a = [1, 2, 3]
b = ['x', 'y', 'z']

z = zip(a, b)  # zip 객체 생성

print(list(z))  # [(1, 'x'), (2, 'y'), (3, 'z')] -> zip 객체 순회해서 결과 반환
print(list(z))  # [] -> 이미 순회가 끝났으므로 비어 있음

두 개 이상의 리스트, 튜플, 문자열 등의 이터러블을 나란히 묶어서 한 쌍씩 짝을 지어주는 함수이다.
그렇게 만든 짝을 하나씩 꺼낼 수 있는 이터레이터를 만들어준다.
(결과는 이터레이터로 반환되기 때문에 리스트 or 튜플로 변환해야 한다.)

zip( ) 함수는 결과를 이터레이터로 반환하기 때문에 메모리를 절약하면서 한 번에 하나씩 값을 처리한다.
한번 순회하면 zip 객체는 소진되므로 여러 번 사용하려면 리스트로 변환해서 저장하면 된다.

6. 아래를 zip함수를 이용하여 만드시오.

(('a', 1), ('b', 2), ('c', 3))

print(tuple(zip('abc', (1, 2, 3))))		# 출력 : (('a', 1), ('b', 2), ('c', 3))

7. 아래를 zip함수를 이용하여 만드시오.

# 출력 [('a',1,'one'),('b',2,'two'),('c',3,'three')]

dic = zip('abc', (1, 2, 3), ('one', 'two', 'three'))
print(list(dic)) 

8. * 와 ** 사용 규칙 4가지로 요약하여 설명하시오.

  • # func(*iterable) : 언패킹
    : 이터러블(리스트, 튜플 등)을 개별 요소로 풀어서 전달한다.
def add(a, b, c):
    return a + b + c

nums = [1, 2, 3]
print(add(*nums))  	# 1, 2, 3을 풀어서 전달 -> 출력 : 6

  • # func(**dict) : 언패킹
    : 딕셔너리를 키=값 형태로 풀어서 전달한다.
def greet(name, age):
    return f"Hello {name}, you are {age}!"

person = {'name': 'Sua', 'age': 100}
print(greet(**person))  # 키=값 형태로 전달 -> 출력 : Hello Sua, you are 100!

  • # def func(*args) : 패킹
    : 여러 개의 위치 인자를 튜플로 묶어서 받는다.
def sum_all(*nums) : 
	s = 0
	for i in nums :
		s += i
	return s

print(sum_all(1,2,3))       # 출력 : 6  

  • # def func(**args) : 패킹
    : 여러 개의 키워드 인자를 딕셔너리로 묶어서 받는다.
def func(**args) :     
    print(args) 

func(a = 1, b = 2, c= 3)	# 출력 : {'a': 1, 'b': 2, 'c': 3}

9. 아래의 함수가 있다. 키와 값을 한꺼번에 넘기는 방법을 코딩하시오.

def who(a,b,c):
    print(a,b,c ,sep=",")

d = dict(a=1,b=2,c=3)

# 출력 : ('a', 1),('b', 2),('c', 3)

who(*d.items())			# 출력 : ('a', 1),('b', 2),('c', 3)

10.아래와 같이 변수로 패킹 할때와 , 함수에서 파라미터로 패킹 할때의 차이점은?

a ,*b,c = 1,2,3,4
print(a,b,c)

def func(*args): # 튜플로 묶음
    print(args)	

둘 다 패킹의 역할을 하지만 목적과 결과 타입이 다르다.

변수에서 *를 사용할 때는 나머지 값을 리스트로 묶어서 저장한다.
나머지 값을 한 변수에 저장하기 위해서 사용된다.

함수 파라미터에서 *를 사용할 때는 여러 개의 포지셔널 인자를 튜플로 묶어서 함수 내부로 전달한다.
함수 호출 시 전달된 모든 포지셔널 인자를 하나의 튜플로 묶는다.
여러 포지셔널 인자를 한꺼번에 받기 위해 사용된다.

11. 아래의 함수가 있다. 출력값이 아래와 같이 나오도록 함수 호출을 하시오.

def func(*arg,**args):
    print(arg)
    print(args)  #def print(*arg,**args):

# 출력 : 
(1, 2, 3)
{'a': 1, 'b': 2}

func(1, 2, 3, a=1, b=2)

12. 파이썬에서의 버전 확인 방법은?

import sys

sys.version

# terminal에서 python -v 도 가능

13. OrderedDict으로 객체 생성을 한 dictionary 와 dict()함수로 객체를 생성한 딕셔너리의 차이점을 설명해 보시오.

from collections import OrderedDict

dic = {'a' : 1, 'b' : 2, 'c' : 3}
another_dic = {'c' : 3, 'b' : 2, 'a': 1}

print(dic == another_dic) # True

od = OrderedDict({'a' : 1, 'b' : 2, 'c' : 3})
another_od = OrderedDict({'c' : 3, 'b' : 2, 'a': 1})

print(od == another_od) # False 

파이썬 3.7 버전 이후로는 입력한 순서대로 딕셔너리에 입력되고 있다고 하지만 딕셔너리 자체에 순서가 없기 때문에 같은 키 - 값 쌍을 가지면 동일하다고 판단한다.

OrderedDict는 입력된 순서를 저장하고 비교할 때도 순서까지 비교하기 때문에 입력 순서가 다른 경우엔 키 - 값이 같더라도 다르다고 판단한다.

14. set과 frozenset 의 차이는?

os = {1, 2, 3, 5, 5}

os.add(6)
print(os)			# 출력 : {1, 2, 3, 5, 6}

os.discard(2)
print(os)			# 출력 : {1, 3, 5, 6}

fs = frozenset({1, 2, 3, 5, 5})
print(fs)			# 출력 : frozenset({1, 2, 3, 5})

# fs.add(6)         # 에러 발생
# fs.discard(6)     # 에러 발생

set과 frozenset은 둘 다 집합 자료형으로 중복을 허용하지 않고 순서가 없다.
인덱스를 통해 접근할 수 없고 for문이나 in을 사용한 연산을 주로 사용한다.
집합 연산을 사용한다.

frozenset은 set과 동일하지만 요소들의 추가, 삭제가 불가능하다.
set은 mutable하지만 frozenset은 immutable하다.

15.아래를 세번째 글자순으로 정렬하시오.

arr = ['abc', 'bac', 'bca'] 

# arr.sort(key = lambda x: x[2])

def third_sort(t) : 
    return t[2]

arr.sort(key = third_sort)
print(arr)				# 출력 : ['bca', 'abc', 'bac']

key 매개변수는 정렬의 기준을 정의하는 함수 or lambda를 받는다.

16.아래를 튜플의 합으로 계산하시오.

nums = [(3, 1),(2, 9),(0, 5)] 

nums.sort(key = lambda x : x[0] + x[1], reverse = True)
print(nums)             # 출력 : [(2, 9), (0, 5), (3, 1)]

오름차순이 기본값이며 reverse = True 를 넣으면 내림차순으로 정렬된다.

17.아래를 글자 갯수 순으로 정렬하시오.

names =  ['Julasdfdsaia','Yooadfn','Stevadfen']

names.sort(key = len)
print(names)        # 출력 : ['Yooadfn', 'Stevadfen', 'Julasdfdsaia']

18. 아래가 에러가 나는 이유는?

frozen_set = frozenset({1,2,3,5,5}) 
print(frozen_set)
frozen_set.add(6) 

frozenset은 set과 달리 요소들을 추가, 삭제가 불가능하기 때문이다.

19. 아래코드에서 중복을 없애시오.

t = [3,3,3,7,7,'z','z']

print(t) # 출력 : [3,'z',7]

t = list(set(t))
print(t) 			# 출력 : [3,'z',7]

코드가 요상해보이지만... 중복을 없애려면 set을 써야하는데 출력 결과는 list로 보이길래....
어쩔 수 없이 저런 코드가 나왔다.

20.아래 코드를 결과값을 예측하고, 분석해 보세요.

b_idx = sorted(range(len(b)), key=lambda k: b[k]) 
print(b_idx)

sorted는 정렬된 새로운 리스트를 반환한다.
0~(b-1)까지의 수를 저장한 리스트를 만들고 그 리스트를 b의 인덱스에 넣어서 나온 값을 기준으로 정렬한다.

b = [40, 10, 30, 20] 

b_idx = sorted(range(len(b)), key=lambda k: b[k])

print(b_idx)  		# 출력: [1, 3, 2, 0] -> b의 값을 기준으로 정렬된 인덱스

b에 대한 정보가 부족해서 잘 와닿지 않을 수 있어서 예시 리스트를 만들어봤다.

세줄요약:
1.네임드 튜플은 클래스를 만드는 과정이다.
2. * 와 ** 쓰는 4가지 케이스를 이해하자.
3. 순서있는 dictionary 는 OrderedDict으로 객체를 생성하자.


궁금한 점

def func(**args) :     
    print(args) 

func(a = 1, b = 2, c= 3)
func('a'= 1, 'b' = 2, 'c'= 3)		# 에러

보통 딕셔너리에 키 - 값을 넣을 때 {'a' : 1, 'b' : 2, 'c' : 3} 이런식으로 넣기도 하고
작은 따옴표, 큰 따옴표 없이 a가 오면 변수로 인식된다는 얘기를 들었어서 func('a'= 1, 'b' = 2, 'c'= 3) 가 맞을 것 같은데 에러가 나서 이해가 잘 가지 않는다...

2개의 댓글

comment-user-thumbnail
2025년 1월 18일

func('a'= 1, 'b' = 2, 'c'= 3) 이 부분은 변수선언이 넘어간다고 생각하시면, 이해가 편하실것 같습니다. 'a' = 1 문자열 a에 1을 할당하는게 아니듯이, 함수에서 호출 할때는 변수 선언으로 넘기고, 함수를 넘겨 받는쪽에서 **agrs 로 받으면 문법적으로 변수를 문자열로 변환시켜 {'a':1 ~~} 받아낸다고 이해해 주시기 바랍니다.

1개의 답글