[Tutor] constructing semi-arbitrary functions

"André Walker-Loud <walksloud@gmail.com>" walksloud at gmail.com
Thu Feb 20 00:59:57 CET 2014


Hi eryksun,

Thanks - this is great.
Also, since you are chiming in, do you have an opinion in general about which approach you prefer?  The string hacking vs class method (for lack of better way to describe them)?


Cheers,

Andre



On Feb 19, 2014, at 4:56 PM, eryksun <eryksun at gmail.com> wrote:

> On Wed, Feb 19, 2014 at 2:56 PM, "André Walker-Loud
> <walksloud at gmail.com>" <walksloud at gmail.com> wrote:
>> 
>> I also happened to get the string-hack to work (which requires
>> using global variables).
> 
> Functions load unassigned names from the global/builtins scopes, so
> there's no need to declare the g* variables global in chisq_mn. Also,
> implicit string concatenation and string formatting will make the
> definition easier to read, IMO:
> 
>    def make_chisq_mn(pars, x, y, dy):
>        global _gx, _gy, _gdy
>        _gx, _gy, _gdy = x, y, dy
>        names = ['c_%d' % i for i in xrange(len(pars))]
>        src = ('def chisq_mn(%(p)s):\n'
>               '    return chisq([%(p)s], _gx, _gy, _gdy)' %
>               {'p': ', '.join(names)})
>        print 'funcdef=\n', src
>        exec src in globals()
> 
> 
> You can use a custom dict with exec to avoid contaminating the
> module's global namespace:
> 
>    def make_chisq_mn(pars, x, y, dy):
>        ns = {'x': x, 'y': y, 'dy': dy, 'chisq': chisq}
>        names = ['c_%d' % i for i in xrange(len(pars))]
>        src = ('def chisq_mn(%(p)s):\n'
>               '    return chisq([%(p)s], x, y, dy)' %
>               {'p': ', '.join(names)})
>        print 'funcdef=\n', src
>        exec src in ns
>        return ns['chisq_mn']
> 
> 
> This version of chisq_mn uses the ns dict as its func_globals:
> 
>>>> chisq = lambda *a: None # dummy
>>>> chisq_mn = make_chisq_mn([1,2,3], 10, 20, 30)
>    funcdef=
>    def chisq_mn(c_0, c_1, c_2):
>        return chisq([c_0, c_1, c_2], x, y, dy)
> 
>>>> sorted(chisq_mn.func_globals)
>    ['__builtins__', 'chisq', 'chisq_mn', 'dy', 'x', 'y']
> 
>>>> dis.dis(chisq_mn)
>      2           0 LOAD_GLOBAL              0 (chisq)
>                  3 LOAD_FAST                0 (c_0)
>                  6 LOAD_FAST                1 (c_1)
>                  9 LOAD_FAST                2 (c_2)
>                 12 BUILD_LIST               3
>                 15 LOAD_GLOBAL              1 (x)
>                 18 LOAD_GLOBAL              2 (y)
>                 21 LOAD_GLOBAL              3 (dy)
>                 24 CALL_FUNCTION            4
>                 27 RETURN_VALUE



More information about the Tutor mailing list