Python forum for Python programmers

Using non-dict namespaces in functions

Mar 17, 2012 11:18 am
Steven D'Aprano

Inspired 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 Snow
Re: Using non-dict namespaces in functions

On 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.

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?

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'Aprano
Re: Using non-dict namespaces in functions

On 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:
>> Note that it is important for my purposes that MockChainMap does not
>> 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.

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 Otten
Re: Using non-dict namespaces in functions

Steven D'Aprano wrote:

> On 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:
>>> Note that it is important for my purposes that MockChainMap does not
>>> 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.
>
> 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?
Hello there

is it possible to have multiple namespaces within a single python
module?

I have a small app which is in three or four .py files. For various
reasons I would like to (perhaps optionally) combine these into one
file. I was hoping that there might be a simple mechanism that...
Functions which take functions
Do you have some real or realistic (but easy and self-contained)
examples when you had to define a (multi-statement) function and pass it
to another function?
Thank you.

Kiuhnm


Vertical ordering of functions
Hi,

I'm just reading Robert M. Martin's book entitled "Clean Code". In Ch.
5 he says that a function that is called should be below a function
that does the calling. This creates a nice flow down from top to
bottom.
However, when I write a Python script I do just the opposite. I...
Of Functions, Objects, and Methods-I NEED HELP PLEASE
I am almost there, but I need a little help:

I would like to

a) print my dogs in the format index. name: breed as follows:

0. Mimi:Poodle
1.Sunny: Beagle
2. Bunny: German Shepard
I am getting

(0, ('Mimi', 'Poodle')) . Mimi : Poodle instead-what have I done wrong?

b) I would...
How to handle calling functions from cli
I have a bunch of sub routines that run independently to perform various system checks on my servers. I wanted to get an opinion on the following code I have about 25 independent checks and I'm adding the ability to disable certain checks that don't apply to certain hosts.


m = { 'a':...
Dict comprehension help
I get a list of dicts as output from a source I need to then extract various dicts
out of. I can easily extract the dict of choice based on it containing a key with
a certain value using list comp but I was hoping to use dict comp so the output
was not contained within a list.

reduce(lambda x,y:...
Re: Virtual functions are virtually invisible!
On Sun, Jul 10, 2011 at 2:15 PM, rantingrick <rantingrick@gmail.com> wrote:
> On Jul 4, 3:43 am, Gregory Ewing <greg.ew...@canterbury.ac.nz> wrote:
>> rantingrick wrote:
>> > what concerns me is the fact that virtual methods in derived
>> > classes just blend in to the crowd.
>> > I think we...
Geodetic functions library GeoDLL 32 Bit and 64 Bit
Hi developers,

who develops programs with geodetic functionality like world-wide coordinate transformations or distance calculations, can work with the latest version of my GeoDLL. The Dynamic Link Library can easily be used with any programming language to add geodetic functionality to own...
Why did GMPY change the names of its functions?
OK, GMPY is now called GMPY2. No big deal, I can import as GMPY.

But why were scan0 and scan1 changed to bit_scan0 and bit_scan1?

What's the justification for that? I use those functions extensively
in my library of Collatz utilities and I had to re-edit them for no
obvious reason.


(Learner-here) Lists + Functions = headache
Hey guys and gals doing this tutorial(codecademy) and needed a bit help from the experienced.

I'm writing a function that takes a list(one they supply during runtime)
here's what my function is supposed to do

1. for each instance of the string "fizz" make a count
2. Finally return that...