본문 바로가기

프로그래밍언어/Python

[Python] Asterisks(*) in Python

반응형

파이썬 예제들을 찾아보던 중에 **option 같은 문법을 발견하였다.

마치  c언어의 포인터와 같이 변수의 앞에 위치하고 있는 asterisk의 의미에 대해서 조사하면서 이외에 파이썬에서 asterisk를 사용하는 방법들에 대해서 살펴보았다.

 

 

1. 곱셈, 거듭제곱 연산

 

기본적으로 곱셈을 위한 연산자로 * 많이 사용한다.

 

2 * 5	# 10

 

또한 asterisk를 두개 붙여 사용하여서 거듭제곱 연산자로 사용한다.

 

2 ** 3	# 8

4 ** 2	# 16

 

 

2. iterable arguments의 unpacking

 

함수의 argument로 iterable한 값이 입력되었을 때 *를 사용해서 unpacking 할 수 있다.

 

fruits = ['lemon', 'pear', 'watermelon', 'tomato']

print(fruits[0], fruits[1], fruits[2], fruits[3])
# lemon pear watermelon tomato

print(*fruits)
# lemon pear watermelon tomato

 

위의 예제에서 print 함수는 fruits 리스트의 모든 요소들을 분리된 인자로 받아 실행한다.

 

**를 사용하는 경우는 keywork arguments를 unpack 할 때이다. 위의 *를 사용하여서 iterable argument를 unpack 하는 것과 같이 **는 dict 타입의 argument를 unpack하여 함수 호출시에 사용할 수 있도록 한다.

 

date_info = {'year': "2021", 'month': "04", 'day': "14"}

filename = "{year}-{month}-{day}.txt".format(**date_info)

print(filename)
# '2021-04-14.txt'

 

예제에서 filename의 year, month, day의 key에 맞춰서 data_info의 value들이 대입된다.

 

함수의 호출 시에 예제처럼 하나의 변수만 주는 것이 아니라 *나 **를 여러번 사용하여 값을 인자로 줄 수 있다. 이때 **의 경우에는 각 key arguments 중에 중복되는 key를 가진 데이터가 없는지 잘 확인해야한다. 파이썬에서는 같은 key의 argument가 여러번 정의될 수 없기 때문에 오류를 발생시키게 된다.

 

 

3. function parameters를 packing (가변인자)

 

함수를 정의할 때 파라미터의 개수를 가변적으로 정의하기 위해서 *를 사용한다. *를 사용하여서 정의하면 입력되는 값들의 숫자에 관계없이 모두 tuple로 묶여서 사용할 수 있게된다. print() 와 zip() 과 같은 함수들이 이러한 방식으로 인자를 받아서 동작한다.

 

def calc_sum(*params):
	return sum(param for param in params)
    
print(calc_sum(1,2,3))			# 6

print(calc_sum(1,3,5,7,9,10)	# 35

 

예제의 calc_sum은 입력받는 모든 인자들에 대해서 그 개수에 상관없이 모두 더한 값을 반환한다.

 

** 연산자는 *와 같이 packing을 통해서 가변인자를 정의하지만 keyword arguments에 대해서 동작한다. 입력된 keyword arguments 들을 dictionary 로 packing 해서 함수안에서 사용 가능하다.

 

def print_kwargs(**kwargs):
	print(kwargs)
    
print_kwargs(first=1, second=2, third=3)
# {'first': 1, 'second': 2, 'third': 3}

 

 

4. Positional arguments with keyword-only arguments

 

keyword-only argument는 함수 호출 시에 argument를 keyword 문법으로만 할당할 수 있도록 하는 argument를 말한다. 이 방식을 사용하기 위해서는 함수 선언시에 parameter에 *연산자를 붙여서 선언하면 된다.

 

def kw_only_func(*keys, arg1, arg2):
	print(keys)
    print(arg1, arg2)
    
kw_only_func('k1', 'k2', 'k3', arg1=1, arg2=2)
# ('k1', 'k2', 'k3')
# 1 2

 

가변인자 keys는 positional 형식으로 값을 받는 반면에, arg1과 arg2는 keywork 방식으로만 인자를 받을 수 있다. 만약 keywork 방식이 아닌 positional 방식으로 값을 넘겨주는 경우 오류가 발생한다.

이 방식 (keyword-only arguments)는 python3 부터 사용할 수 있음을 주의하자.

 

 

5. tuple unpacking

 

temp = [1, 2, 3, 4, 5]
var1, var2, *rest = temp

print(var1)		# 1
print(var2)		# 2
print(rest)		# [3, 4, 5]

 

va11과 val2에 값이 할당되고 rest에 나머지 값들이 모두 할당된다.

 

 

6. list literals

 

python3.5에서 처음 소개된 이 방법은 *를 사용하여서 iterable한 데이터를 새로운 list로 dump 시키는 것이다.

 

def next_list(sequence):
	return [*sequence[1:], sequence[0]]

 

예제의 함수는 인자로 받은 리스트의 첫번째 값을 가장 뒤로 옮긴 리스트를 반환한다.

 

 

7. dictionary literals

 

리스트와 같이 딕셔너리 타입도 새로운 딕셔너리로 값을 dump할 수 있다. 다른 점은 딕셔너리에서는 double asterisks (**)을 사용한다.

 

dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'d': 1, 'e': 2, 'f': 3, 'g': 4}

comb = {**dict1, **dict2}
print(comb)
# {'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3, 'g': 4}

sum_dict = {**comb, 'h': 1}
prit(sum_dict)
# {'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3, 'g': 4, 'h': 5}

 

위의 예제의 comb와 같이 서로 다른 딕셔너리의 값을 **을 사용하여서 합쳐서 새로운 딕셔너리 데이터를 만들 수 있다.

또한 sum_dict에서와 같이 딕셔너리 값을 복사한 후 새로운 값을 더해서 새로운 딕셔너리 데이터를 만들 수도 있다.

 

 

<reference>

- Asterisks in Python: what they are and how to use them

반응형