Цепочка kwargs в вызове функции

У меня есть функция AND и OR, которая оценивает выражение. Я хотел бы связать эти элементы вместе во что-то вроде этого:

>>> AND(
        # kwarg
        Neutered=True, 
        # reduces/evaluates to arg/value
        OR(Black=False, AND(Female=False, NOT(White=True)), AND(NOT(Female=False), OR(White=True, Tan=True))))

Однако при этом я получаю эту ошибку:

SyntaxError: позиционный аргумент следует за аргументом ключевого слова

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


person David542    schedule 22.03.2020    source источник
comment
Поместить аргументы ключевого слова после позиционных аргументов?   -  person Mark    schedule 22.03.2020
comment
или передать все как аргументы ключевого слова...   -  person DeepSpace    schedule 22.03.2020
comment
@MarkMeyer также может быть несколько уровней вложенности, и я не совсем уверен, какая часть будет оцениваться как значение (например, ИЛИ (...), а какая просто переменная).   -  person David542    schedule 22.03.2020
comment
Один из вариантов @DeepSpace, который я подумал, заключался в том, чтобы обернуть все kwargs чем-то вроде нового класса, который откладывает оценку, например Var(...), но я ищу, возможно, кого-то с гораздо лучшим пониманием python, чтобы предложить некоторые решения.   -  person David542    schedule 22.03.2020


Ответы (1)


Просто переставьте вызов, чтобы kwargs были после аргументов:

AND(
    OR(AND(NOT(White=True), Female=False), AND(NOT(Female=False), OR(White=True, Tan=True)), Black=False),
    Neutered=True)

Или, если возможно, используйте оператор распаковки dict:

AND(
    Neutered=True,
    **OR(Black=False, **AND(Female=False, **NOT(White=True)), **AND(NOT(Female=False), OR(White=True, Tan=True))))
person wjandrea    schedule 22.03.2020
comment
Мне нравятся оба подхода. Первый работает при тестировании, для второго я получаю TypeError: type object argument after ** must be a mapping, not NOT - возможно, насколько сильно ** связывает, но не совсем уверен. - person David542; 22.03.2020
comment
чтобы упростить это, выполнение AND(Neutered=True, **OR(Black=False, Blue=False)) дает мне то же самое. - person David542; 22.03.2020
comment
@David542 David542 Это означает, что ваши классы не являются сопоставлениями (например, dict), что, я думаю, означает, что второй вариант невозможен. Если это должны быть сопоставления, ознакомьтесь с Как правильно реализовать протокол сопоставления в Python? - person wjandrea; 22.03.2020