Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The <code>__getitem__</code> function is a way to simulate a dictionary or list (or, more accurately, any mapping or sequence).</p> <p>The reference documentation for sequences and mappings is in <a href="http://docs.python.org/3/reference/datamodel.html" rel="nofollow">Data model</a>, but the best place to start is probably with the <a href="http://docs.python.org/3/library/collections.abc.html" rel="nofollow"><code>collections.abc</code></a> module, and the links from there.</p> <p>To summarize the basic idea, when you write code like this:</p> <pre><code>foo[bar] </code></pre> <p>Python translates it into*:</p> <pre><code>foo.__getitem__(bar) </code></pre> <hr> <p>There is nothing wrong with defining <code>__getitem__</code> to simulate a <code>dict</code>. </p> <p>And doing it to create an object that treats its attributes as dict items is such a common pattern that it has a name ("attrdict").</p> <p>However, using <code>eval</code> <em>is</em> almost always the wrong thing to do. So, doing the right thing to make <code>eval</code> work is, generally, right in that you're doing the right thing, but wrong in that you're using <code>eval</code> in the first place.</p> <hr> <p>In your particular case, there's no good reason to use <code>eval</code> in the first place. Instead of this:</p> <pre><code>eval("color=='green'",new_dict) </code></pre> <p>Just do this:</p> <pre><code>new_dict['color']=='green' </code></pre> <p>One reason Python novices (especially those who grew up on old versions of PHP, Tcl, or JavaScript) often want to use <code>eval</code> is to get an expression they can pass around easily. But in Python (and, for that matter, modern PHP and JS), functions are first-class values, just as easy to pass around as strings—and, unlike strings, of course, they're callable. You can create named or lambda functions, or use <code>partial</code>, close over whatever local variables you want, etc. </p> <p>There is almost nothing you can do with a string you can't do with a function—except, of course, for opening a gaping security hole, slowing down performance, and hindering debugging.</p> <p>So, instead of something like this:</p> <pre><code>expr = "color=='green'" # ... eval(expr, new_dict) </code></pre> <p>… just do this:</p> <pre><code>expr = lambda x: x.color=='green' # ... expr(new_dict) </code></pre> <hr> <p>In you edited question:</p> <blockquote> <p>Here is why eval is used in the program: Imagine you got like 20 objects of myStuff in a list mylist and you want to filter them by color yellow, then one can simply call [ n for n in mylist if eval(query, Dummy(n) ] with `query="color=='yellow'".</p> </blockquote> <p>So, you're presumably doing something like this:</p> <pre><code>query = "color=={}'.format(color) # ... [n for n in mylist if eval(query, Dummy(n)] </code></pre> <p>But you could just as easily do this:</p> <pre><code>[n for n in mylist if n.color == color] </code></pre> <p>Even when you need something more dynamic, you can build functions dynamically, even more easily than strings:</p> <pre><code>query = lambda n: n.color == color [n for n in mylist if query(n)] </code></pre> <p>In fact, if you really want to, you can even make this completely functional:</p> <pre><code>filter(compose(partial(operator.eq, color), attrgetter('color')), mylist) </code></pre> <p>But the great thing about Python is that you don't have to go completely functional or completely imperative, you can write something half-way between—or 25% or 75%, whatever happens to be easiest to read and write.</p> <hr> <p>Meanwhile:</p> <blockquote> <p>Or is it bad to use the above method, because no one really knows how the eval method has been implemented and the code could therefore come up with some strange errors in future?</p> </blockquote> <p>No, that's almost <em>never</em> a problem. </p> <p>First, the <a href="http://docs.python.org/3/library/functions.html#eval" rel="nofollow">documentation for <code>eval</code></a> is generally sufficient to predict exactly what it will do, and all Python implementations must follow that documentation.</p> <p>In the rare occasions where you <em>do</em> need to know more, all of the major implementations are open source, so you can just read the code. For example, you can browse the CPython 3.3 code online <a href="http://hg.python.org/cpython/file/3.3/" rel="nofollow">here</a>.**</p> <hr> <p>* This isn't completely accurate; the real code actually looks up <code>__getitem__</code> in the class rather than the object (slightly differently for old-style vs. new classes in 2.x), and handles extension types from C modules/Java packages/whatever's appropriate to your Python implementation, deals with slices (differently in 2.x vs. 3.x), etc. But that's the basic idea.</p> <p>** The <code>eval</code> code has been gradually refactored over the years, so at this point you could pretty much reimplement <code>eval</code> in a few lines of pure Python by using the <code>ast</code> module and friends, or a few lines of C using the <code>PyEval*</code> functions, so it's hard to point you to the exact line of code to start in without knowing which implementation and version you care about.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload