从 Python 中的表达式文本中获取快速仿函数(比 eval 快)
Get fast functor from text of expression in Python (faster than eval)
我在性能方面遇到了一些问题。
我需要在字符串中执行用 Python 语法编写的表达式。
def FindOccurences( data, condition, left, right ):
result = []
func = eval( u"lambda data, i : " + condition )
for i in range(left, right):
if(func( data, i ) == True ):
result.append( i )
return result
此代码有效,但它比 if
慢 ~3-4 倍
if(func( data, i ) == True):
result.append( i )
将替换为:
if( *condition* ):
result.append( i )
但我不想为每个条件从模板生成 python 脚本。
有什么方法可以提高脚本第一个变体的性能吗?
PS 不用担心安全,这个功能会被包含在项目中的人使用
尝试使用 list comprehensions. That way you won't have to load the list.append
function into memory and it can boost your script, for not having to do a lot of appends, so check this article 进行比较。使用列表推导的代码可以这样写:
def FindOccurences(data, condition, left, right):
func = eval( u"lambda data, i : " + condition)
return [i for i in range(left, right) if func(data, i)]
我还会 return 一个遍历 indexes
的迭代器,它是函数的结果,如下所示:
def FindOccurences(data, condition, left, right):
func = eval( u"lambda data, i : " + condition)
return (i for i in range(left, right) if func(data, i))
那样的话,我们可以在不获取包含所有结果的列表的情况下获取 FindOcurrences 方法的前三个结果,当然我们可以通过左右调整来实现,但这种方式更像是一种按需方法:
from itertools import islice
results = islice(FindOccurrences(mydata, condition_str, 0, 100)
for item in result:
print item
你可以只在条件下调用 eval 应该更快:
func = (lambda data, i : eval(condition) )
Using a simple example:
In [28]: condition = "i > 10"
In [29]: timeit func = (lambda i: eval(condition))
10000000 loops, best of 3: 62.8 ns per loop
In [30]: timeit eval( u"lambda data, i : " + condition )
100000 loops, best of 3: 13.9 µs per loop
将其放入列表 comp 中 if func(data, i)
与 if func(data, i) == True
相同,您也不需要在 if 语句中使用括号并使用小写字母作为函数名称。
def find_occurrences( data, condition, left, right ):
func = eval(lambda data, i : eval(condition))
return [ i for i in xrange(left,right) if func(data, i)]
我在性能方面遇到了一些问题。 我需要在字符串中执行用 Python 语法编写的表达式。
def FindOccurences( data, condition, left, right ):
result = []
func = eval( u"lambda data, i : " + condition )
for i in range(left, right):
if(func( data, i ) == True ):
result.append( i )
return result
此代码有效,但它比 if
慢 ~3-4 倍if(func( data, i ) == True):
result.append( i )
将替换为:
if( *condition* ):
result.append( i )
但我不想为每个条件从模板生成 python 脚本。
有什么方法可以提高脚本第一个变体的性能吗?
PS 不用担心安全,这个功能会被包含在项目中的人使用
尝试使用 list comprehensions. That way you won't have to load the list.append
function into memory and it can boost your script, for not having to do a lot of appends, so check this article 进行比较。使用列表推导的代码可以这样写:
def FindOccurences(data, condition, left, right):
func = eval( u"lambda data, i : " + condition)
return [i for i in range(left, right) if func(data, i)]
我还会 return 一个遍历 indexes
的迭代器,它是函数的结果,如下所示:
def FindOccurences(data, condition, left, right):
func = eval( u"lambda data, i : " + condition)
return (i for i in range(left, right) if func(data, i))
那样的话,我们可以在不获取包含所有结果的列表的情况下获取 FindOcurrences 方法的前三个结果,当然我们可以通过左右调整来实现,但这种方式更像是一种按需方法:
from itertools import islice
results = islice(FindOccurrences(mydata, condition_str, 0, 100)
for item in result:
print item
你可以只在条件下调用 eval 应该更快:
func = (lambda data, i : eval(condition) )
Using a simple example:
In [28]: condition = "i > 10"
In [29]: timeit func = (lambda i: eval(condition))
10000000 loops, best of 3: 62.8 ns per loop
In [30]: timeit eval( u"lambda data, i : " + condition )
100000 loops, best of 3: 13.9 µs per loop
将其放入列表 comp 中 if func(data, i)
与 if func(data, i) == True
相同,您也不需要在 if 语句中使用括号并使用小写字母作为函数名称。
def find_occurrences( data, condition, left, right ):
func = eval(lambda data, i : eval(condition))
return [ i for i in xrange(left,right) if func(data, i)]