Supply condition in function call

Peter Otten __peter__ at web.de
Fri Mar 27 16:38:54 EDT 2015


Manuel Graune wrote:

> Peter Otten <__peter__ at web.de> writes:
> 
>> Cameron Simpson wrote:
>>
>>>   test1([0,1,2,3], [1,2,3,4], condition_test)
>>> 
>>> This passes the local variables inside test1() to "condition" as a
>>> single parameter. Now, I grant that vars['i'] is a miracle of
>>> tediousness. So consider this elaboration:
>>> 
>>>   from collections import namedtuple
>>> 
>>>   condition_test = lambda vars: vars.i + vars.j > 4
>>> 
>>>   def test1(a, b, condition):
>>>     for i, j in zip(a,b):
>>>       c = i + j
>>>       vars = locals()
>>>       varnames = list(vars.keys())
>>
>> instead or pass the list of arguments explicitly, optionally with some
>> inspect fallback:
>>
>> $ cat pass_condition_inspect.py
>> import inspect
>>
>> def test3(a, b, condition, args=None):
>>     if args is None:
>>         args = inspect.getargspec(condition).args
>>
>>     for i, j in zip(a,b):
>>         c = i + j
>>         _locals = locals()
>>         if condition(*[_locals[name] for name in args]):
>>             print("Foo", i, j)
>>
>> def condition(c, i):
>>     return i * i > c
>>
>> test3([1, 2, 3], [2, 3, 4], condition)
>> print("---")
>> # note reverse order of argument names
>> test3([1, 2, 3], [2, 3, 4], condition, ["i", "c"])
>> $ python3 pass_condition_inspect.py
>> Foo 3 4
>> ---
>> Foo 1 2
>> Foo 2 3
>> Foo 3 4
>>
> 
> I'm just comparing the different solutions. For most of them, the
> logic and the costs/benefits are pretty clear to me. Can you
> elaborate on your code? I'm not clear what you are achieving with
> explicitly passing the arguments instead of simply passing some
> variant of the complete locals()-dictionary.

Positional arguments are the most common calling convention, and the 
resulting condition() function

def condition(c, i):
   return i * i > c

looks more natural to my eye than the

def condition(d):
    return d["i"] * d["i"] > d["c"]

or

def condition(s):
    return d.i * d.i > d.c

variants that you have to write when you follow Cameron's suggestions. You
are basically trading cleaner condition() client functions for messier 
testX() calling code.

You might also be able to reuse functions not written specifically for that 
interface. Example using the sum() builtin:

test3([1, 2, 3], [10, 20, 30], sum, ("a", "j"))

Not that sum() makes much sense here, but I hope you get the idea...




More information about the Python-list mailing list