0

I have an AND and OR function that evaluates an expression. I would like to chain these items together into something like this:

>>> 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))))

However, I get this error when doing so:

SyntaxError: positional argument follows keyword argument

This is because the OR evaluates to a boolean and not a kwarg, which is how it needs to be passed. What would be a good way to get around this issue?

David542
  • 104,438
  • 178
  • 489
  • 842
  • 1
    Put the keyword arguments after the positional arguments? – Mark Mar 22 '20 at 19:47
  • 1
    or pass everything as keyword arguments... – DeepSpace Mar 22 '20 at 19:49
  • @MarkMeyer there can also be multiple levels of nesting and I'm not quite sure which part will evaluate to a value (such as "OR(...)" and which is just a variable). – David542 Mar 22 '20 at 19:49
  • @DeepSpace one option I thought was to wrap all the kwargs in something like a new class that defers evaluation, such as `Var(...)` -- but I'm looking for perhaps someone with a much better understanding of python to offer some solutions. – David542 Mar 22 '20 at 19:50

1 Answers1

1

Simply rearrange the call to have the kwargs after the args:

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

Or, if possible, use the dict unpacking operator:

AND(
    Neutered=True,
    **OR(Black=False, **AND(Female=False, **NOT(White=True)), **AND(NOT(Female=False), OR(White=True, Tan=True))))
wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • I like both approaches. The first one works when testing it, for the second one I get `TypeError: type object argument after ** must be a mapping, not NOT` -- it might be how tightly `**` binds but not entirely sure. – David542 Mar 22 '20 at 20:09
  • to simplify it, doing `AND(Neutered=True, **OR(Black=False, Blue=False))` gives me the same. – David542 Mar 22 '20 at 20:11
  • 1
    @David542 That means your classes aren't mappings (like a dict), which I guess means the second option isn't possible. If they should be mappings, check out [How to correctly implement the mapping protocol in Python?](https://stackoverflow.com/q/19775685/4518341) – wjandrea Mar 22 '20 at 20:12