2010-04-05 22 views
3

У меня есть две функции Python, каждая из которых принимает переменные аргументы в своих определениях функций. Чтобы дать простой пример:Список Python как * args?

def func1(*args): 
    for arg in args: 
     print arg 

def func2(*args): 
    return [2 * arg for arg in args] 

Я хотел бы, чтобы составить их - как в func1(func2(3, 4, 5)) - но я не хочу args в func1 быть ([6, 7, 8],), я хочу, чтобы это было (6, 7, 8), как если бы оно был назван как func1(6, 7, 8), а не func1([6, 7, 8]).

Как правило, я бы просто использовал func1(*func2(3, 4, 5)) или имел func1, чтобы проверить, был ли args[0]. К сожалению, я не могу использовать первое решение в этом конкретном экземпляре, и для применения второго потребуется выполнить такую ​​проверку во многих местах (в функции func1 есть много функций).

Есть ли у кого-нибудь идеи, как это сделать? Я предполагаю, что какая-то интроспекция может быть использована, но я могу ошибаться.

+7

"' Я не могу использовать первое решение в данном конкретном instance'" Почему нет? – interjay

+0

Я использую парсер, который вызывает функции Python, но не поддерживает распаковку в грамматике. – exupero

ответ

3

Вы можете использовать декоратор, размещенный Ярославом.

Минимальный пример:

def unpack_args(func): 
    def deco_func(*args): 
     if isinstance(args, tuple): 
      args = args[0] 

     return func(*args) 

    return deco_func 


def func1(*args): 
    return args 

def func2(*args): 
    return args 

@unpack_args 
def func3(*args): 
    return args 

print func1(1,2,3) # > (1,2,3) 
print func2(1,2,3) # > (1,2,3) 
print func1(*func2(1,2,3)) # > (1,2,3) 
print func1(func2(1,2,3)) # > ((1,2,3),) 
print func3(func2(1,2,3)) # > (1,2,3) 
4

Вы можете рассмотреть возможность создания декоратора функций, который проверяет, является ли первый аргумент списком. Применение декоратора к существующим функциям немного проще, чем изменение функций.

1

Обычно, я бы просто использовать func1(*func2(3, 4, 5)) или иметь func1 проверить, если args[0] был list. К сожалению, я не могу использовать первое решение в этом конкретном экземпляре, и для применения второго потребуется выполнить такую ​​проверку во многих местах (в функции func1 есть много функций).

Почему вы не можете использовать первое решение?

>>> def func1(*args): 
    for arg in args: 
     print arg 

>>> def func2(*args): 
    return [2 * arg for arg in args] 

>>> func2(3, 4, 5) 
[6, 8, 10] 
>>> func1(1,2,3) 
1 
2 
3 
>>> func1(*func2(3, 4, 5)) 
6 
8 
10 
>>> 

Если это не возможно, еще можно было бы использовать func1(*tuple(func2(3, 4, 5))) (но не нужно).

+0

Я думаю, что OP имеет функции, возвращающие скалярные значения, а не только кортежи или списки. Преобразование их в общий стандарт слишком дорого. – Yaroslav

Смежные вопросы