2015-03-22 3 views
1
>>> def foo1(*args, **kwargs): 
... print(*args, **kwargs) 

>>> def foo2(*args, **kwargs): 
... print("{} {}".format(*args, **kwargs)) 

>> foo1(1) 
1 
>> foo2(1) 
IndexError: tuple index out of range 

мое понимание правильно: *args, **kwargs на самом деле кортежем потому, что запятая марок он в один и, поскольку есть два заполнителя {}, то .format пытается получить доступ ко второму элементу этого кортежа?печати (* Args, ** kwargs) против печати (. "{}, {}" Формат (* арг, ** kwargs))

+0

@thefourtheye: Какие? Нет, это неправильно. –

ответ

7

Нет, это не так, если это было бы верно, что ваш код будет выводить "((1) {})", потому что args будет кортеж с 1 и kwargs пустой Словаре (который представлен как {}).

Обычно func(a,b) вызывает функцию с двумя аргументами. Это не то же самое, что вызывать функцию с кортежем func((a,b)), вы вызываете эту функцию только с помощью одного аргумента.

Иногда вы хотите написать функцию, которая содержит неизвестное количество аргументов. Вы можете использовать func(*args) (обратите внимание, что имя args не требуется, но соглашение. Любое имя с одной звездой впереди будет работать) синтаксис для этого. Мы могли бы написать join() функцию, которая не список строк, но произвольное количество строк в качестве аргументов:

def join_(*args): 
    rv = "" 
    for _string in args: 
     rv += _string 
    return(rv) 

>>> join_("first", "second", "third") 
"firstsecondthird" 

>>> join_(["first", "second", "third"]) 
TypeError: Can't convert 'list' object to str implicitly 

Как вы видите, есть разница кастрированный баран вы называете это со многими аргументами или со списком аргументов (или кортеж, для этого важно). Если бы мы определили его как def join_(args), первая версия не сработала бы, а только вторая. Звезда «сосет» аргументы в один список. Вы можете найти документацию here.

Если есть способ вывести аргументы в список, должен быть способ вывести аргументы из списка в аргументы функции. И есть! (Предположу, что определение join_() сверху)

>>>join_(*["first", "second", "third"]) 
"firstsecondthird" 

Так * перед списком (или кортежа) будет «толкать» элементы списка из аргументов функции. ** - это то же самое, только со словарем для аргументов ключевого слова.

Так что делает ваш пример? Давайте посмотрим на foo1. Он всасывает все аргументы в список с именем args, а затем снова выводит эти аргументы в функцию печати. Поэтому ваш звонок foo1(1) звонит print(1). Что делает foo2? Ваш звонок foo2(1) звонит print("{} {}".format(1)) - вы просите заменить на значения, но только один. Также обратите внимание, что кортежа нет нигде. Что случилось с ** kwargs? Поскольку вы не указали аргументы ключевого слова, оно «исчезло». Это даже не пустой словарь, как вы можете проверить:

>>>print(**{}) 

>>>print({}) 
{} 

На другой ноте вы можете сделать:

def foo3(*args, **kwargs): 
    print("{} {}".format(args, kwargs)) 

, который никогда не возбудит исключение:

>>> foo3() 
() {} 
>>> foo3("abc", "123") 
('abc', '123') {} 
>>>foo3("foo", c="bar") 
('foo',) {'c': 'bar'} 
Смежные вопросы