Mar 17, 2012 11:18 am
Steven D'ApranoInspired by the new collections.ChainMap in Python 3.3
http://docs.python.org/dev/library/collections.html#collections.ChainMap
I would like to experiment with similar non-dictionary namespaces in
Python 3.2.
My starting point is these two recipes, adapted for Python 3.2:
http://code.activestate.com/recipes/305268/
http://code.activestate.com/recipes/577434/
Or for simplicity, here's a mock version:
from collections import Mapping
class MockChainMap(Mapping):
def __getitem__(self, key):
if key == 'a': return 1
elif key == 'b': return 2
raise KeyError(key)
def __len__(self):
return 2
def __iter__(self):
yield 'a'
yield 'b'
Note that it is important for my purposes that MockChainMap does not
inherit from dict.
Now I try to create a function that uses a MockChainMap instead of a dict
for its globals:
function = type(lambda: None)
f = lambda x: (a+b+x)
g = function(f.__code__, MockChainMap(), 'g')
And that's where I get into trouble:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function() argument 2 must be dict, not MockChainMap
How do I build a function with globals set to a non-dict mapping?
If this can't be done, any suggestions for how I might proceed?
Steven
Mar 17, 2012 6:42 pm
Eric SnowOn Sat, Mar 17, 2012 at 4:18 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Note that it is important for my purposes that MockChainMap does not
> inherit from dict.
> inherit from dict.
Care to elaborate?
> Now I try to create a function that uses a MockChainMap instead of a dict
> for its globals:
>
> function = type(lambda: None)
> f = lambda x: (a+b+x)
> g = function(f.__code__, MockChainMap(), 'g')
>
> And that's where I get into trouble:
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: function() argument 2 must be dict, not MockChainMap
>
>
> How do I build a function with globals set to a non-dict mapping?
>
> If this can't be done, any suggestions for how I might proceed?
> for its globals:
>
> function = type(lambda: None)
> f = lambda x: (a+b+x)
> g = function(f.__code__, MockChainMap(), 'g')
>
> And that's where I get into trouble:
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: function() argument 2 must be dict, not MockChainMap
>
>
> How do I build a function with globals set to a non-dict mapping?
>
> If this can't be done, any suggestions for how I might proceed?
This looks like one of those cases where there is strict type checking
(of a Python object) at the C level. You may consider bringing this
up in a tracker ticket. Unless there are performance implications,
it's likely a case of no one having bothered to change this spot to be
more duck-type friendly. There are quite a few of those in CPython
and I've seen at least a couple updated when someone brought it up.
Regardless, you could also implement __call__() on a function
look-alike class to get what you're after. It may not be as
performant though.
-eric
Mar 18, 2012 1:52 am
Steven D'ApranoOn Sat, 17 Mar 2012 11:42:49 -0700, Eric Snow wrote:
> On Sat, Mar 17, 2012 at 4:18 AM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
> Care to elaborate?
> <steve+comp.lang.python@pearwood.info> wrote:
>> Note that it is important for my purposes that MockChainMap does not
>> inherit from dict.
> >> inherit from dict.
> Care to elaborate?
I want to use collections.ChainMap, or something very like it, and I
don't want to be forced into an unnatural is-a relationship with dict if
I don't have to.
[...]
> Regardless, you could also implement __call__() on a function look-alike
> class to get what you're after. It may not be as performant though.
> class to get what you're after. It may not be as performant though.
I don't think that can work, because __call__ itself is a function, and I
would need to change *its* globals. Which brings me back exactly where I
started, trying to change globals in a function to a non-dict.
Steven
Mar 18, 2012 7:50 am
Peter OttenSteven D'Aprano wrote:
> On Sat, 17 Mar 2012 11:42:49 -0700, Eric Snow wrote:
>
> I want to use collections.ChainMap, or something very like it, and I
> don't want to be forced into an unnatural is-a relationship with dict if
> I don't have to.
>
>
> [...]
> I don't think that can work, because __call__ itself is a function, and I
> would need to change *its* globals. Which brings me back exactly where I
> started, trying to change globals in a function to a non-dict.
>
>> On Sat, Mar 17, 2012 at 4:18 AM, Steven D'Aprano
>> <steve+comp.lang.python@pearwood.info> wrote:
>> Care to elaborate?
> >> <steve+comp.lang.python@pearwood.info> wrote:
>>> Note that it is important for my purposes that MockChainMap does not
>>> inherit from dict.
>> >>> inherit from dict.
>> Care to elaborate?
> I want to use collections.ChainMap, or something very like it, and I
> don't want to be forced into an unnatural is-a relationship with dict if
> I don't have to.
>
>
> [...]
>> Regardless, you could also implement __call__() on a function look-alike
>> class to get what you're after. It may not be as performant though.
> >> class to get what you're after. It may not be as performant though.
> I don't think that can work, because __call__ itself is a function, and I
> would need to change *its* globals. Which brings me back exactly where I
> started, trying to change globals in a function to a non-dict.
The key lookup code in ceval.c is inlined, so even subclassing dict and
overriding __getitem__() won't help. Instead of
def f(a):
return a + b # b taken from some custom namespace
you have to resort to the conventional approach
def f(a, ns=magic()):
return a + ns["b"]
or
def f(self, a):
return a + self.b
Previous Thread: Question about python 3.2 distutils
Next Thread: Programming D. E. Knuth in Python with the Deterministic Finite Automatonconstruct
Related Forum Topics
- Multiple namespaces within a single module?
- Functions which take functions
- Vertical ordering of functions
- Of Functions, Objects, and Methods-I NEED HELP PLEASE
- How to handle calling functions from cli
- Dict comprehension help
- Re: Virtual functions are virtually invisible!
- Geodetic functions library GeoDLL 32 Bit and 64 Bit
- Why did GMPY change the names of its functions?
- (Learner-here) Lists + Functions = headache