학습 정리 - 키워드 인자, 포지셔널 인자 / 뷰 객체 / 딕셔너리 컴프리헨션 / map(), filter() / 패킹과 언패킹(2025.01.15)

수아·2025년 1월 15일
1

학습 정리

목록 보기
12/51
post-thumbnail

회고 리스트

1. 키워드 인자 와 포지셔널 인자에 대하여 설명하시오.

  • 키워드 인자 (Keyword-only Argument)
    : 함수를 호출할 때 변수명=값 형태로 사용해야 하는 인자
    : * 는 키워드 인자를 강제하기 위해 사용된다.
    뒤쪽에 나오는 인자를 모두 키워드 인자로 받도록 강제한다.
    ( ' *, ' << 이렇게 사용 / 변수 앞에 바로 붙이지 않는다.)

  • 포지셔널 인자 (Positional-only Argument)
    : 함수를 호출할 때 값을 순서대로 전달해야 하는 인자
    : /는 포지션 인자를 강제하기 위해 사용된다.
    : / 앞에 있는 인자는 순서대로 전달해야 한다.
    (포지셔널 인자로 받고 싶은 변수 뒤에 /를 단독으로 붙인다.)

def mix_func(a, b, /, h, i, *, x, y) :
    print(a - b, h - i, x * y)
    
mix_func(15, 6, 6, h = 9, x = 3, y = 2)         # 에러
mix_func(15, 6, i = 6, h = 9, x = 3, y = 2)

a, b는 포지셔널 인자 / x, y는 키워드 인자 / 나머지 h, i는 둘 다 가능하다.
이때 h도 키워드로 넘겨줬을 때 나머지만 순서대로 전달하면 될 거라고 생각했다.
하지만... 포지션 인자는 순서대로 채워지기 때문에 h를 중복으로 전달받았다고 생각해서 TypeError가 발생한다.
그래서 h를 키워드로 전달하고 싶을 경우엔 i도 키워드로 전달해야 한다.

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

def mul(x,y,/):	 #포지션 인자만 받겠다.
    return x * y

mul(x=4,y=5)

포지션 인자만 받겠다고 맨 뒤에 /를 붙여놓고 값은 키워드로 전달했기 때문이다.
함수 정의할 때 파라미터 자리에서 /를 빼던지 값을 전달할 때 포지션 인자로 전달해야 한다.

3. 아래가 에러가 나는 줄은 몇번째 줄이며 이유는?

def only_keyword(*,x,y): # 키워드 인자만 받겠다
    return x + y

only_keyword(x=1,y=2)
only_keyword(1,2)

에러는 마지막 줄에서 난다.
함수를 정의할 때 * 를 사용해 키워드 인자만 받도록 정했기 때문에 포지션 인자로 값을 전ㄴ달하면 에러가 난다.
바로 윗 줄에서 한 것처럼 only_keyword(x = 1, y = 2) 이런 형태로 전달해야 한다.

4. mix_fun 함수를 호출하여 결과 물이 나오도록 하시오.

def mix_fun(a,b,/,h,i,*,x,y): 
    print(a-b)
    print(h-i)
    print(x*y)

mix_fun( 파라미터 )

mix_fun(1,  2, 3, i = 4, x = 5, y = 6)		# 출력 : -1, -1, 30

5. 아래의 출력이 어떻게 나오는지 예측하고, 그이유는?

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

vo = d.items()  # view 객체 생성

for kv in vo:
    print(kv)

d['a'] = d['a'] + 3 # 값 수정
d['c'] += 2  # 값 수정

for kv in vo:
    print(kv)

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

d.items()는 dict_items 객체 (뷰 객체)를 반환한다.
(튜플 형태로 반복 가능한 객체를 반환한다.)
뷰 객체는 복사본이 아닌 참조 객체이기 때문에 d의 현재 상태를 실시간으로 보여준다.
따라서 d의 값이 바뀌면 vo도 변경된 값을 반영한다.

6. 아래의 소스코드를 컴프리헨션으로 줄여 보시오.

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

d2 ={}

for k,v in d1.items():
    d2[k] = v*2

print(d2)
===========================
#컴프리 헨션으로 채우시오.
d2 = {  } ## d1의 값을 두 배 늘린 딕셔너리 생성
print(d2)

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

