길이를 알수 없는 요소를 Unpacking 하고 싶다면?


이럴때는 *를 사용하는데, 예를 들면, 리스트중 첫번째와 마지막을 버리고 중간으로만 평균을 낸다.

라고 가정을 하면 어떻게 만들수 있을까?


def drop_first_last(grades):
    first, *middle, last = grades
    return avg(middle)

굉장히 간단하게 구현이 가능하다.


또한 아래와 같은 경우에도 사용이 가능하다


[ '이름', '이메일', '전화번호', '전화번호', '전화번호' ]


>>> record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')
>>> name, email, *phone_numbers = user_record
>>> name
'Dave'
>>> email
'dave@example.com'
>>> phone_numbers
['773-555-1212', '847-555-1212']
>>>

위의 코드에서 phone_number는 항상 list라는 것이 포인트다

전화번호의 개수에 상관없이 unpacking이 가능하다.


*된 변수는 제일 마지막이라는 법은 없다. 처음이 될 수도 있다.


1~8 분기 까지의 판매실적이 있는데 1~7까지만 평균을 보고 8분기는 현재실적을 리턴하고 싶다면 아래와 같이 구현할수 있다


*trailing_qtrs, current_qtr = sales_record
trailing_avg = sum(trailing_qtrs) / len(trailing_qtrs)
return avg_comparison(trailing_avg, current_qtr)

파이썬 입장에서 해석되는 코드 (아래)


>>> *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3]
>>> trailing
[10, 8, 7, 1, 9, 5, 10]
>>> current
3

*을 사용하면 길이가 분명하지 않은 반복가능한 객체에 대해서 값을 출력할수 있음.


활용을하자면 다양한 길이의 튜플이 존재할 경우 아래와 같이 활용할 수있음.


records = [
     ('two', 1, 2),
     ('one', 'hello'),
     ('two', 3, 4),
]

def do_foo(x, y):
    print('two', x, y)

def do_bar(s):
    print('one', s)

for tag, *args in records:
    if tag == 'two':
        do_foo(*args)
    elif tag == 'one':
do_bar(*args)

*사용하면 split 함수와도 굉장히 잘 어울립니다.!


>>> line = 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false'
>>> uname, *fields, homedir, sh = line.split(':')
>>> uname
'nobody'
>>> homedir
'/var/empty'
>>> sh
'/usr/bin/false'
>>>

또한 아래와 방법으로도 사용이 가능하다. (이부분에서 좀 놀랐음.)


record = ('ACME', 50, 123.45, (12, 18, 2012)) 의 데이터가 있으면

이름과 마지막 2012의 년도만 값으로 얻고싶으면 어떻게할까?


>>> record = ('ACME', 50, 123.45, (12, 18, 2012))
>>> name, *_, (*_, year) = record
>>> name
'ACME'
>>> year
2012
>>>

위와같이 사용하면 된다.


첫값을 가지고 오고, 나머지는 리스트로 반환하려면?


>>> items = [1, 10, 7, 4, 5, 9]
>>> head, *tail = items
>>> head
1
>>> tail
[10, 7, 4, 5, 9]
>>>

위의 방법을 활용하면 '효율적인 재귀알고리즘'을 만들 수 있다.


>>> def sum(items):
...     head, *tail = items
...     return head + sum(tail) if tail else head
...
>>> sum(items)
36
>>>

그렇지만 추천 하는 방법은 아님. 그냥 이런 방법이 있구나 하고 알아두자.

Posted by C마노
,