сопоставление аргументов, переданных функции в локальное пространство имен, используя ** kwargs? - PullRequest
0 голосов
/ 29 ноября 2018

Если это дублирующий вопрос, заранее извиняюсь .. Я хотел бы лучше понять, что такое ** kwargs в python, и на самом деле надеялся написать функцию, которая могла бы обрабатывать распаковку и внутреннюю ссылку на key:value пары для передачи ** аргументов kwargs.

Мой маленький пример выглядит следующим образом:

arguments = {'apple': 50, 'zoom': 'foo', 'bar': True}

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

def test(**kwargs):

    if kwargs is not None:

        print(f'apple: {apple}')
        print(f'zoom:  {zoom}')
        print(f'bar: {bar}')

Вызов вышеупомянутого через test(**arguments), конечно, не удался, но есть ли способ "распаковать" ** kwargs в локальное пространство имен внутри функции, чтобы выполнить то, о чем я думаю?

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

Есть ли другой способ присвоения локальных переменных из ** kwargs непосредственно в функцию?

Заранее спасибо.

РЕДАКТИРОВАТЬ

Я также исследовал с использованием vars() и написал следующее:

def test(**kwargs):

    try:
        print(**vars())
    except Exception as e:
        print(e, '\n\n')    
        print(vars())



    if kwargs is not None:

        try:

            print(f'apple: {apple}')
            print(f'zoom:  {zoom}')
            print(f'bar: {bar}')
        except:

            for k, v in kwargs.items():
                print(f'k: {k} : v: {v}') 

Со следующим выводом:

'kwargs' is an invalid keyword argument for this function 


{'kwargs': {'apple': 50, 'zoom': 'foo', 'bar': True}, 'e':TypeError("'kwargs' is an invalid keyword argument for this function",)}
k: apple : v: 50
k: zoom : v: foo
k: bar : v: True

Я заметил, что print(**kwargs) пытается получить доступ к "kwargs" как к именованной переменной.Я предполагаю, что вопрос, который я пытаюсь решить, если определение функции с аргументами по умолчанию, то передача ** kwargs решит проблему?Я могу попробовать это и посмотреть, работает ли он, и обновить ..

РЕДАКТИРОВАТЬ II

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

arguments = {'apple': 50, 'zoom': 'foo', 'bar': True, 'baz': 99}


def test(apple = None, zoom = 'fee', bar = False, **kwargs):

    if kwargs is not None:

        try:

            print(f'apple: {apple}')
            print(f'zoom:  {zoom}')
            print(f'bar: {bar}')
        except Exception as e:
            print(e, '\n\n\n')

        for k, v in kwargs.items():
            print(f'k: {k} : v: {v}')

test(**arguments)

РЕДАКТИРОВАТЬ III: update

Следующее является наиболее близким к тому, что я изначально пытался передать и реализовать.Функция, которая обрабатывает произвольные пользовательские ключевые аргументы и связывает их с переменными в локальном пространстве имен ...

def test(**kwargs):            

   ns = {}

   args_string = ''

   for k, v in kwargs.items():

        print(f'k: {k}, v: {v}')

        try:
            args_string += str(k) + '=' + '{}'.format(int(v))+'\n'
        except:
            args_string += str(k) + '=' + '"{}"'.format(str(v))+'\n'


    exec(args_string, ns)   

    return {k:v for k, v in ns.items() if k in kwargs.keys() }

Запуск следующего позволяет мне получить доступ к переменным, но я подозреваю, что это небезопасный или "хороший" код,

locals().update(test(**arguments))

1 Ответ

0 голосов
/ 29 ноября 2018

kwargs - это диктат, поэтому вы можете просто ссылаться на значения по их ключам:

def test(**kwargs):
    if kwargs:
        print(f'apple: {kwargs.get("apple")}')
        print(f'zoom:  {kwargs.get("zoom")}')
        print(f'bar: {kwargs.get("bar")}')
...