Python 在numexpr表达式中使用对象属性

Python 在numexpr表达式中使用对象属性,python,numpy,numexpr,Python,Numpy,Numexpr,我试图在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") 导致以下错误 ------------------------------------------------------

我试图在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'
一旦MyClass有十几个属性,并且有一些这样的调用要调用ne.evaluate,这将变得非常混乱


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

如果您的对象开始有很多属性,您主要关心的似乎是evaluate调用的可伸缩性/可维护性。通过传递varso,您可以自动化此部件:

请注意,我使用了local_dict,因为将这些名称放入本地名称空间可能要快一些。如果实例属性有可能与脚本中的本地名称冲突,这在很大程度上取决于您如何命名属性以及类的作用,那么可能更安全的做法是将变量作为全局dict传递,就像问题中一样,出于同样的原因


您仍然需要跟踪numexpr表达式中实例属性及其名称之间的对应关系,但上述内容可以跳过大部分工作。

如果您的对象开始具有大量属性,您主要关心的似乎是evaluate调用的可伸缩性/可维护性。通过传递varso,您可以自动化此部件:

请注意,我使用了local_dict,因为将这些名称放入本地名称空间可能要快一些。如果实例属性有可能与脚本中的本地名称冲突,这在很大程度上取决于您如何命名属性以及类的作用,那么可能更安全的做法是将变量作为全局dict传递,就像问题中一样,出于同样的原因

您仍然需要跟踪numexpr表达式中实例属性及其名称之间的对应关系,但上述操作可以跳过大部分工作。

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

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

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
请注意,此函数还将包括方法和某些隐藏属性,如uuu模块uuu和uuu主uu

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

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

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

请注意,此函数还将包括方法和某些隐藏属性,如_umodule _uuu和_umain uuu

@NateBronman,用于定制类,这些定制类通常与_u插槽uu一起出现,对吗?否则,varso应该返回与dunder o.dict一样的东西,比如在另一个答案中,对吗?主要是的,还有一些其他情况。考虑到这个问题,我重申,他的目标不太可能是这些案件之一。但问题不仅在于OP,所以你永远不知道别人心目中的对象是什么。@NateBronman你希望如果你使用numexpr,你会期望某种稳定性或先入为主,而不是真正的大规模抽象,只想做任何事…:我最初确实使用了local_dict,但当表达式还包含来自本地名称空间的变量时,效果就不太好了。@NathanMusoke有什么理由必须在实例之外进行求值,而没有实例方法求值吗?@NateBronman用于定制类,这些类通常可以与u slots_u一起出现,对吗?否则,varso应该返回与dunder o.dict一样的东西,比如在另一个答案中,对吗?主要是的,还有一些其他情况。考虑到这个问题,我重申,他的目标不太可能是这些案件之一。但问题不仅在于OP,所以你永远不知道别人心目中的对象是什么。@NateBronman你希望如果你使用numexpr,你会期望某种稳定性或先入为主,而不是真正的大规模抽象,只想做任何事…:我最初确实使用了local_dict,但当表达式还包含来自本地名称空间的变量时,这就没有那么好了。@NathanMusoke是否有任何原因使您必须在实例之外进行求值而没有实例方法求值?有任何建议对您有用吗?@DennisPatterson或多或少。我已经接受了答案。我仍然想避免把口述交给ne。不过……这些建议对你有用吗?@DennisPatterson或多或少。我已经接受了答案。我还是想
避免将dict传递给ne.evaluate…但是,您确实不应该为此使用dir。试试vars,即dict,如果失败,请检查@uuuu slots@juanpa.arrivillaga为什么不?有什么不好的地方吗?你真的不应该用dir。试试vars,即dict,如果失败,请检查@uuuu slots@juanpa.arrivillaga为什么不?它肯定有什么不好的地方吗?