Что в следующих определениях методов делают * и ** для param2?
def foo(param1, *param2):
def bar(param1, **param2):
Этот вопрос - очень популярная повторяющаяся цель, но, к сожалению, часто используется неправильно. Имейте в виду, что этот вопрос касается определение функций с помощью varargs (def func(*args)). По вопросу о том, что это означает в функции звонки (func(*[1,2])), см. здесь. По вопросу о том, как как распаковывать списки аргументов, см. здесь. На вопрос, что означает * в литералы ([*[1, 2]]), см. здесь.
@ Aran-Fey: Я думаю, что лучшая цель для «что это значит в вызовах функций» - это Что означает оператор-звезда при вызове функции?. Ваша ссылка на самом деле не касается использования **, и это гораздо более узкий вопрос.






Из документации Python:
If there are more positional arguments than there are formal parameter slots, a TypeError exception is raised, unless a formal parameter using the syntax "*identifier" is present; in this case, that formal parameter receives a tuple containing the excess positional arguments (or an empty tuple if there were no excess positional arguments).
If any keyword argument does not correspond to a formal parameter name, a TypeError exception is raised, unless a formal parameter using the syntax "**identifier" is present; in this case, that formal parameter receives a dictionary containing the excess keyword arguments (using the keywords as keys and the argument values as corresponding values), or a (new) empty dictionary if there were no excess keyword arguments.
*args и **kwargs - это общая идиома, позволяющая использовать произвольное количество аргументов для функций, как описано в разделе подробнее об определении функций документации Python.
*args предоставит вам все параметры функции как кортеж:
def foo(*args):
for a in args:
print(a)
foo(1)
# 1
foo(1,2,3)
# 1
# 2
# 3
**kwargs даст вам все
аргументы ключевого слова, кроме тех, которые соответствуют формальному параметру в качестве словаря.
def bar(**kwargs):
for a in kwargs:
print(a, kwargs[a])
bar(name='one', age=27)
# age 27
# name one
Обе идиомы можно смешивать с обычными аргументами, чтобы разрешить набор фиксированных и некоторых переменных аргументов:
def foo(kind, *args, **kwargs):
pass
Также можно использовать это наоборот:
def foo(a, b, c):
print(a, b, c)
obj = {'b':10, 'c':'lee'}
foo(100,**obj)
# 100 10 lee
Другое использование идиомы *l - распаковать списки аргументов при вызове функции.
def foo(bar, lee):
print(bar, lee)
l = [1,2]
foo(*l)
# 1 2
В Python 3 можно использовать *l в левой части назначения (Расширенная итерируемая распаковка), хотя в этом контексте он дает список вместо кортежа:
first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]
Также Python 3 добавляет новую семантику (см. PEP 3102):
def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
pass
Такая функция принимает только 3 позиционных аргумента, и все, что находится после *, может быть передано только как аргументы ключевого слова.
Вывод [6] в обратном порядке. назови один возраст 27
@ thanos.a Python dicts, семантически используемые для передачи аргументов ключевого слова, упорядочены произвольно. Однако в Python 3.6 аргументы ключевого слова гарантированно запоминают порядок вставки. «Порядок элементов в **kwargs теперь соответствует порядку, в котором аргументы ключевого слова были переданы функции». - docs.python.org/3/whatsnew/3.6.html Фактически, все dicts в CPython 3.6 запоминают порядок вставки как деталь реализации, это становится стандартом в Python 3.7.
Очень точный, чистый и простой для понимания. Я ценю, что вы отметили, что это «оператор распаковки», чтобы я мог отличить передачу по ссылке от C. +1
Как проверить последнюю функцию с PEP 3102? Я вызываю его с помощью func (1,2,3, name = "me", age = 10), и он выдает исключение: got an unexpected keyword argument 'name'.
@KokHowTeh Вам нужно передать kwarg, названные так, как они есть в функции: func (1, 2, 3, kwarg1 = 'me', kwarg2 = 10)
Для тех, кто хочет исходную документацию, посмотрите PEP3102
Я был немного озадачен, когда впервые увидел синтаксис «единственная звезда» для обозначения конца позиционных параметров.
Синтаксис «одиночная звезда» может использоваться для того, чтобы заставить вызывающую функцию предоставлять аргументы только по ключевым словам.
См. здесь для КРАТКОГО обзора ВСЕХ ВОЗМОЖНЫХ сценариев.
Одиночный * означает, что может быть любое количество дополнительных позиционных аргументов. foo() можно вызывать как foo(1,2,3,4,5). В теле foo () param2 - это последовательность, содержащая 2-5.
Двойное ** означает, что может быть любое количество дополнительных именованных параметров. bar() можно вызывать как bar(1, a=2, b=3). В теле bar () param2 находится словарь, содержащий {'a': 2, 'b': 3}
Со следующим кодом:
def foo(param1, *param2):
print(param1)
print(param2)
def bar(param1, **param2):
print(param1)
print(param2)
foo(1,2,3,4,5)
bar(1,a=2,b=3)
выход
1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}
Возможно, для полноты ответа потребуется дополнительный пример с foobar(param1, *param2, **param3).
@AniketThakur добавил оставшуюся часть здесь.
Также стоит отметить, что вы также можете использовать * и ** при вызове функций. Это ярлык, который позволяет передавать несколько аргументов функции напрямую, используя список / кортеж или словарь. Например, если у вас есть следующая функция:
def foo(x,y,z):
print("x = " + str(x))
print("y = " + str(y))
print("z = " + str(z))
Вы можете делать что-то вроде:
>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3
>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3
>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3
Примечание: ключи в mydict должны быть названы точно так же, как параметры функции foo. В противном случае он выдаст TypeError:
>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'
См. здесь для КРАТКОГО обзора ВСЕХ ВОЗМОЖНЫХ сценариев.
* и ** имеют специальное использование в списке аргументов функции. *
подразумевает, что аргумент является списком, а ** подразумевает, что аргумент
это словарь. Это позволяет функциям принимать произвольное количество
аргументы
What does
**(double star) and*(star) do for parameters
Они позволяют для функции, которые должны быть определены для принятия и для пользователей передать любое количество аргументов, позиционных (*) и ключевых слов (**).
*args допускает любое количество необязательных позиционных аргументов (параметров), которые будут назначены кортежу с именем args.
**kwargs допускает любое количество необязательных аргументов ключевого слова (параметров), которые будут в dict с именем kwargs.
Вы можете (и должны) выбрать любое подходящее имя, но если намерение состоит в том, чтобы аргументы имели неспецифическую семантику, args и kwargs являются стандартными именами.
Вы также можете использовать *args и **kwargs для передачи параметров из списков (или любых повторяемых) и dicts (или любого сопоставления) соответственно.
Функция, получающая параметры, не должна знать, что они расширяются.
Например, xrange Python 2 явно не ожидает *args, но поскольку он принимает 3 целых числа в качестве аргументов:
>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x) # expand here
xrange(0, 2, 2)
В качестве другого примера мы можем использовать расширение dict в str.format:
>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'
У вас может быть аргументы только для ключевых слов после *args - например, здесь kwarg2 должен быть указан как аргумент ключевого слова, а не позиционно:
def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs):
return arg, kwarg, args, kwarg2, kwargs
Использование:
>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})
Кроме того, * может использоваться сам по себе, чтобы указать, что следуют только аргументы ключевого слова, без разрешения неограниченных позиционных аргументов.
def foo(arg, kwarg=None, *, kwarg2=None, **kwargs):
return arg, kwarg, kwarg2, kwargs
Здесь kwarg2 снова должен быть явно названным аргументом ключевого слова:
>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})
И мы больше не можем принимать неограниченное количество позиционных аргументов, потому что у нас нет *args*:
>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments
but 5 positional arguments (and 1 keyword-only argument) were given
Опять же, проще, здесь мы требуем, чтобы kwarg давался по имени, а не позиционно:
def bar(*, kwarg=None):
return kwarg
В этом примере мы видим, что если мы попытаемся передать kwarg позиционно, мы получим ошибку:
>>> bar('kwarg')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given
Мы должны явно передать параметр kwarg в качестве аргумента ключевого слова.
>>> bar(kwarg='kwarg')
'kwarg'
*args (обычно называется «звездные аргументы») и **kwargs (звезды могут подразумеваться, говоря «kwargs», но быть явным с «double-star kwargs») - общие идиомы Python для использования обозначений * и **. Эти конкретные имена переменных не требуются (например, вы можете использовать *foos и **bars), но отступление от соглашения может привести в ярость ваших коллег-программистов Python.
Обычно мы используем их, когда не знаем, что наша функция получит или сколько аргументов мы можем передать, а иногда даже при именовании каждой переменной по отдельности может быть очень беспорядочно и излишне (но это тот случай, когда обычно явно указывается лучше, чем неявный).
Пример 1
Следующая функция описывает, как их можно использовать, и демонстрирует поведение. Обратите внимание, что именованный аргумент b будет использоваться вторым позиционным аргументом перед:
def foo(a, b=10, *args, **kwargs):
'''
this function takes required argument a, not required keyword argument b
and any number of unknown positional arguments and keyword arguments after
'''
print('a is a required argument, and its value is {0}'.format(a))
print('b not required, its default value is 10, actual value: {0}'.format(b))
# we can inspect the unknown arguments we were passed:
# - args:
print('args is of type {0} and length {1}'.format(type(args), len(args)))
for arg in args:
print('unknown arg: {0}'.format(arg))
# - kwargs:
print('kwargs is of type {0} and length {1}'.format(type(kwargs),
len(kwargs)))
for kw, arg in kwargs.items():
print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
# But we don't have to know anything about them
# to pass them to other functions.
print('Args or kwargs can be passed without knowing what they are.')
# max can take two or more positional args: max(a, b, c...)
print('e.g. max(a, b, *args) \n{0}'.format(
max(a, b, *args)))
kweg = 'dict({0})'.format( # named args same as unknown kwargs
', '.join('{k} = {v}'.format(k=k, v=v)
for k, v in sorted(kwargs.items())))
print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
dict(**kwargs), kweg=kweg))
Мы можем проверить онлайн-справку на наличие сигнатуры функции с помощью help(foo), которая сообщает нам
foo(a, b=10, *args, **kwargs)
Назовем эту функцию с помощью foo(1, 2, 3, 4, e=5, f=6, g=7)
который печатает:
a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args)
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns:
{'e': 5, 'g': 7, 'f': 6}
Пример 2
Мы также можем вызвать его с помощью другой функции, в которую мы просто предоставляем a:
def bar(a):
b, c, d, e, f = 2, 3, 4, 5, 6
# dumping every local variable into foo as a keyword argument
# by expanding the locals dict:
foo(**locals())
bar(100) печатает:
a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args)
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns:
{'c': 3, 'e': 5, 'd': 4, 'f': 6}
Пример 3: практическое использование в декораторах
Хорошо, может быть, мы еще не видим эту утилиту. Итак, представьте, что у вас есть несколько функций с избыточным кодом до и / или после отличительного кода. Следующие ниже именованные функции представляют собой просто псевдокод для иллюстративных целей.
def foo(a, b, c, d=0, e=100):
# imagine this is much more code than a simple function call
preprocess()
differentiating_process_foo(a,b,c,d,e)
# imagine this is much more code than a simple function call
postprocess()
def bar(a, b, c=None, d=0, e=100, f=None):
preprocess()
differentiating_process_bar(a,b,c,d,e,f)
postprocess()
def baz(a, b, c, d, e, f):
... and so on
Мы могли бы справиться с этим по-другому, но мы, безусловно, можем извлечь избыточность с помощью декоратора, и поэтому наш нижеприведенный пример демонстрирует, как *args и **kwargs могут быть очень полезны:
def decorator(function):
'''function to wrap other functions with a pre- and postprocess'''
@functools.wraps(function) # applies module, name, and docstring to wrapper
def wrapper(*args, **kwargs):
# again, imagine this is complicated, but we only write it once!
preprocess()
function(*args, **kwargs)
postprocess()
return wrapper
И теперь каждая обернутая функция может быть написана гораздо лаконичнее, поскольку мы исключили избыточность:
@decorator
def foo(a, b, c, d=0, e=100):
differentiating_process_foo(a,b,c,d,e)
@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
differentiating_process_bar(a,b,c,d,e,f)
@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
differentiating_process_baz(a,b,c,d,e,f, g)
@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
differentiating_process_quux(a,b,c,d,e,f,g,h)
И, исключив наш код, что позволяет нам делать *args и **kwargs, мы сокращаем количество строк кода, улучшаем читаемость и ремонтопригодность и получаем единственные канонические места для логики в нашей программе. Если нам нужно изменить какую-либо часть этой структуры, у нас есть одно место для внесения каждого изменения.
Помимо вызовов функций, * args и ** kwargs полезны в иерархиях классов, а также позволяют избежать написания метода __init__ на Python. Подобное использование можно увидеть в таких фреймворках, как код Django.
Например,
def __init__(self, *args, **kwargs):
for attribute_name, value in zip(self._expected_attributes, args):
setattr(self, attribute_name, value)
if kwargs.has_key(attribute_name):
kwargs.pop(attribute_name)
for attribute_name in kwargs.viewkeys():
setattr(self, attribute_name, kwargs[attribute_name])
Тогда подкласс может быть
class RetailItem(Item):
_expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']
class FoodItem(RetailItem):
_expected_attributes = RetailItem._expected_attributes + ['expiry_date']
Затем подкласс будет создан как
food_item = FoodItem(name = 'Jam',
price = 12.0,
category = 'Foods',
country_of_origin = 'US',
expiry_date = datetime.datetime.now())
Кроме того, подкласс с новым атрибутом, который имеет смысл только для этого экземпляра подкласса, может вызвать базовый класс __init__, чтобы разгрузить настройку атрибутов.
Это делается через * args и ** kwargs. kwargs в основном используется для чтения кода с использованием именованных аргументов. Например,
class ElectronicAccessories(RetailItem):
_expected_attributes = RetailItem._expected_attributes + ['specifications']
# Depend on args and kwargs to populate the data as needed.
def __init__(self, specifications = None, *args, **kwargs):
self.specifications = specifications # Rest of attributes will make sense to parent class.
super(ElectronicAccessories, self).__init__(*args, **kwargs)
который может быть установлен как
usb_key = ElectronicAccessories(name = 'Sandisk',
price = '.00',
category = 'Electronics',
country_of_origin = 'CN',
specifications = '4GB USB 2.0/USB 3.0')
Полный код - здесь
1. По сути, в этом - это метод, поэтому (в данном контексте) он не отличается. 2. Используйте # для комментариев, а не "", который просто отмечает буквальные строки 3. Использование super должно быть предпочтительным способом, особенно для вашего примера с многоуровневым наследованием.
В Python 3.5 вы также можете использовать этот синтаксис в дисплеях list, dict, tuple и set (также иногда называемых литералами). См. PEP 488: Дополнительные обобщения распаковки.
>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}
Это также позволяет распаковывать несколько итераций за один вызов функции.
>>> range(*[1, 10], *[2])
range(1, 10, 2)
(Спасибо mgilson за ссылку на PEP.)
Я не уверен, что это нарушение принципа «есть только один способ сделать это». Нет другого способа инициализировать список / кортеж из нескольких итераций - в настоящее время вам нужно связать их в одну итерацию, что не всегда удобно. О рациональном можно прочитать в PEP-0448. Кроме того, это не функция python3.x, это функция python3.5 + :-).
@mgilson, это объясняет, почему об этом не упоминалось раньше.
Давайте сначала разберемся, что такое позиционные аргументы и аргументы ключевого слова. Ниже приведен пример определения функции с Позиционные аргументы.
def test(a,b,c):
print(a)
print(b)
print(c)
test(1,2,3)
#output:
1
2
3
Итак, это определение функции с позиционными аргументами. Вы также можете вызвать его с ключевым словом / именованными аргументами:
def test(a,b,c):
print(a)
print(b)
print(c)
test(a=1,b=2,c=3)
#output:
1
2
3
Теперь рассмотрим пример определения функции с помощью аргументы ключевого слова:
def test(a=0,b=0,c=0):
print(a)
print(b)
print(c)
print('-------------------------')
test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------
Вы также можете вызвать эту функцию с позиционными аргументами:
def test(a=0,b=0,c=0):
print(a)
print(b)
print(c)
print('-------------------------')
test(1,2,3)
# output :
1
2
3
---------------------------------
Итак, теперь мы знаем определения функций как с позиционными, так и с ключевыми аргументами.
Теперь давайте изучим оператор «*» и оператор «**».
Обратите внимание, что эти операторы могут использоваться в 2-х областях:
а) вызов функции
б) определение функции
Использование оператора '*' и оператора '**' в вызов функции.
Давайте сразу перейдем к примеру, а затем обсудим его.
def sum(a,b): #receive args from function calls as sum(1,2) or sum(a=1,b=2)
print(a+b)
my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}
# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple) # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list) # becomes same as sum(1,2) after unpacking my_list with '*'
sum(**my_dict) # becomes same as sum(a=1,b=2) after unpacking by '**'
# output is 3 in all three calls to sum function.
Так что помни
когда оператор '*' или '**' используется в вызов функции -
Оператор '*' распаковывает структуру данных, такую как список или кортеж, в аргументы, необходимые для определения функции.
Оператор ** распаковывает словарь в аргументы, необходимые для определения функции.
Теперь давайте изучим использование оператора '*' в определение функции. Пример:
def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
sum = 0
for a in args:
sum+=a
print(sum)
sum(1,2,3,4) #positional args sent to function sum
#output:
10
В функции определение оператор '*' упаковывает полученные аргументы в кортеж.
Теперь давайте посмотрим на пример использования '**' в определении функции:
def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
sum=0
for k,v in args.items():
sum+=v
print(sum)
sum(a=1,b=2,c=3,d=4) #positional args sent to function sum
В функции определение оператор '**' упаковывает полученные аргументы в словарь.
Так что помните:
В вызов функции структура данных '*' распаковывает кортежа или списка в позиционные или ключевые аргументы, которые должны быть получены определением функции.
В вызов функции структура данных словаря '**' распаковывает в позиционные или ключевые аргументы, которые должны быть получены определением функции.
В определение функции позиционные аргументы '*' пакеты в кортеж.
В определение функции аргументы ключевого слова '**' пакеты в словарь.
Действительно чистое, пошаговое и понятное объяснение!
спасибо. Продолжайте получать положительные голоса. [Также для дальнейших заметок от меня, я на @mrtechmaker в твиттере]
Хороший пример использования обоих в функции:
>>> def foo(*arg,**kwargs):
... print arg
... print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b)
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b)
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}
Я хочу привести пример, о котором не упоминали другие
* также можно распаковать генератор
Пример из документа Python3
x = [1, 2, 3]
y = [4, 5, 6]
unzip_x, unzip_y = zip(*zip(x, y))
unzip_x будет [1, 2, 3], unzip_y будет [4, 5, 6]
Zip () получает несколько аргументов iretable и возвращает генератор.
zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
unzip_x будет (1, 2, 3), а не [1, 2, 3]. То же самое и с unzip_y
Этот пример поможет вам сразу вспомнить *args, **kwargs и даже super и наследование в Python.
class base(object):
def __init__(self, base_param):
self.base_param = base_param
class child1(base): # inherited from base class
def __init__(self, child_param, *args) # *args for non-keyword args
self.child_param = child_param
super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg
class child2(base):
def __init__(self, child_param, **kwargs):
self.child_param = child_param
super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg
c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1
Эта таблица удобна для использования * и ** в функциях строительство и вызов:
In function construction In function call
=======================================================================
| def f(*args): | def f(a, b):
*args | for arg in args: | return a + b
| print(arg) | args = (1, 2)
| f(1, 2) | f(*args)
----------|--------------------------------|---------------------------
| def f(a, b): | def f(a, b):
**kwargs | return a + b | return a + b
| def g(**kwargs): | kwargs = dict(a=1, b=2)
| return f(**kwargs) | f(**kwargs)
| g(a=1, b=2) |
-----------------------------------------------------------------------
На самом деле это просто обобщение отвечать Лорина Хохштейна, но я считаю его полезным.
В связи с этим: использование операторов star / splat было расширенный в Python 3
*args и **kwargs: позволяют передавать функции переменное количество аргументов.
*args: используется для отправки в функцию списка аргументов переменной длины без ключевых слов:
def args(normal_arg, *argv):
print("normal argument:", normal_arg)
for arg in argv:
print("Argument in list of arguments from *argv:", arg)
args('animals', 'fish', 'duck', 'bird')
Изготовим:
normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird
**kwargs*
**kwargs позволяет передавать в функцию аргументы переменной длины с указанием ключевых слов. Вам следует использовать **kwargs, если вы хотите обрабатывать именованные аргументы в функции.
def who(**kwargs):
if kwargs is not None:
for key, value in kwargs.items():
print("Your %s is %s." % (key, value))
who(name = "Nikola", last_name = "Tesla", birthday = "7.10.1856", birthplace = "Croatia")
Изготовим:
Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
* - дать вам возможность определить функцию, которая может принимать произвольное количество аргументов, представленных в виде списка (например, f(*myList)).** - дать вам возможность передавать аргументы функции, предоставляя словарь (например, f(**{'x' : 1, 'y' : 2})).Давайте покажем это, определив функцию, которая принимает две обычные переменные x, y, и может принимать больше аргументов как myArgs, и может принимать еще больше аргументов как myKW. Позже мы покажем, как кормить y с помощью myArgDict.
def f(x, y, *myArgs, **myKW):
print("# x = {}".format(x))
print("# y = {}".format(y))
print("# myArgs = {}".format(myArgs))
print("# myKW = {}".format(myKW))
print("# ----------------------------------------------------------------------")
# Define a list for demonstration purposes
myList = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}
# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x = myEx
# y = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------
# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x = myEx
# y = Why?
# myArgs = ()
# myKW = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------
# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x = myEx
# y = y
# myArgs = ('y0', 'q')
# myKW = {}
# ----------------------------------------------------------------------
# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x = myEx
# y = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------
# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x = ['Left', 'Right', 'Up', 'Down']
# y = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW = {}
# ----------------------------------------------------------------------
** предназначен исключительно для словарей.** всегда должен идти после *.* означает получение переменных аргументов в виде кортежа
** означает получение переменных аргументов в виде словаря
Используется следующим образом:
1) одиночный *
def foo(*args):
for arg in args:
print(arg)
foo("two", 3)
Выход:
two
3
2) Теперь **
def bar(**kwargs):
for key in kwargs:
print(key, kwargs[key])
bar(dic1 = "two", dic2=3)
Выход:
dic1 two
dic2 3
def foo(param1, *param2): - это метод, который может принимать произвольное количество значений для *param2,def bar(param1, **param2): - это метод, который может принимать произвольное количество значений с ключами для *param2param1 - простой параметр.Например, синтаксис для реализации varargs в Java выглядит следующим образом:
accessModifier methodName(datatype… arg) {
// method body
}
Он упаковывает аргументы, переданные в функцию, в list и dict соответственно внутри тела функции. Когда вы определяете сигнатуру функции следующим образом:
def func(*args, **kwds):
# do stuff
его можно вызвать с любым количеством аргументов и аргументов ключевого слова. Аргументы, не являющиеся ключевыми словами, упаковываются в список с именем args внутри тела функции, а аргументы ключевого слова упаковываются в dict с именем kwds внутри тела функции.
func("this", "is a list of", "non-keyowrd", "arguments", keyword = "ligma", options=[1,2,3])
теперь внутри тела функции, когда функция вызывается, есть две локальные переменные, args, который представляет собой список со значением ["this", "is a list of", "non-keyword", "arguments"], и kwds, который является dict со значением {"keyword" : "ligma", "options" : [1,2,3]}
Это также работает в обратном порядке, то есть со стороны вызывающего абонента. например, если у вас есть функция, определенная как:
def f(a, b, c, d=1, e=10):
# do stuff
вы можете вызвать его, распаковав итерации или сопоставления, которые есть в вызывающей области:
iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)
Основываясь на никде отвечать ...
def foo(param1, *param2):
print(param1)
print(param2)
def bar(param1, **param2):
print(param1)
print(param2)
def three_params(param1, *param2, **param3):
print(param1)
print(param2)
print(param3)
foo(1, 2, 3, 4, 5)
print("\n")
bar(1, a=2, b=3)
print("\n")
three_params(1, 2, 3, 4, s=5)
Выход:
1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}
1
(2, 3, 4)
{'s': 5}
По сути, любое количество позиционные аргументы может использовать * args, а любое именованные аргументы (или kwargs, также известное как аргументы ключевого слова) может использовать ** kwargs.
**В дополнение к ответам в этой ветке есть еще одна деталь, которая больше нигде не упоминалась. Это расширяет ответ Брэда Соломона
Распаковка с помощью ** также полезна при использовании python str.format.
Это несколько похоже на то, что вы можете сделать с python f-stringsф-струна, но с дополнительными накладными расходами на объявление dict для хранения переменных (f-строка не требует dict).
## init vars
ddvars = dict()
ddcalc = dict()
pass
ddvars['fname'] = 'Huomer'
ddvars['lname'] = 'Huimpson'
ddvars['motto'] = 'I love donuts!'
ddvars['age'] = 33
pass
ddcalc['ydiff'] = 5
ddcalc['ycalc'] = ddvars['age'] + ddcalc['ydiff']
pass
vdemo = []
## ********************
## single unpack supported in py 2.7
vdemo.append('''
Hello {fname} {lname}!
Today you are {age} years old!
We love your motto "{motto}" and we agree with you!
'''.format(**ddvars))
pass
## ********************
## multiple unpack supported in py 3.x
vdemo.append('''
Hello {fname} {lname}!
In {ydiff} years you will be {ycalc} years old!
'''.format(**ddvars,**ddcalc))
pass
## ********************
print(vdemo[-1])
TL; DR
Ниже приведены 6 различных вариантов использования * и ** в программировании на Python:
*args:def foo(*args): pass, здесь foo принимает любое количество позиционных аргументов, т.е. е., следующие вызовы действительны foo(1), foo(1, 'bar')**kwargs:def foo(**kwargs): pass, здесь 'foo' принимает любое количество аргументов ключевого слова, т.е. е., следующие вызовы действительны foo(name='Tom'), foo(name='Tom', age=33)*args, **kwargs:def foo(*args, **kwargs): pass, здесь foo принимает любое количество позиционных аргументов и аргументов ключевого слова, т.е. е., следующие вызовы действительны foo(1,name='Tom'), foo(1, 'bar', name='Tom', age=33)*:def foo(pos1, pos2, *, kwarg1): pass, здесь * означает, что foo принимает аргументы ключевого слова только после pos2, следовательно, foo(1, 2, 3) вызывает TypeError, но foo(1, 2, kwarg1=3) в порядке.*_ (Примечание: это только соглашение):def foo(bar, baz, *_): pass означает (по соглашению), что foo использует в своей работе только аргументы bar и baz и игнорирует другие.\**_ (Примечание: это только соглашение):def foo(bar, baz, **_): pass означает (по соглашению), что foo использует в своей работе только аргументы bar и baz и игнорирует другие.БОНУС: Начиная с python 3.8 и далее, можно использовать / в определении функции для принудительного применения только позиционных параметров. В следующем примере параметры a и b - это только позиционный, в то время как c или d могут быть позиционными или ключевыми, а e или f должны быть ключевыми словами:
def f(a, b, /, c, d, *, e, f):
pass
Учитывая функцию, которая имеет 3 элемента в качестве аргумента
sum = lambda x, y, z: x + y + z
sum(1,2,3) # sum 3 items
sum([1,2,3]) # error, needs 3 items, not 1 list
x = [1,2,3][0]
y = [1,2,3][1]
z = [1,2,3][2]
sum(x,y,z) # ok
sum(*[1,2,3]) # ok, 1 list becomes 3 items
Представьте себе эту игрушку с сумкой из треугольника, круга и прямоугольника. Эта сумка не подходит. Вам нужно распаковать сумку, чтобы взять эти 3 предмета, и теперь они подходят. Оператор Python * выполняет этот процесс распаковки.
см. также stackoverflow.com/questions/6967632/…