pythonic tools - asterisk

python의 숙련도를 높여보고자 itertools를 공부하려고 보니 iterable, iterator, generator, 그리고 asterisk까지 서로 엮여있는 상황이라… 함께 공부하는 것이 나은 듯 하다. 어떤 공부든 요약 정리를 하다 보면 이해가 잘 되는 편이라, 오늘도 여기에 정리. 시작은 쉬운 asterisk부터.

asterisk *

python을 잘 쓴다는 사람들은 pythonic하게 코드를 쓰는 걸 좋아하는데, 그 의미는 대략 ‘intelligence’, ‘straightforward’, ‘brief’ 정도의 느낌이다. 그리고 * 는 그런 pythonic한 코드를 쓰도록 돕는 도구 중 하나. 물론 itertools도 pythonic한 느낌이다. (주관 가득)

1. 곱셈 및 거듭제곱

>>> 2*3, 2**3
(6, 8)

2. List 반복 확장

>>> zeros_list = [0] * 100 # 길이 100의 제로값 리스트
>>> zeros_tuple = (0,) * 100 # 길이 100의 제로값 튜플
>>> vector_list = [[1, 2, 3]]
>>> for i, vector in enumerate(vector_list * 3):
        print("{0} scalar product of vector: {1}".format((i + 1), [(i + 1) * e for e in vector]))

1 scalar product of vector: [1, 2, 3]
2 scalar product of vector: [2, 4, 6]
3 scalar product of vector: [3, 6, 9]

3. Variadic Parameters 가변 인자

python의 인자는 positional/keyword arguments로 나뉜다. 전자는 위치에 따라 정해지는 인자, 후자는 이름을 가진 인자를 말한다. 파이썬의 함수는 이러한 인자를 받아 함수를 처리한다.

>>> def get_arguments(positional, keyword=None):
...     ...

그런데 만약 함수에 들어오는 인자의 갯수를 모르거나, 어떤 인자가 들어올지 모르지만 모두 받아서 처리를 해야 할 때는 어떻게 해야 할까?

  • 바로 * 를 이용해서 가변 인자를 쓰는 것이다.
>>> def every_positional_arguments(*args):
...     print(args)

>>> every_positional_arguments('MJ', 34, 'MKS', [34])
('MJ', 34, 'MKS', [34])

>>> def every_keyword_arguments(**kwargs):
...     print(kwargs)

>>> every_keyword_arguments(first='MJ', second=34, Whatever='MKS', fourth=[34])
{'first': 'MJ', 'second': 34, 'Whatever': 'MKS', 'fourth': [34]}

args, kwargs는 다른 인자명을 사용할 수도 있고, 함께 쓸 수도 있다.

  • 다만 특별한 의미가 있는 것이 아니라면 관례(*args, **kwargs)를 따르는 것이 권장된다.
>>> def every_arguments(*whatever1, **whatever2):
...     print(whatever1)
...     print(whatever2)

>>> every_arguments('MJ', 34, 'KK', first='MJ', second=34, Whatever='MKS', fourth=[34])
('MJ', 34, 'KK')
{'first': 'MJ', 'second': 34, 'Whatever': 'MKS', 'fourth': [34]}

4. 컨테이너 타입 데이터 Unpacking

>>> from functools import reduce
>>> primes = [2, 3, 5, 7, 11, 13]
>>> def product(*numbers):
...     print(numbers, type(numbers))
...     p = reduce(lambda x, y: x * y, numbers)
...     return p

        # reduce?
        # p = ((((2 * 3) * 5) * 7) * 11) * 13
  • * 를 붙이면 리스트의 데이터들을 unpacking해서 전달 numbers = (2, 3, 5, 7, 11, 13)
  • * 를 안붙이면 numbers = ([2, 3, 5, 7, 11, 13])
>>> product(*primes)
(2, 3, 5, 7, 11, 13) <class 'tuple'>
30030
>>> product(primes)
([2, 3, 5, 7, 11, 13],) <class 'tuple'>
[2, 3, 5, 7, 11, 13]

튜플도 동일하게 동작한다.

>>> product(*(1, 2, 3))
(1, 2, 3) <class 'tuple'>
6

References

mingrammer.com - 파이썬의 Asterisk(*) 이해하기

댓글남기기