Function Factory Basics

I’m sharing these first steps in function factories purely as I see them unfold, intuitively, not as instruction.

>>> def foo(x):
	return (x ** 3 - 2 * x) * 2

Above we have an arbitrary function that just does some stuff to an input and churns out a value.

>>> for n in [1,2,3,4,5]:
	print (foo(n))


How can we test the divisibility of these numbers? With a function? Yes. But what kind of function? One we have hard coded? If the factor we seek is singular, then that would be okay. Otherwise? No. We would have a sea of functions in no time.

Function factory f to the rescue. It can be called upon transiently and leave no trace whence gone.

Let’s look at the single function approach, given that we only want to test divisibility by 7.

>>> def mod_7(x):
	return not x % 7

>>> f = filter(mod_7, map(foo, range(10)))
>>> f
<filter object at 0x02E48CB0>
>>> list(f)
[0, 42, 112, 658]

Mind, now we have this method cluttering up the namespace, and who knows when it will be called again?

Notice where we snuck in a couple of callbacks? The one in the MAP should be easy to decipher… We just want a bunch of numbers from that one. mod_7 is where we need to focus. It has less real meaning and just comes out of nowhere. AND it is dedicated.

What if we can make that function call dedicated to our dynamic need? Well, we can. With a function factory we return this function dynamically, with the constant set as needed.

>>> def mod(x):
	def u(v):
		return not v % x
	return u

>>> f = filter(mod(7), map(foo, range(10)))
>>> list(f)
[0, 42, 112, 658]
>>> f = filter(mod(6), map(foo, range(10)))
>>> list(f)
[0, 42, 408, 1422]
>>> f = filter(mod(7), map(foo, range(20)))
>>> list(f)
[0, 42, 112, 658, 1960, 2618, 5432, 9758, 11592]
>>> f = filter(mod(6), map(foo, range(20)))
>>> list(f)
[0, 42, 408, 1422, 3408, 6690, 11592]

foo is still taking up space but since we call it so much we can’t call that a problem. All those pesky modulo calls, well they are history.

Edited: July 7, 2019

1 Like