David MacQuigg dmq at gain.com
Wed Mar 17 01:21:35 CET 2004

```On Tue, 16 Mar 2004 14:52:54 -0600, Skip Montanaro <skip at pobox.com>
wrote:

>    Dave>     def h23(freq):
>    Dave>         s = complex(2*pi*freq)
>    Dave>         h0 = PZfuncs.h0
>    Dave>         z1 = PZfuncs.z1; z2 = PZfuncs.z2
>    Dave>         p1 = PZfuncs.p1; p2 = PZfuncs.p2; p3 = PZfuncs.p3
>    Dave>         return h0*(s-z1)*(s-z2)/((s-p1)*(s-p2)*(s-p3))
>
>    Dave> Notice the clarity in that last formula.
>
>Yeah, but h0, z1, z2, etc are not long-lived copies of attributes in
>PZfuncs.  If I execute:
>
>    >>> blah = h23(freq)
>    >>> blah = h23(freq)
>
>things will work properly.  It's only long-lived aliases that present a
>problem:
>
>    def h23(freq, h0=PZfuncs.h0):
>        s = complex(2*pi*freq)
>        z1 = PZfuncs.z1; z2 = PZfuncs.z2
>        p1 = PZfuncs.p1; p2 = PZfuncs.p2; p3 = PZfuncs.p3
>        return h0*(s-z1)*(s-z2)/((s-p1)*(s-p2)*(s-p3))

I think we are saying the same thing.  I moved the alias definitions
inside the loop, knowing they would be short-lived, and therefor not a
problem.

>    Dave> In this case we avoid the problem of local variables out-of-sync
>    Dave> with a reloaded module by refreshing those variables with every
>    Dave> call to the function.  In other cases, this may add too much
>    Dave> overhead to the computation.
>
>Unlikely.  Creating local copies of frequently used globals (in this case
>frequently used globals in another module) is almost always a win.  In fact,
>it's so much of a win that a fair amount of brain power has been devoted to
>optimizing global access.  See PEPs 266 and 267 and associated threads in
>python-dev from about the time they were written.  (Note that optimizing
>global access is still an unsolved problem in Python.)

Interesting.  I just ran a test comparing 10,000 calls to the original
h23 above with 10,000 calls to h23a below.

h0 = PZfuncs.h0
z1 = PZfuncs.z1; z2 = PZfuncs.z2
p1 = PZfuncs.p1; p2 = PZfuncs.p2; p3 = PZfuncs.p3
def h23a(freq):
s = complex(2*pi*freq)
return h0*(s-z1)*(s-z2)/((s-p1)*(s-p2)*(s-p3))

The results are very close:

time/loop (sec)    %
Test 1: 6.48E-006   119.1 (class PZfuncs)
Test 2: 6.88E-006   126.4 (module PZfuncs)
Test 3: 5.44E-006   100.0 (z1, p1, etc  outside loop)

There is not much difference in the original loop between accessing
the constants from a class vs accessing them from a module.  There is
a significant difference ( but not as much as I expected ) if we move
the six assignments outside the loop.  Then we are back to the problem
of ensuring that the aliases get updated each time we update the
module.

-- Dave

```