0

There is an array of many various items (functions, object properties, values), for example:

lst = [
 1,
 a(),
 obj.prop,
 ...

 z()
]

I'd like to check all of values are True, so I use all():

all(lst)

But in this case all values of list are calculated at the moment list created.

The aim is not to calculate all values on list initialization, but calculate it "on the fly" and stop iterate (and calculate) on first False item in list. So one solution is to yield every value from generator:

def gen():
 yield 1
 yield a()
 yield obj.prop
 ...

 yield z()

But it is not dry code and looks ugly with repeated yield keyword. Is there any another, more beautiful, solution?

  • 2
    The code is only ugly because having "an array of various items" is ugly to begin with, you've only added the `yield` keyword to each line. If the best way to define this list is by literally writing out each element as you've shown, then no: there isn't a more beautiful way to write it as a generator that could support your requirement to stop evaluating elements after the first false is found (which `all` does for you https://stackoverflow.com/questions/14730046/is-the-shortcircuit-behaviour-of-pythons-any-all-explicit ) – Hymns For Disco Feb 28 '20 at 13:45

1 Answers1

-1

I'm going to be down-voted for posting this, but if you can split the functions and the parameters into a list of tuples (with params=None if the not really a function), something like this would work. But as people has said in the comments, that data comes in ugly. Think again were those functions are coming from before being added to the list and try to evaluate them one by one before generating a list with them if possible.

def a(z):
    print('a')
    return True
def b(z):
    print('b')
    return False
def c(z):
    print('c')
    return True

def map_func_params(x):
    for func, params in x:
        if params is None:
            if func:
                continue
        if func(*params):
            continue
        else:
            return False
    return True

print(
map_func_params([(a, (1,)), (b, (2, )), (c, (2, )), (4, None)])
)

The prints show:

a
b
False

and the function c is never executed.

Jano
  • 455
  • 2
  • 9
  • This handles functions, but not variables, like `obj.prop` - object properties could be rewritten using `getattr`, simple variables would need a wrapper function: `def get_a(): return a` – Błotosmętek Feb 28 '20 at 14:01
  • It is not just function calls, but also object properties that can lead to arbitrary code execution on evaluation – Hymns For Disco Feb 28 '20 at 14:02