Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #21810 > unrolled thread
| Started by | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| First post | 2012-03-17 11:18 +0000 |
| Last post | 2012-03-18 08:50 +0100 |
| Articles | 4 — 3 participants |
Back to article view | Back to comp.lang.python
Using non-dict namespaces in functions Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-03-17 11:18 +0000
Re: Using non-dict namespaces in functions Eric Snow <ericsnowcurrently@gmail.com> - 2012-03-17 11:42 -0700
Re: Using non-dict namespaces in functions Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-03-18 01:52 +0000
Re: Using non-dict namespaces in functions Peter Otten <__peter__@web.de> - 2012-03-18 08:50 +0100
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-03-17 11:18 +0000 |
| Subject | Using non-dict namespaces in functions |
| Message-ID | <4f647317$0$29981$c3e8da3$5496439d@news.astraweb.com> |
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
[toc] | [next] | [standalone]
| From | Eric Snow <ericsnowcurrently@gmail.com> |
|---|---|
| Date | 2012-03-17 11:42 -0700 |
| Message-ID | <mailman.764.1332009772.3037.python-list@python.org> |
| In reply to | #21810 |
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
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-03-18 01:52 +0000 |
| Message-ID | <4f653fd9$0$29981$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #21828 |
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
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2012-03-18 08:50 +0100 |
| Message-ID | <mailman.776.1332057058.3037.python-list@python.org> |
| In reply to | #21845 |
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
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web