Generator vs functools.partial?
J. Cliff Dyer
jcd at sdf.lonestar.org
Thu Jun 21 12:15:08 EDT 2012
On Thu, 2012-06-21 at 21:25 +1000, John O'Hagan wrote:
> Sometimes a function gets called repeatedly with the same expensive argument:
>
> def some_func(arg, i):
> (do_something with arg and i)
>
> same_old_arg = big_calculation()
> for i in lots_of_items:
> some_func(same_old_arg, i)
>
Another possibility is to refactor this into a callable class.
class DoesSomethingWithExpensiveData(object):
def __init__(self, arg):
self.arg = arg
def __call__(self, operand):
return sum([self.arg, operand])
func = DoesSomethingWithExpensiveData(big_calculation()):
for thing in a_bunch_of_things:
print func(thing)
Or you can write a function factory:
def get_func(arg):
def inner(operand):
return sum([arg, operand])
return inner
func = get_func(big_calculation())
for thing in a_bunch_of_things:
print func(thing)
> A simple case like that looks OK, but it can get messy when groups of arguments
> are passed between functions, especially if the arguments are used by functions
> called within the functions they are passed to (by other functions!).
>
> Maybe that's a code smell, but it can be cleaned up with:
>
> import functools
> some_func = functools.partial(some_func, big_calculation())
> for i in lots_of_items:
> some_func(i)
>
> But what about a generator?
>
> def some_func():
> arg = big_calculation()
> while 1:
> i = yield
> (do_something with arg and i)
>
> some_gen = some_func()
> some_gen.send(None)
> for i in lots_of_items:
> some_gen.send(i)
>
> I like this because it encapsulates the calculation of the arguments
> inside the function that is using them without repeating it, and there are no
> restrictions on argument order like partial. But sending None is annoying. :)
>
> Old news? Thoughts, criticisms, theories?
>
> --
>
> John
More information about the Python-list
mailing list