updating local()

Bengt Richter bokr at oz.net
Fri Oct 14 20:27:00 EDT 2005


On Thu, 06 Oct 2005 07:15:12 -0700, Robert Kern <robert.kern at gmail.com> wrote:

>Flavio wrote:
>> Ok, its not thousands, but more like dozens of variables...
>> I am reading a large form from the web which returns a lot of values.
>> (I am Using cherrypy)
>> 
>> I know I could pass these variables around as:
>> 
>> def some_function(**variables):
>>     ...
>> 
>> some_function(**variables)
>> 
>> but its a pain in the neck to have to refer to them as
>> variables['whatever']...
>> 
>> dont you think? 
>
>Use a Bunch.
>
>class Bunch(dict):
>    def __init__(self, *args, **kwds):
>        dict.__init__(self, *args, **kwds)
>        self.__dict__ = self
>
>--
Or use a version-sensitive byte-code hack to set some preset locals before executing,
either with one-time presets via normal decorator, e.g.,

 >>> from ut.presets import presets
 >>> @presets(x=111, y=222, z='zee')
 ... def foo():
 ...     return locals()
 ...
 >>> foo()
 {'y': 222, 'x': 111, 'z': 'zee'}

Or the same, just using a predefined dict instead of the keyword format:

 >>> e = {'a':0, 'b':1}
 >>> @presets(**e)
 ... def foo():
 ...     return locals()
 ...
 >>> foo()
 {'a': 0, 'b': 1}

What happened to foo viat the decoration:
 >>> import dis
 >>> dis.dis(foo)
   1           0 LOAD_CONST               1 ((0, 1))
               3 UNPACK_SEQUENCE          2
               6 STORE_FAST               0 (a)
               9 STORE_FAST               1 (b)

   3          12 LOAD_GLOBAL              0 (locals)
              15 CALL_FUNCTION            0
              18 RETURN_VALUE

To mess with the same base function with different presets more dynamically,
use the explicit way of calling the decorator:

The base function:

 >>> def bar(x, y=123):
 ...    return locals()
 ...

decorate and invoke on the fly with particular presets:

 >>> presets(**e)(bar)('exx')
 {'a': 0, 'y': 123, 'b': 1, 'x': 'exx'}

The keyword way:
 >>> presets(hey='there')(bar)('exx')
 {'y': 123, 'x': 'exx', 'hey': 'there'}

BTW, @presets does not change the signature of the function whose selected locals
are being preset from the decoration-time-generated constant, e.g.,

 >>> presets(hey='there')(bar)()
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 TypeError: bar() takes at least 1 argument (0 given)
 >>> presets(hey='there')(bar)('exx', 'wye')
 {'y': 'wye', 'x': 'exx', 'hey': 'there'}
 >>> presets(hey='there')(bar)('exx', 'wye', 'zee')
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 TypeError: bar() takes at most 2 arguments (3 given)

Regards,
Bengt Richter



More information about the Python-list mailing list