1

我正在尝试在numexpr表达式中使用对象属性。最明显的做法是:

import numpy as np
import numexpr as ne

class MyClass:
    def __init__(self):
        self.a = np.zeros(10)

o = MyClass()

o.a

b = ne.evaluate("o.a+1")

导致以下错误

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-22-dc90c81859f1> in <module>()
     10 o.a
     11 
---> 12 b = ne.evaluate("o.a+1")

~/.local/lib/python3.5/site-packages/numexpr/necompiler.py in evaluate(ex, local_dict, global_dict, out, order, casting, **kwargs)
    799     expr_key = (ex, tuple(sorted(context.items())))
    800     if expr_key not in _names_cache:
--> 801         _names_cache[expr_key] = getExprNames(ex, context)
    802     names, ex_uses_vml = _names_cache[expr_key]
    803     arguments = getArguments(names, local_dict, global_dict)

~/.local/lib/python3.5/site-packages/numexpr/necompiler.py in getExprNames(text, context)
    706 
    707 def getExprNames(text, context):
--> 708     ex = stringToExpression(text, {}, context)
    709     ast = expressionToAST(ex)
    710     input_order = getInputOrder(ast, None)

~/.local/lib/python3.5/site-packages/numexpr/necompiler.py in stringToExpression(s, types, context)
    296         names.update(expressions.functions)
    297         # now build the expression
--> 298         ex = eval(c, names)
    299         if expressions.isConstant(ex):
    300             ex = expressions.ConstantNode(ex, expressions.getKind(ex))

<expr> in <module>()

AttributeError: 'VariableNode' object has no attribute 'a'

咨询另一个问题,我能够通过使用得到一个不太令人满意的解决numexpr方案global_dict

import numpy as np
import numexpr as ne

class MyClass:
    def __init__(self):
        self.a = np.zeros(10)

o = MyClass()

o.a

b = ne.evaluate("a+1", global_dict={'a':o.a})

一旦MyClass有十几个属性并且有几个这样的调用ne.evaluate.

有没有一种简单、干净的方法来做到这一点?

4

2 回答 2

2

您可以使用对象的__dict__属性来执行此操作。这将返回一个字典,其中键是属性的名称(作为字符串),值是该属性本身的实际值。

因此,例如,您问题中的代码如下所示:

import numpy as np
import numexpr as ne

class MyClass:
    def __init__(self):
        self.a = np.zeros(10)

o = MyClass()

o.a

b = ne.evaluate("a+1", global_dict=o.__dict__)  # Notice the .__dict__

但是,某些对象可能没有__dict__属性。所以,相反,我做了一个小函数来做同样的事情:

def asdict(obj):
    objDict = {}
    for attr in dir(g):
        objDict[attr] = getattr(g, attr)

    return objDict

请注意,此函数还将包括方法和某些隐藏属性,例如__module____main__

于 2018-10-29T22:52:59.113 回答
2

evaluate如果您的对象开始具有很多属性,您主要关心的似乎是调用的可伸缩性/可维护性。您可以通过传递自动化这部分vars(o)

import numpy as np
import numexpr as ne

class MyClass:
    def __init__(self):
        self.a = np.arange(10000)
        self.b = 2*self.a

o = MyClass()

c = ne.evaluate("a+b", local_dict=vars(o))

请注意,我之所以使用local_dict这些名称,是因为将这些名称放入本地命名空间可能会稍微快一些。如果实例属性有可能与脚本中的本地名称发生冲突(这在很大程度上取决于您如何命名属性以及该类的作用),那么varsglobal_dict问题中传递原因如评论中所述)。

您仍然需要跟踪实例属性和它们在 numexpr 表达式中的名称之间的对应关系,但是上面的大部分工作可以跳过。

于 2018-10-29T22:48:37.017 回答