function factory question: embed current values of object attributes

A

Alan Isaac

I have a class `X` where many parameters are set
at instance initialization. The parameter values
of an instance `x` generally remain unchanged,
but is there way to communicate to a method that
it depends only on the initial values of these parameters
(and does not need to worry about any changes)?

The behavior of method `m` depends on these parameter values.
It turns out `m` gets called a lot, which means
that the pameter values are accessed over and over
(self.p0, self.p1, etc). I would like to
manufacture a function equivalent to the method
that simply uses fixed values (the values at the
time it is manufactured). I do not care if this
function is attached to `x` or not.

I have a feeling that I am turning something simple
into something complex, perhaps for lack of an
afternoon coffee or lack of CS training. Suggestions
appreciated.

Alan Isaac
 
T

Terry Reedy

Alan said:
I have a class `X` where many parameters are set
at instance initialization. The parameter values
of an instance `x` generally remain unchanged,

'Parameters' are the function local names in the header that get bound
to argument objects when the function is called. What you are
describing are 'attributes'.
but is there way to communicate to a method that
it depends only on the initial values of these parameters
(and does not need to worry about any changes)?

In the terms stated, no.
The behavior of method `m` depends on these parameter values.
It turns out `m` gets called a lot, which means
that the pameter values are accessed over and over
(self.p0, self.p1, etc). I would like to
manufacture a function equivalent to the method
that simply uses fixed values (the values at the
time it is manufactured).

You are now describing a function closure. Here is an example that
might help.

def f_maker(a1, a2):
def _(b): return a1*b + a2
return _

class C:
def __init__(self, attr1, attr2):
self.attr1 = attr1
self.attr2 = attr2
self.f = f_maker(attr1, attr2)

c = C(2,3)
print(*(c.f(i) for i in range(5)))

# 3 5 7 9 11

Having f use both initial and 'current' attribute values would be a bit
trickier ;-)

Terry Jan Reedy
 
G

Gabriel Genellina

I have a class `X` where many parameters are set
at instance initialization. The parameter values
of an instance `x` generally remain unchanged,
but is there way to communicate to a method that
it depends only on the initial values of these parameters
(and does not need to worry about any changes)?

The behavior of method `m` depends on these parameter values.
It turns out `m` gets called a lot, which means
that the pameter values are accessed over and over
(self.p0, self.p1, etc). I would like to
manufacture a function equivalent to the method
that simply uses fixed values (the values at the
time it is manufactured). I do not care if this
function is attached to `x` or not.

Not automatically; but you could refactor the method to call an external
function with arguments:

class X(...):
...
def foo(self):
c = self.a + self.b
return c

Rewrite the method as:

def foo(self):
return _foo(self.a, self.b)

and define _foo outside the class:

def _foo(a, b):
c = a + b
return c

If you want a "frozen" function (that is, a function already set-up with
the parameters taken from the current values of x.a, x.b) use
functools.partial:

x = X()
frozen_foo = functools.partial(_foo, a=x.a, b=x.b)
frozen_foo() # equivalent to x.foo() at the time it was defined

But if you call this in a loop, perhaps it's enough to assign x.a, x.b to
local variables and call _foo with those arguments.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,139
Latest member
JamaalCald
Top