Правильный способ использования ** kwargs в Python

Я добавил проверку нулевых значений в JSON на другой ответ

У меня была такая же проблема, поэтому я написал это сам. Это решение отличается от других ответов, поскольку оно может десериализоваться на нескольких уровнях.

Просто отправьте строку json в функцию deserializeToDictionary , она вернет не строго типизированный объект Dictionary<string, object> .

private Dictionary<string, object> deserializeToDictionary(string jo)
{
    var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(jo);
    var values2 = new Dictionary<string, object>();
    foreach (KeyValuePair<string, object> d in values)
    {
        if (d.Value != null && d.Value.GetType().FullName.Contains("Newtonsoft.Json.Linq.JObject"))
        {
            values2.Add(d.Key, deserializeToDictionary(d.Value.ToString()));
        }
        else
        {
            values2.Add(d.Key, d.Value);
        }
    }
    return values2;
}

Ex: Это вернет объект Dictionary<string, object> ответа JSON в Facebook.

private void button1_Click(object sender, EventArgs e)
{
    string responsestring = "{\"id\":\"721055828\",\"name\":\"Dasun Sameera
        Weerasinghe\",\"first_name\":\"Dasun\",\"middle_name\":\"Sameera\",\"last_name\":\"Weerasinghe\",\"username\":\"dasun\",\"gender\":\"male\",\"locale\":\"en_US\",
        hometown: {id: \"108388329191258\", name: \"Moratuwa, Sri Lanka\",}}";
    Dictionary<string, object> values = deserializeToDictionary(responsestring);
}

Примечание: родной город далее десериализуется в объект Dictionary<string, object>.

396
задан SilentGhost 8 July 2009 в 14:53
поделиться

7 ответов

Вы можете передать значение по умолчанию get () для ключей, которых нет в словаре:

self.val2 = kwargs.get('val2',"default value")

Однако, если вы планируете использовать определенный аргумент с конкретное значение по умолчанию, почему бы не использовать в первую очередь именованные аргументы?

def __init__(self, val2="default value", **kwargs):
430
ответ дан 22 November 2019 в 23:28
поделиться

Я предлагаю что-то вроде этого

def testFunc( **kwargs ):
    options = {
            'option1' : 'default_value1',
            'option2' : 'default_value2',
            'option3' : 'default_value3', }

    options.update(kwargs)
    print options

testFunc( option1='new_value1', option3='new_value3' )
# {'option2': 'default_value2', 'option3': 'new_value3', 'option1': 'new_value1'}

testFunc( option2='new_value2' )
# {'option1': 'default_value1', 'option3': 'default_value3', 'option2': 'new_value2'}

А затем используйте значения так, как хотите.

dictionaryA.update (dictionaryB) добавляет содержимое dictionaryB в dictionaryA перезапись любых повторяющихся ключей.

68
ответ дан 22 November 2019 в 23:28
поделиться

While most answers are saying that, e.g.,

def f(**kwargs):
    foo = kwargs.pop('foo')
    bar = kwargs.pop('bar')
    ...etc...

is "the same as"

def f(foo=None, bar=None, **kwargs):
    ...etc...

this is not true. In the latter case, f can be called as f(23, 42), while the former case accepts named arguments only -- no positional calls. Often you want to allow the caller maximum flexibility and therefore the second form, as most answers assert, is preferable: but that is not always the case. When you accept many optional parameters of which typically only a few are passed, it may be an excellent idea (avoiding accidents and unreadable code at your call sites!) to force the use of named arguments -- threading.Thread is an example. The first form is how you implement that in Python 2.

The idiom is so important that in Python 3 it now has special supporting syntax: every argument after a single * in the def signature is keyword-only, that is, cannot be passed as a positional argument, but only as a named one. So in Python 3 you could code the above as:

def f(*, foo=None, bar=None, **kwargs):
    ...etc...

Indeed, in Python 3 you can even have keyword-only arguments that aren't optional (ones without a default value).

However, Python 2 still has long years of productive life ahead, so it's better to not forget the techniques and idioms that let you implement in Python 2 important design ideas that are directly supported in the language in Python 3!

260
ответ дан 22 November 2019 в 23:28
поделиться

Вы бы сделали

self.attribute = kwargs.pop('name', default_value)

или

self.attribute = kwargs.get('name', default_value)

Если вы используете pop , тогда вы можете проверить, не отправлены ли какие-либо ложные значения, и предпринять соответствующие действия ( если есть).

53
ответ дан 22 November 2019 в 23:28
поделиться

Использовать ** kwargs и значения по умолчанию очень просто. Иногда, однако, вам вообще не следует использовать ** kwargs.

В данном случае мы не очень хорошо используем ** kwargs.

class ExampleClass( object ):
    def __init__(self, **kwargs):
        self.val = kwargs.get('val',"default1")
        self.val2 = kwargs.get('val2',"default2")

Вышеупомянутый вопрос - «зачем беспокоиться?» декларация. Это то же самое, что и

class ExampleClass( object ):
    def __init__(self, val="default1", val2="default2"):
        self.val = val
        self.val2 = val2

. Когда вы используете ** kwargs, вы имеете в виду, что ключевое слово не просто необязательно, а условно. Существуют более сложные правила, чем простые значения по умолчанию.

Когда вы используете ** kwargs, вы обычно имеете в виду что-то вроде следующего, где простые значения по умолчанию не применяются.

class ExampleClass( object ):
    def __init__(self, **kwargs):
        self.val = "default1"
        self.val2 = "default2"
        if "val" in kwargs:
            self.val = kwargs["val"]
            self.val2 = 2*self.val
        elif "val2" in kwargs:
            self.val2 = kwargs["val2"]
            self.val = self.val2 / 2
        else:
            raise TypeError( "must provide val= or val2= parameter values" )
40
ответ дан 22 November 2019 в 23:28
поделиться

Вы можете сделать что-то вроде этого

class ExampleClass:
    def __init__(self, **kwargs):
        arguments = {'val':1, 'val2':2}
        arguments.update(kwargs)
        self.val = arguments['val']
        self.val2 = arguments['val2']
11
ответ дан 22 November 2019 в 23:28
поделиться

Вот еще один подход:

def my_func(arg1, arg2, arg3):
    ... so something ...

kwargs = {'arg1': 'Value One', 'arg2': 'Value Two', 'arg3': 'Value Three'}
# Now you can call the function with kwargs like this:

my_func(**kwargs)
14
ответ дан 22 November 2019 в 23:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: