Как передать dict как позиционный аргумент, а не как аргумент ключевого слова - PullRequest
0 голосов
/ 05 июня 2018

Я создал функцию (send_to_api), которая принимает три аргумента.user_id и event_type принимают строки, а event_properties принимает словарь, который я передаю в качестве позиционного аргумента.Это формат, который требуется для внешнего API.Вот упрощенная версия функции:

def send_to_api(user_id, event_type, *args):

    event_args = {"user_id": user_id,
              "event_type": event_type,
              "event_properties": args}

    data = json.dumps(event_args)
    r = requests.post(url=url, data=data)

В другом месте функция вызывается так:

event_properties = {"property_1": "a", "property_whatever": "b"}

send_to_api("my_user_id", "my_event", event_properties)

После ознакомления с * args и ** kwargs я все ещекажется, что-то делает не так, потому что dict event_properties не проходит через.

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

Ответы [ 4 ]

0 голосов
/ 05 июня 2018

* args и ** kwargs предназначены для обеспечения возможности передачи переменной числа аргументов в функцию.Прежде чем использовать их, вам необходимо знать, нужен ли вам keyworded аргумент или non-keyworded аргументы.

В вашем случае вы используете аргумент на основе ключевого слова, поэтому вам нужно изменить его на **kwargs

def test_arg_kwargs(arg1, arg2, **kwargs):
    print("arg1:", arg1)
    print("arg2:", arg2)
    print("arg3:", kwargs)


event_properties = {"property_1": "a", "property_whatever": "b"}

test_arg_kwargs('arg1', 'arg2', **event_properties)

вывод:

arg1: arg1
arg2: arg2
arg3: {'property_1': 'a', 'property_whatever': 'b'}
0 голосов
/ 05 июня 2018

Вы должны использовать распаковку dict следующим образом:

send_to_api("my_user_id", "my_event", **event_properties)

Подробнее об этом здесь .

0 голосов
/ 05 июня 2018

Для лучшего понимания вы можете просто отладить вашу send_to_api функцию.Короче говоря:

  1. * args используется для отправки списка аргументов переменной длины без ключа в функцию

    def send_to_api(param1, param2, *args):
        print(param1, param2, args)
    

Если вызатем вызовите вашу функцию и передайте после param1, param2 любое количество позиционных аргументов, которые вы можете получить к ним внутри функции в args кортеже.Итак, в вашем примере с вопросом ваш dict находится внутри args variable.

    send_to_api(1,2, {"a":1, "b":2})
    ...
    1 2 ({'a': 1, 'b': 2},)

И вы можете получить к нему доступ как args [0] , так что ваш код может выглядеть следующим образом:

    def send_to_api(user_id, event_type, *args):
        event_args = {"user_id": user_id,
                      "event_type": event_type,
                      "event_properties": args[0]}

Но, вероятно, будет лучше, если вы сможете сменить подпись на что-то вроде этого:

    def send_to_api(user_id, event_type, event_properties, *args):
        event_args = {"user_id": user_id,
                      "event_type": event_type,
                      "event_properties": event_properties}

Что касается меня, то она намного чище;)

Если вынеобходимо обработать любое количество позиционных аргументов - используйте * args в определении функции, тогда вы можете получить к ним доступ в args кортеже внутри функции.

Если вам нужно обработать любое количество аргументов с ключевыми словами -используйте ** kwargs в определении функции, затем внутри функции вы можете получить к ним доступ в словаре kwargs.

, например:

def send_to_api(arg1, *args, **kwargs):
    print(arg1, args, kwargs)

, затем вы можете вызвать функцию с помощью:

 send_to_api(1, 2 , key1=1, key2=2)

будет напечатано:

 1 (2,) {'key1': 1, 'key2': 2}

, чтобы вы могли видеть, что args - это кортеж (2,); kwargs - это словарь {'key1': 1, 'key2': 2}

Также вы можете передать kwargs функции как словарь с оператором распаковки:

  send_to_api(1, 2, **{'key1': 1, 'key2': 2})

он напечатает то же самое:

   1 (2,) {'a': 1, 'b': 2}

Таким образом, словарь {'key1': 1, 'key2': 2} был распакован с оператором ** для key1 = 1, key2 = 2 аргументов ключевого слова идоступно внутри вашей функции в kwargs dict.

Там нет магии, просто попробуйте поиграть в интерактивной консоли python.

0 голосов
/ 05 июня 2018

с одним * это будет кортеж, но с двумя ** будет словарь

def send_to_api(user_id, event_type, **args):
...
...
send_to_api("my_user_id", "my_event", **event_properties)

некоторые полезные документы

Вывод

{
 "user_id": "my_user_id", 
 "event_type": "my_event", 
 "event_properties": {
                       "property_1": "a", 
                       "property_whatever": "b"
                      }
}
...