__getitem__
的功能是模擬字典或列表(或,更準確地,任何映射或序列)的一種方式。
序列和映射的參考文檔在Data model中,但最好的啓動地點可能是collections.abc
模塊以及從那裏的鏈接。
總結的基本概念,當你寫這樣的代碼:
foo[bar]
Python的將其轉換爲*:
foo.__getitem__(bar)
沒有什麼錯定義__getitem__
模擬dict
。
而且做起來創建對待自己的屬性字典項目的對象是這樣一個共同的模式,它有一個名字(「attrdict」)。
但是,使用eval
是幾乎總是做錯了事情。因此,做正確的事情,使eval
工作,通常是正確的,因爲你做正確的事情,但錯誤的是,你首先使用eval
。
你的具體情況,也沒有充分的理由擺在首位使用eval
。取而代之的是:
eval("color=='green'",new_dict)
只是這樣做:
new_dict['color']=='green'
原因之一Python的新手(尤其是那些誰在舊版本的PHP,TCL,或JavaScript的長大)經常要使用eval
是得到他們可以輕鬆傳遞的表達。但是在Python(以及現代PHP和JS)中,函數是一流的值,就像字符串一樣容易傳遞 - 並且與字符串不同,當然它們是可調用的。您可以創建命名函數或lambda函數,或者使用partial
,關閉所需的任何局部變量等。
幾乎沒有什麼可以對字符串做任何事情 - 除了當然,打開一個漏洞大的安全漏洞,降低性能,並妨礙調試。
所以,與其是這樣的:
expr = "color=='green'"
# ...
eval(expr, new_dict)
...只是這樣做:
expr = lambda x: x.color=='green'
# ...
expr(new_dict)
在你編輯的問題:
這是爲什麼EVAL是在程序中使用:想象一下,您在列表mylist和您中獲得了20個myStuff對象想要用黃色過濾它們,那麼可以簡單地用`query =「color =='yellow'」來調用[n for mylist if eval(query,Dummy(n)]。
所以,你可能做這樣的事情:
query = "color=={}'.format(color)
# ...
[n for n in mylist if eval(query, Dummy(n)]
但是你可以很容易地做到這一點:當你需要的東西更動態
[n for n in mylist if n.color == color]
甚至,你可以動態構建函數,甚至比字符串更容易:
query = lambda n: n.color == color
[n for n in mylist if query(n)]
事實上,如果你真的想,你甚至可以讓這個完整的功能:
filter(compose(partial(operator.eq, color), attrgetter('color')), mylist)
但是關於Python的偉大的事情是,你不必去完全功能性或完全必要的,你可以寫在25%或75%之間,或者是最容易閱讀和書寫的東西。
同時:
或者是不好用上面的方法,因爲沒有人真正知道如何eval方法已經實現,因此代碼能想出在未來的一些奇怪的錯誤?
不,這差不多從來沒有一個問題。
首先,documentation for eval
通常足以準確預測它將執行的操作,所有Python實現必須遵循該文檔。
在極少數情況下,您需要知道更多,所有主要實現都是開源的,因此您可以閱讀代碼。例如,你可以在網上瀏覽here CPython的3.3碼**
*這不完全準確。真正的代碼實際上在類中查找__getitem__
而不是對象(在舊版和新版的2.x版中略有不同),並且處理來自C模塊/ Java包的擴展類型/任何適合您的Python實現的交易類型,交易與切片(2.x與3.x不同),等等。但這是基本的想法。
**的eval
代碼已逐步多年來重構,所以在這一點上,你可以非常使用ast
模塊和朋友,或者使用C幾行重新實現純Python幾行eval
PyEval*
函數,因此很難指出您確切的代碼行,而不知道您關心的是哪個實現和版本。
你爲什麼這樣使用'eval'?剛纔'd ['color'] =='green''有什麼問題? – Blender 2013-05-03 21:25:58
想知道* eval *如何工作(即在命名空間中執行評估,可以使用\ _ \ _ getitem \ _ \ _進行任意映射)是一個完全合理的問題。該技術是通用的,可以輕鬆實現鏈接計算,例如電子表格中使用的鏈接計算(使用常規字典無法輕鬆完成的計算)。 – 2013-05-03 22:01:51
@RaymondHettinger:是的,我們有理由懷疑'eval'是如何工作的,如果有人寫了OP正在尋找的那種教程,那真的會很酷。但是這並沒有改變這樣一個事實,就像99%的有eval問題的人,OP在這裏不應該使用它。這就是爲什麼總是值得問「爲什麼你想在這裏使用'eval'?」第一。最壞的情況是他們有一個很好的迴應(可以包括「因爲我想了解'eval'」),這使得他們的問題對未來的讀者更有用,對吧? – abarnert 2013-05-03 22:05:30