Как получить доступ к kwargs, созданным в другой функции, с помощью Python?

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

Однако сейчас я столкнулся с проблемой. Из основной функции я вызываю другую функцию, используя kwargs. Эта вторая функция затем обрабатывает ввод и добавляет новые kwargs. Проблема в том, что новые kwargs, созданные в этой функции, недоступны в первой. Есть ли питонический способ сделать это? В качестве примера я создал следующий код:

# Create main function
def main(**kwargs):
    # Add a key word argument
    kwargs["textMain"] = "text added in main"

    # Call a function with existing kwargs and a new one
    functionA(textNew = "text added in new" ,**kwargs)

    # Test what is in kwargs after subfunction is called
    print("\nTest kwargs after subfunction is called:")

    if "textMain" in kwargs:
        print(kwargs["textMain"])

    if "textNew" in kwargs:
        print(kwargs["textNew"])

    if "textA" in kwargs:
        print(kwargs["textA"])

def functionA(**kwargs):

    # Test kwargs before adding kwargs in subfunction
    print("\nTest kwargs in subfunction before adding:")

    if "textMain" in kwargs:
        print(kwargs["textMain"])

    if "textNew" in kwargs:
        print(kwargs["textNew"])

    if "textA" in kwargs:
        print(kwargs["textA"])

    # Add kwargs
    kwargs["textA"] = "text added in sub A"

    # and test kwargs again
    print("\nTest kwargs in subfunction after adding:")
    if "textMain" in kwargs:
        print(kwargs["textMain"])

    if "textNew" in kwargs:
        print(kwargs["textNew"])

    if "textA" in kwargs:
        print(kwargs["textA"])

if __name__ == "__main__":
    main()

Это дает следующий результат:

#Test kwargs in subfunction before adding:
#text added in main
#text added in new

#Test kwargs in subfunction after adding:
#text added in main
#text added in new
#text added in sub A

#Test kwargs after subfunction is called:
#text added in main

где мой предпочтительный результат был бы:

#Test kwargs in subfunction before adding:
#text added in main
#text added in new

#Test kwargs in subfunction after adding:
#text added in main
#text added in new
#text added in sub A

#Test kwargs after subfunction is called:
#text added in main
#text added in new
#text added in sub A

Было бы очень полезно, если бы кто-нибудь мог решить мою проблему. Заранее спасибо!


person Jan Willem Feitsma    schedule 25.06.2015    source источник
comment
Ваш пример кажется немного раздутым, вы уверены, что не можете сделать его немного короче?   -  person firelynx    schedule 25.06.2015


Ответы (1)


Когда вы используете синтаксис **kwargs в выражении вызова, Python расширяет словарь и передает отдельные аргументы. Тот же синтаксис в сигнатуре функции затем указывает Python создать новый словарь в этой функции для захвата аргументов ключевого слова.

Другими словами, kwargs в main() - это не тот же словарь, что и в functionA().

Либо передать фактический словарь (без использования синтаксиса **kwargs), либо functionA() вернет новый словарь.

Передача kwargs в качестве единственного аргумента позволяет вам изменить словарь с functionA() и увидеть изменения, отраженные в main(), поскольку теперь они используют ссылку на тот же словарь:

def main(**kwargs):
    functionA(kwargs, textNew="text added in new")
    # ... etc ...


def functionA(mapping, **kwargs):
    # do something with mapping, it is the same dictionary as kwargs in main

Для возврата обновленного kwargs словаря из functionA() требуется, чтобы вы снова назначили новый объект kwargs в main():

def main(**kwargs):
    kwargs = functionA(textNew="text added in new", **kwargs)
    # ... etc ...

def functionA(**kwargs):
    # ...
    return kwargs
person Martijn Pieters    schedule 25.06.2015
comment
Но разве возврат кваргов не будет дорогостоящей операцией? Создаем ли мы новый словарь, возвращая таким образом kwargs? Было бы лучше вернуть ссылку на исходный словарь, но я хотел бы иметь возможность добавлять аргументы ключ-значение, а не просто ссылку на него. - person Jan Willem Feitsma; 26.06.2015
comment
@JanWillemFeitsma: нет, возвращать kwargs не дорого. Python уже создал словарь, когда вы вызывали функцию (и создание его на самом деле относительно дешево). В противном случае функции Python всегда что-то возвращают (возвращаемое значение по умолчанию - None). Что лучше - зависит от ваших сценариев использования; в данном примере передать ссылку и изменить ее, безусловно, проще. - person Martijn Pieters; 26.06.2015