d2 = {k : v * 2 for k, v in d1.items()}
print(d2)		# 출력 : {'a': 2, 'b': 4, 'c': 6}

7.map을 예를 들어 설명해 보시오.

map 함수는 반복 가능한 객체(리스트, 튜플 등)의 각 요소에 대해 주어진 함수를 적용하여 새로운 값을 반환하는 함수다.
-> map(함수, iterable)

iterable의 각 요소에 함수를 적용해 변환된 값을 가진 map 객체를 반환한다.
반환값은 map 객체이므로 list()나 tuple()로 변환해 사용해야 실제 값을 볼 수 있다.
반복 가능한 여러 iterable을 동시에 다룰 수도 있다.

# 리스트의 요소를 제곱으로 변환
nums = [range(1, 6)]
squared_nums = list(map(lambda x: x ** 2, nums))
print(squared_nums) 	 # 출력: [1, 4, 9, 16, 25]

a, b = map(int, input().split())
난 문제를 풀 때 이런식으로 많이 썼다.
입력받은 문자열을 공백을 기준으로 나누어 리스트로 반환하고
그 요소들을 int함수에 적용하여 정수형으로 변환하여 각각 a와 b에 할당하는 것이다.

8.filter 함수를 예를 들어 설명하시오.

반복 가능한 객체의 각 요소에 대해 조건 함수를 적용하여 True인 값만 필터링하는 함수다.
-> filter(함수, iterable)

함수의 결과가 True인 요소만 반환하며 filter 객체 형태로 반환된다.
map과 마찬가지로 반환값은 filter 객체이므로 list()나 tuple()로 변환해 사용해야 한다.
조건 함수 대신 lambda 함수를 사용해 간단하게 필터링할 수도 있다.

# 짝수만 필터링
nums = [1, 2, 3, 4, 5]
even_nums = list(filter(lambda x: x % 2 == 0, nums))
print(even_nums)  # 출력: [2, 4]

9. 아래가 돌아가도록 sum 함수를 만드시오.

st1 = [1,2,3]
st2 = [3,2,1]


st3 = list(map(sum,st1,st2)) # 함수에 파라미터가 두개 있을 경우
st3 # 출력[4, 4, 4]

st1 = [1,2,3]
st2 = [3,2,1]

def sum (s, t) : 
    return s + t
st3 = list(map(sum,st1,st2)) # 함수에 파라미터가 두개 있을 경우
st3 # 출력[4, 4, 4]

10. 아래의 함수를 완성하시오.

s1 = ['one', 'two','three']
ref = list(map(함수,s1))
print(ref) 
#['eno', 'owt', 'eerht']

def rev (lst) : 
    return lst[::-1]

s1 = ['one', 'two','three']
ref = list(map(rev,s1))
print(ref) 
#['eno', 'owt', 'eerht']

11. filter 함수를 써서 'gender' 가 M 인 사람의 이름만 뽑아내시오.

users = [{'mail': 'gregorythomas@gmail.com', 'name': 'Brett Holland', 'gender': 'M'},
         {'mail': 'hintoncynthia@hotmail.com', 'name': 'Madison Martinez', 'gender': 'F'}]

def is_male(user) : 
    return user['gender']=='M'

m_user = list(filter(is_male, users))

for user in m_user : 
	print(user['name'])
# 출력 : 'Brett Holland'

12. 위의 예제에서 filter 함수를 써서 'gender' 가 F 인 사람을 리스트로 뽑아내시오.

def is_female(user) : 
    return user['gender']=='F'

f_users = list(filter(is_female, users))

for user in f_users : 
    print(user)		# 출력 : Madison Martinez

13. 튜플 언패킹 예제 설명

# 아래 결과를 예측하시오.
nums = (1,2,3,4,5)
first, *others, last = nums 

print(first, others, last)		# 출력 : 1 [2, 3, 4] 5

nums의 첫 번째 요소는 first, 마지막 요소는 last에 할당된다.
나머지 요소는 리스트 형태로 others에 패킹된다.

14. 함수에서 * 사용 시의 차이

