Search code examples
pythonif-statementconcatenationgenerator-expression

Python concatenate string for conditions used in a generator expression


I have a set of conditions for a generator expression which will vary, and if possible, I thought to try concatenate the conditions as a string, and use this string variable inside the generator expression:

The following works fine:

Total = sum(sale["Date"] == date for sale in Sales_Store)

Where date is an integer, and Sales_Store a list of dictionaries with same keys, "Date" is one of the key names. it returns the number of sales in the sales store which satisfy this condition.

But this gives error: unsupported operand type(s) for +: 'int' and 'str'

strTest = "sale[\"Date\"] == date for sale in Sales_Store"
Total = sum(strTest)

Of course, I only want this condition in the generator expression if a certain other condition holds true, and have several other conditions to concatenate with this, each condition only applying in certain circumstances.

So do you know if there is way to make this concatenation work?


Solution

  • Strings are not executable code. Python won't look at a string and execute it if it could possibly be. You need to express your conditions differently.

    You could just create a function that given one dictionary returns a boolean; for a simple expression you can create that function using the lambda syntax:

    condition = lambda d: d['Date'] == date
    

    for larger tests you can use a def condition(d): function definition and use multiple statements, etc. Functions are executable expressions!

    Then use that in a map() call to apply the condition to each dictionary:

    sum(map(condition, Sales_Store))
    

    If you need to dynamically change the conditions, then build a sequence of tests, and use the any() or all() functions to combine these tests:

    conditions = (test1, test2, test3)
    all_conditions = lambda d: all(t(d) for t in conditions)
    any_condition = lambda d: any(t(d) for t in conditions)
    
    all_conditions_sum = map(all_conditions, Sales_Store)
    any_conditions_sum = map(any_conditions, Sales_Store)
    

    As you can probably tell from the function names, any() will return True if one of the tests is true, all() if all of the tests are true.

    How you select the tests to go into the conditions sequence is up to you. You could, for example, have a dictionary mapping a user-friendly string to a function and let an end-user decide.