[BangPypers] Evaluating a string against mapping in python.

Noufal Ibrahim KV noufal at nibrahim.net.in
Sun Oct 26 12:58:31 CET 2014


On Sun, Oct 26 2014, Okan bhan wrote:


[...]

> A simple implementation of this is:
>
> class SimpleMapping:
>   def __init__(self, items):
>     self._items = items
>
>   def __getitems__(self, subitem):
>     print('*' * 20)
>     for item in self._items:
>       if subitem in item:
>         return True
>     return False                    

This is broken in two ways
1. The magic method is __getitem__ (not __getitems__). I'm assuming it's
   a typo otherwise, the rest of your code will not work even as you've
   mentioned. 
2. A mapping object is similar to a dictionary. It should
   return the actual object if you try to access it. Not a boolean True
   or False. 

The mapping objects given are specifications of the locals and globals
in which you will evaluate your string. Consult help("eval") for more
information.

    eval(source[, globals[, locals]]) -> value

> Playing around against it for a bit.
>>>>  mapping = SimpleMapping(set(['aaa', 'bbb', 'ccc']))
>>>>  eval('ppp', {}, mapping)
>         ********************
>         False
>>>>  eval('aa', {}, mapping)
>         ********************
>         True
>>>>  eval('xxx and aaa', {}, mapping)
>         ********************
>         False
>>>>  eval('xxx or aaa', {}, mapping)
>         ********************
>         ********************
>         True
>
> Struggled in beginning but now they all seem obvious to me. Tricky is:

Look at my comment above. Your Mapping object is flawed and all these
responses are quite wrong.

>
>>>>  eval('5.6', {}, mapping)
>         5.6

I'm not sure how this will work. In my case, I see this. 

>>> mapping = SimpleMapping(set(['aaa', 'bbb', 'ccc']))
>>> eval('5.6', {}, mapping)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: locals must be a mapping
>>> 


>>>>  eval('aa.a', {}, mapping)
>         AttributeError: 'bool' object has no attribute 'a'
>

> My doubts are:
> a. Why it didn't run for numeric 5.6? Also why is dot separated '5.6' any
> different to 'aa.a'? I looked around on eval documentation and examples but
> couldn't find use of eval with a mapping.

5.6 is not an attribute access. 5.6 is is a floating point number. aa.a
is an attribute access. It will first return False for `aa` since there
is no such key and your code returns False and then try to access `a` in
the Boolean which, predictably, fails. 

> b. I see many blogs suggesting to refrain from using eval unless
> absolutely needed. Is this one use case we must use it? Do we have any
> better way to evaluate this?

I'm not sure what exactly you want to do. Can you explain again?

> c. If indeed, I have to evaluate a string containing dots, how to do
> in the above scenario?

The object whose attribute you're trying to access should be there in
the locals or globals and then should have an attribute with the given
name. It will work then.
[...]


-- 
Cordially,
Noufal
http://nibrahim.net.in


More information about the BangPypers mailing list