5 回答
TA贡献1784条经验 获得超9个赞
是的,使用eval是一种不好的做法。仅举几个原因:
几乎总有一种更好的方法
非常危险和不安全
使调试变得困难
慢
在您的情况下,您可以使用setattr:
class Song: """The class to store the details of each song""" attsToStore=('Name', 'Artist', 'Album', 'Genre', 'Location') def __init__(self): for att in self.attsToStore: setattr(self, att.lower(), None) def setDetail(self, key, val): if key in self.attsToStore: setattr(self, key.lower(), val)
编辑:
在某些情况下,您必须使用eval或exec。但它们很少见。在你的情况下使用eval肯定是一个坏习惯。我强调不好的做法,因为eval和exec经常在错误的地方使用。
编辑2:
看起来有些人不同意eval在OP情况下“非常危险且不安全”。对于这个特定情况可能也是如此,但一般情况下并非如此。问题是一般性的,我列出的原因也适用于一般情况。
编辑3: 重新排序第1点和第4点
TA贡献1803条经验 获得超3个赞
使用eval
很弱,不是一个明显不好的做法。
它违反了“软件基本原理”。您的来源不是可执行文件的总和。除了你的来源之外,还有
eval
必须清楚理解的论据。因此,它是最后的工具。这通常是轻率设计的标志。动态源代码很少有充分的理由,即时构建。使用委托和其他OO设计技术几乎可以做任何事情。
它导致相对较慢的动态编译小块代码。通过使用更好的设计模式可以避免开销。
作为一个脚注,在疯狂的反社会手中,它可能不会很好。然而,当面对精神错乱的反社会用户或管理员时,最好不要首先给他们解释Python。在真正邪恶的手中,Python可以承担责任; eval
根本不会增加风险。
TA贡献1856条经验 获得超5个赞
是的:
使用Python的Hack:
>>> eval(input())
"__import__('os').listdir('.')"
...........
........... #dir listing
...........
以下代码将列出在Windows计算机上运行的所有任务。
>>> eval(input())
"__import__('subprocess').Popen(['tasklist'],stdout=__import__('subprocess').PIPE).communicate()[0]"
在Linux中:
>>> eval(input())
"__import__('subprocess').Popen(['ps', 'aux'],stdout=__import__('subprocess').PIPE).communicate()[0]"
TA贡献1831条经验 获得超10个赞
值得注意的是,对于所讨论的具体问题,有几种替代方法可供使用eval
:
如上所述,最简单的是使用setattr
:
def __init__(self): for name in attsToStore: setattr(self, name, None)
一种不太明显的方法是__dict__
直接更新对象的对象。如果你想要做的就是将属性初始化为None
,那么这比上面的要简单得多。但考虑一下:
def __init__(self, **kwargs): for name in self.attsToStore: self.__dict__[name] = kwargs.get(name, None)
这允许您将关键字参数传递给构造函数,例如:
s = Song(name='History', artist='The Verve')
它还允许您locals()
更明确地使用,例如:
s = Song(**locals())
...并且,如果您真的想要分配None
名称在locals()
以下位置的属性:
s = Song(**dict([(k, None) for k in locals().keys()]))
为对象提供属性列表的默认值的另一种方法是定义类的__getattr__
方法:
def __getattr__(self, name): if name in self.attsToStore: return None raise NameError, name
当以正常方式找不到命名属性时,将调用此方法。这种方法比简单地在构造函数中设置属性或更新__dict__
它更简单,但它具有不实际创建属性的优点,除非它存在,这可以大大减少类的内存使用。
所有这一切:一般来说,有很多原因可以避免eval
- 执行你无法控制的代码的安全问题,你无法调试的代码的实际问题等等。但更重要的原因一般来说,你不需要使用它。Python向程序员公开了很多内部机制,你很少需要编写编写代码的代码。
添加回答
举报