Python 不仅用字典评估
通常我可以这样使用eval:Python 不仅用字典评估,python,dictionary,Python,Dictionary,通常我可以这样使用eval: new_dict={'color':'green'} eval("color=='green'",new_dict) 在这种情况下,它将返回true,因此我知道new_dict中的颜色实际上是绿色的。现在我发现了一些代码,其中有人想使用eval,但使用了更通用的对象,而不是dict。 在以下代码中,基本上就是此人所做的: class myStuff(object): def __init__(self): self.color = "gre
new_dict={'color':'green'}
eval("color=='green'",new_dict)
在这种情况下,它将返回true,因此我知道new_dict中的颜色实际上是绿色的。现在我发现了一些代码,其中有人想使用eval,但使用了更通用的对象,而不是dict。
在以下代码中,基本上就是此人所做的:
class myStuff(object):
def __init__(self):
self.color = "green"
class Dummy(dict):
def __init__(self, node):
dict.__init__(self)
self.node = node
def __getitem__(self, key):
return(getattr(self.node, key))
node=myStuff()
new_dict = Dummy(node)
print eval("color=='green'",new_dict)
我现在想知道——上面代码的开发人员是如何知道eval在new\u dict for color上使用了方法\uuu getitem\uuuu
?我找到了文档和python帮助函数,但找不到方法(或实际代码)的分步文档,因此我永远不会想到像上面的代码那样做。或者,使用上述方法不好,因为没有人真正知道eval方法是如何实现的,因此代码将来可能会出现一些奇怪的错误
编辑:这就是在程序中使用eval的原因:假设在一个列表mylist中有20个myStuff对象,您想用黄色对它们进行过滤,那么您可以简单地调用[n代表mylist中的n,如果eval(query,Dummy(n)],并使用'query=“color=='yellow'”。我不是专家,但我只是想知道这种方法是否会导致问题。
\uuuu getitem\uuuuuuuu
是dict
用来通过关键字检索项目的。通过重写\uuuu getitem\uuuuuuuu
并使其返回self.node
的属性,您基本上可以将node
转换为字典
一种更简单的方法是只使用\uuu dict\uuu
属性,该属性执行相同的操作:
print eval("color=='green'", node.__dict__)
但实际上,请不要使用此选项。
eval()
很少是工作的正确工具,这是一个完美的例子,您不需要使用eval
\uuuu getitem\uuuuuuuuu
是dict
通过键检索项目的工具。通过覆盖\uuu getitem\uuuuuuuuuuu
并使其返回self.node
的属性,您基本上变成了将节点
放入字典
一种更简单的方法是只使用\uuu dict\uuu
属性,该属性执行相同的操作:
print eval("color=='green'", node.__dict__)
但实际上,请不要使用它。
eval()
很少是适合这项工作的工具,这是一个完美的例子,说明您不需要使用eval
函数\uu getitem\uuuuuuuuuu
可以模拟字典或列表(或者更准确地说,任何映射或序列)
序列和映射的参考文档在中,但是最好从模块开始,以及从模块开始的链接
总结一下基本思想,当您编写这样的代码时:
foo[bar]
expr = "color=='green'"
# ...
eval(expr, new_dict)
query = "color=={}'.format(color)
# ...
[n for n in mylist if eval(query, Dummy(n)]
Python将其翻译为*:
foo.__getitem__(bar)
定义
\uuu getitem\uuu
来模拟dict
没有什么错
这样做是为了创建一个对象,将其属性视为dict项,这是一种常见的模式,它有一个名称(“attrdict”)
然而,使用eval
几乎总是错误的。因此,做正确的事情使eval
工作通常是正确的,因为你做的是正确的事情,而错误的是你首先使用eval
在您的特定情况下,首先没有充分的理由使用
eval
。而不是:
eval("color=='green'",new_dict)
只要这样做:
new_dict['color']=='green'
expr = lambda x: x.color=='green'
# ...
expr(new_dict)
Python新手(尤其是那些在旧版本的PHP、Tcl或JavaScript上长大的人)经常想要使用eval
的一个原因是为了得到一个可以轻松传递的表达式,函数是一级值,与字符串一样容易传递,当然,与字符串不同,它们是可调用的。您可以创建命名函数或lambda函数,或使用分部
,关闭您想要的任何局部变量,等等
当然,除了打开一个巨大的安全漏洞、降低性能和阻碍调试之外,对于一个字符串,几乎没有什么是函数所不能做的
因此,与此不同的是:
foo[bar]
expr = "color=='green'"
# ...
eval(expr, new_dict)
query = "color=={}'.format(color)
# ...
[n for n in mylist if eval(query, Dummy(n)]
…就这样做:
new_dict['color']=='green'
expr = lambda x: x.color=='green'
# ...
expr(new_dict)
在您编辑的问题中: 下面是在程序中使用eval的原因:假设您在一个列表mylist中有20个myStuff对象,并且您想用黄色对它们进行过滤,那么您可以简单地调用[n代表mylist中的n,如果eval(query,Dummy(n)],并使用'query=“color=='yellow'” 那么,你大概在做这样的事情:
foo[bar]
expr = "color=='green'"
# ...
eval(expr, new_dict)
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方法是如何实现的,因此代码将来可能会出现一些奇怪的错误 不,这几乎从来都不是问题 首先,通常情况下,该文档足以准确预测它将做什么,所有Python实现都必须遵循该文档 在极少数需要了解更多信息的情况下,所有主要的实现都是开源的,因此您只需阅读代码即可。例如,您可以在线浏览CPython 3.3代码**
*这并不完全准确;真正的代码实际上是在类中而不是在对象中查找
\uuuu getitem\uuuu
(对于2.x中的旧式类和新类略有不同),并且处理C模块/Java包/适合Python实现的任何扩展类型,处理切片(在2.x和3.x中有所不同)等等,但这是最基本的想法
**eval
代码已逐渐重构