함수에서 단독으로 쓰일때와 , 변수명 쓰일때의 차이는?

  • 단독으로 쓰일 때
    : 키워드 인자만 받을 것을 강제하기 위한 표시이다.
    : 그 이후 인자들은 모두 키워드 인자로만 전달해야 한다.

  • 함수 선언에서 *변수명
    : 패킹 연산자로 가변 인자를 받을 때 사용한다.
    : 여러 개의 인자를 튜플로 묶어서 하나의 변수에 할당한다.

  • 함수 호출에서 *변수명
    : 언패킹을 위해 사용된다.
    : 리스트나 튜플의 요소를 함수의 개별 인자로 풀어서 전달할 때 사용되나.

15. 튜플에서 *이 언패킹 하는 케이스를 예를 들어 설명하시오.

def show_man(name, age, height) : 
    print(name, age, height)

p = ('Yoon', 20, 180)

show_man('Yoon', 20, 180)
show_man(*p)

*는 함수 호출 시 언패킹 연산자로 사용되며 튜플이나 리스트의 요소를 개별 인자로 풀어서 전달해 준다.
show_man(*p)는 p의 각 요소가 name, age, height에 각각 할당되므로 문제없이 작동한다.

show_man(p)의 결과가 궁금했는데 name = p로 인식해서 age, height를 전달받지 못 했기 때문에 TypeError가 뜬다.

16.다음을 프로그래밍 하시오.

c = Circle(10)
c.get_area() # 314~~~~

rec = Rectangle(10)
rec.get_area() # 100 

class Circle : 
    def __init__(self, r) : 
        self.r = r
    
    def get_area(self) : 
        return 3.14 * self.r **2 
    
class Rectangle : 
    def __init__(self, length) : 
        self.length = length
    
    def get_area(self) : 
        return self.length ** 2
    
c = Circle(10)
print(c.get_area())         # 출력 : 314

rec = Rectangle(10)
print(rec.get_area())       # 출력 : 100 

세줄요약:
1.결과 데이터 반환을 위해 filter 와 컴프리 헨션으로 효율적 코딩 가능하다.
2.언패킹 하는 케이스는 튜플로 함수 호출 할때 이다.
3.함수 파라미터에서 단독으로 쓰일때와 파라미터명 으로 쓰일때를 구분하자


아침에 궁금했던 것

(해결 완료)

d = dic(a = 1, b = 2, c = 3)
vo = d.items()

for kv in vo : 
	print(kv)

1) 여기서 vo와 kv의 데이터 타입이 궁금했다.
: type( ) 함수를 통해 알아보니 각각 class <'dict.items> / class <'tuple> 이었다.

2) d와 vo가 같은지 궁금했다.
: 아침엔 <'dict'>와 <'dict.items'>의 차이를 몰랐다.
자세하게 안 읽고 앞부분만 보다보니 데이터 타입도 같고 값도 같네..? 라는 생각이 들었다.
알고보니 같은 내용을 참조하기 때문에 값이 같은 거였다.
d는 딕셔너리 / vo는 딕셔너리의 현재값을 반영해서 보여주는 뷰 객체(dict_items 객체)로 튜플 상의 뷰라고 한다.

아침에는 이게 너무 궁금해서 챗 GPT한테 엄청 물어봤다.
단어를 어떻게 말해야 할 지 모르겠어서 이거가 저거야? 이렇게 물어봐도 챗 GPT는 화를 안 낸다.
고마워 챗 GPT야


오늘 배운 것들을 크게 정리해보면 키워드 인자, 포지셔널 인자 / 뷰 객체 / 딕셔너리 컴프리헨션 / map(), filter() / 패킹과 언패킹

딕셔너리 컴프리헨션은 리스트와 다르게 딕셔너리가 있어야만 쓸 수 있어보이길래 쓸모없어보였는데 강사님께서 자주 쓰지는 않는다고 하셨다.. 역시....


* << 이거 보고 앗 포인터...? 싶어서 챗 GPT한테 물어봤는데 답변 읽고 있는 도중에 강사님께서 그 얘기를 고대로 하셔서 신기했다.ㅋㅋㅋㅋㅋ
내 화면을 다 보고 계시는 느낌이었다.

1학년 때 파이썬 배우면서 컴공으로 많이 몰렸다가
전공 결정하기 전에 C언어 포인터 배우고 나서 컴공 친구들이 많이 사라졌던 기억이 난다....ㅎ
내가 1학년 때 사귄 친구들은 반수 아님 타과로 가버린 친구들이었다...

0개의 댓글