Default scope of variables
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sun Jul 7 12:03:51 EDT 2013
On Sun, 07 Jul 2013 23:43:24 +1000, Chris Angelico wrote:
> On Sun, Jul 7, 2013 at 11:13 PM, Wayne Werner <wayne at waynewerner.com>
> wrote:
>> Which you would then use like:
>>
>>
>> conn = create_conn()
>> with new_transaction(conn) as tran:
>> rows_affected = do_query_stuff(tran)
>> if rows_affected == 42:
>> tran.commit()
>
> Yep. There's a problem, though, when you bring in subtransactions. The
> logic wants to be like this:
[snip hideous code]
> I don't like the look of this. It might work, but it's hardly ideal.
> This is why I like to be able to nest usages of the same name.
Yes, and the obvious way to nest usages of the same name is to use a
instance with a class attribute and instance attribute of the same name:
class Example:
attr = 23
x = Example()
x.attr = 42
print(x.attr)
del x.attr
print(x.attr)
If you need more than two levels, you probably ought to re-design your
code to be less confusing, otherwise you may be able to use ChainMap to
emulate any number of nested scopes.
One interesting trick is you can use a ChainMap as function globals.
Here's a sketch for what you can do in Python 3.3:
from types import FunctionType
from collections import ChainMap
class _ChainedDict(ChainMap, dict):
# Function dicts must be instances of dict :-(
pass
def chained_function(func, *dicts):
"""Return a new function, copied from func, using a
ChainMap as dict.
"""
dicts = dicts + (func.__globals__, builtins.__dict__)
d = _ChainedDict(*dicts)
name = func.__name__
newfunc = FunctionType(
func.__code__, d, name, closure=func.__closure__)
newfunc.__dict__.update(func.__dict__)
newfunc.__defaults__ = func.__defaults__
return newfunc
And in use:
py> f = chained_function(lambda x: x+y, {'y': 100})
py> f(1)
101
py> f.__globals__.maps.insert(0, {'y': 200})
py> f(1)
201
py> del f.__globals__.maps[0]['y']
py> f(1)
101
--
Steven
More information about the Python-list
mailing list