10 ответов:
можно использовать
**kwargsчтобы ваши функции принимали произвольное количество аргументов ключевых слов ("kwargs" означает "аргументы ключевых слов"):>>> def print_keyword_args(**kwargs): ... # kwargs is a dict of the keyword args passed to the function ... for key, value in kwargs.iteritems(): ... print "%s = %s" % (key, value) ... >>> print_keyword_args(first_name="John", last_name="Doe") first_name = John last_name = Doeвы также можете использовать
**kwargsсинтаксис при вызове функций путем построения словаря аргументов ключевых слов и передачи его в функцию:>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'} >>> print_keyword_args(**kwargs) first_name = Bobby last_name = SmithThe Python Tutorial содержит хорошее объяснение, как это работает, наряду с некоторыми хорошими примерами.
для люди, использующие Python 3, вместо iteritems (), используют items ()
распаковка словари
**распаковывает словари.этой
func(a=1, b=2, c=3)это то же самое, что
args = {'a': 1, 'b': 2, 'c':3} func(**args)это полезно, если вам нужно построить параметры:
args = {'name': person.name} if hasattr(person, "address"): args["address"] = person.address func(**args) # either expanded to func(name=person.name) or # func(name=person.name, address=person.address)параметры упаковки функции
def setstyle(**styles): for key, value in styles.iteritems(): # styles is a regular dictionary setattr(someobject, key, value)это позволяет использовать функцию следующим образом:
setstyle(color="red", bold=False)
kwargs-это просто словарь, который добавляется к параметрам.
словарь может содержать пары ключ, значение. А это-кварги. Хорошо, вот как.
В какой не так просто.
например (очень гипотетический) у вас есть интерфейс, который просто вызывает другие процедуры для выполнения задания:
def myDo(what, where, why): if what == 'swim': doSwim(where, why) elif what == 'walk': doWalk(where, why) ...Теперь вы получаете новый метод "диск":
elif what == 'drive': doDrive(where, why, vehicle)но подождите минутку, есть новый параметр "транспортное средство" -- вы не знали это было раньше. Теперь вы должны добавить его в подпись myDo-функция.
здесь вы можете бросить кварги в игру - вы просто добавляете кварги к подписи:
def myDo(what, where, why, **kwargs): if what == 'drive': doDrive(where, why, **kwargs) elif what == 'swim': doSwim(where, why, **kwargs)таким образом, вам не нужно менять подпись вашей функции интерфейса каждый раз, когда некоторые из ваших вызываемых подпрограмм могут измениться.
Это всего лишь один хороший пример, который вы могли бы найти kwargs полезным.
на основании того, что хороший образец иногда лучше, чем длинный дискурс, я напишу две функции, используя все средства передачи аргументов переменных python (как позиционные, так и именованные аргументы). Вы должны легко увидеть, что он делает самостоятельно:
def f(a = 0, *args, **kwargs): print("Received by f(a, *args, **kwargs)") print("=> f(a=%s, args=%s, kwargs=%s" % (a, args, kwargs)) print("Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)") g(10, 11, 12, *args, d = 13, e = 14, **kwargs) def g(f, g = 0, *args, **kwargs): print("Received by g(f, g = 0, *args, **kwargs)") print("=> g(f=%s, g=%s, args=%s, kwargs=%s)" % (f, g, args, kwargs)) print("Calling f(1, 2, 3, 4, b = 5, c = 6)") f(1, 2, 3, 4, b = 5, c = 6)и вот результат:
Calling f(1, 2, 3, 4, b = 5, c = 6) Received by f(a, *args, **kwargs) => f(a=1, args=(2, 3, 4), kwargs={'c': 6, 'b': 5} Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs) Received by g(f, g = 0, *args, **kwargs) => g(f=10, g=11, args=(12, 2, 3, 4), kwargs={'c': 6, 'b': 5, 'e': 14, 'd': 13})
мотив:
*argsи**kwargsслужит в качестве заполнителя для аргументов, которые должны быть переданы вызову функциииспользуя
*argsи**kwargsдля вызова функцииdef args_kwargs_test(arg1, arg2, arg3): print "arg1:", arg1 print "arg2:", arg2 print "arg3:", arg3теперь мы будем использовать
*argsдля вызова указанной выше функции#args can either be a "list" or "tuple" >>> args = ("two", 3, 5) >>> args_kwargs_test(*args)результат:
arg1: два
arg2: 3
arg3: 5
теперь, используя
**kwargsчтобы вызвать то же самое функция#keyword argument "kwargs" has to be a dictionary >>> kwargs = {"arg3":3, "arg2":'two', "arg1":5} >>> args_kwargs_test(**kwargs)результат:
arg1: 5
аргумент2: два
arg3: 3Bottomline:
*argsне имеет интеллекта, он просто интерполирует переданные args к параметрам (в порядке слева направо) в то время как**kwargsведет себя разумно, помещая соответствующее значение @ необходимое место
kwargsна**kwargs- это просто имя переменной. Вы можете очень хорошо иметь**anyVariableNamekwargsозначает "ключевые аргументы". Но я считаю, что их лучше называть "именованными аргументами", поскольку это просто аргументы, передаваемые вместе с именами (я не нахожу никакого значения слову" ключевое слово "в термине"ключевые аргументы". Я предполагаю, что "ключевое слово" обычно означает слова, зарезервированные языком программирования и, следовательно, не используемые программистом для имен переменных. Нет такое происходит здесь в случае с кваргами.). Поэтому мы даем именаparam1иparam2для двух значений параметров, передаваемых в функцию следующим образом:func(param1="val1",param2="val2"), вместо того, чтобы принимать только значения:func(val1,val2). Таким образом, я считаю, что они должны быть соответствующим образом названы "произвольное число именованных аргументов" как мы можем указать любое количество этих параметров (аргументов) еслиfuncподписьfunc(**kwargs)так говорят, что позвольте мне объяснить "именованные аргументы" сначала и затем "произвольное количество именованных аргументов"
kwargs.именованные аргументы
- именованные Арги должны следовать за позиционными аргами
- порядок именованных аргументов не важен
пример
def function1(param1,param2="arg2",param3="arg3"): print("\n"+str(param1)+" "+str(param2)+" "+str(param3)+"\n") function1(1) #1 arg2 arg3 #1 positional arg function1(param1=1) #1 arg2 arg3 #1 named arg function1(1,param2=2) #1 2 arg3 #1 positional arg, 1 named arg function1(param1=1,param2=2) #1 2 arg3 #2 named args function1(param2=2, param1=1) #1 2 arg3 #2 named args out of order function1(1, param3=3, param2=2) #1 2 3 # #function1() #invalid: required argument missing #function1(param2=2,1) #invalid: SyntaxError: non-keyword arg after keyword arg #function1(1,param1=11) #invalid: TypeError: function1() got multiple values for argument 'param1' #function1(param4=4) #invalid: TypeError: function1() got an unexpected keyword argument 'param4'произвольное количество именованных аргументов
kwargs
- последовательность параметров функции:
- позиционные параметры
- формальный параметр, фиксирующий произвольное количество аргументов (с префиксом *)
- именованные формальные параметры
- формальный параметр захват произвольного количества именованных параметров (с префиксом **)
пример
def function2(param1, *tupleParams, param2, param3, **dictionaryParams): print("param1: "+ param1) print("param2: "+ param2) print("param3: "+ param3) print("custom tuple params","-"*10) for p in tupleParams: print(str(p) + ",") print("custom named params","-"*10) for k,v in dictionaryParams.items(): print(str(k)+":"+str(v)) function2("arg1", "custom param1", "custom param2", "custom param3", param3="arg3", param2="arg2", customNamedParam1 = "val1", customNamedParam2 = "val2" ) # Output # #param1: arg1 #param2: arg2 #param3: arg3 #custom tuple params ---------- #custom param1, #custom param2, #custom param3, #custom named params ---------- #customNamedParam2:val2 #customNamedParam1:val1передача переменных кортежа и dict для пользовательских args
чтобы закончить, позвольте мне также отметить, что мы можем пройти
- "формальный параметр, фиксирующий произвольное количество аргументов" в качестве переменной кортежа и
- "формальный параметр, фиксирующий произвольное количество именованных параметров" как переменная dict
таким образом, тот же самый вызов выше может быть сделан следующим образом:
tupleCustomArgs = ("custom param1", "custom param2", "custom param3") dictCustomNamedArgs = {"customNamedParam1":"val1", "customNamedParam2":"val2"} function2("arg1", *tupleCustomArgs, #note * param3="arg3", param2="arg2", **dictCustomNamedArgs #note ** )наконец, обратите внимание
*и**в вызовы функций выше. Если мы опустим их, мы можем получить плохие результаты.опущение
*в кортеж аргументы:function2("arg1", tupleCustomArgs, #omitting * param3="arg3", param2="arg2", **dictCustomNamedArgs )печать
param1: arg1 param2: arg2 param3: arg3 custom tuple params ---------- ('custom param1', 'custom param2', 'custom param3'), custom named params ---------- customNamedParam2:val2 customNamedParam1:val1выше кортежа!--22--> печатается как есть.
опущение
dictargs:function2("arg1", *tupleCustomArgs, param3="arg3", param2="arg2", dictCustomNamedArgs #omitting ** )дает
dictCustomNamedArgs ^ SyntaxError: non-keyword arg after keyword arg
кроме того, вы также можете смешивать различные способы использования при вызове функций kwargs:
def test(**kwargs): print kwargs['a'] print kwargs['b'] print kwargs['c'] args = { 'b': 2, 'c': 3} test( a=1, **args )дает этот выход:
1 2 3обратите внимание, что **kwargs должен быть последним аргументом
kwargs являются синтаксическим сахаром для передачи аргументов имя как словари(для функций), или словари как именованные аргументы(с изм)
вот простая функция, которая служит для объяснения использования:
def print_wrap(arg1, *args, **kwargs): print(arg1) print(args) print(kwargs) print(arg1, *args, **kwargs)любые аргументы, которые не указанное в определении функции будет помещено в
argsиkwargsсписок, в зависимости от того, являются ли они аргументами сайта или нет:>>> print_wrap('one', 'two', 'three', end='blah', sep='--') one ('two', 'three') {'end': 'blah', 'sep': '--'} one--two--threeblahесли вы добавите аргумент ключевого слова, который никогда не передается функции, будет вызвана ошибка:
>>> print_wrap('blah', dead_arg='anything') TypeError: 'dead_arg' is an invalid keyword argument for this function
вот пример, который я надеюсь поможет:
#! /usr/bin/env python # def g( **kwargs) : print ( "In g ready to print kwargs" ) print kwargs print ( "in g, calling f") f ( **kwargs ) print ( "In g, after returning from f") def f( **kwargs ) : print ( "in f, printing kwargs") print ( kwargs ) print ( "In f, after printing kwargs") g( a="red", b=5, c="Nassau") g( q="purple", w="W", c="Charlie", d=[4, 3, 6] )когда вы запускаете программу, вы получаете:
$ python kwargs_demo.py In g ready to print kwargs {'a': 'red', 'c': 'Nassau', 'b': 5} in g, calling f in f, printing kwargs {'a': 'red', 'c': 'Nassau', 'b': 5} In f, after printing kwargs In g, after returning from f In g ready to print kwargs {'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'} in g, calling f in f, printing kwargs {'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'} In f, after printing kwargs In g, after returning from f
Comments