Использовать атрибут объекта в выражении Numberxpr - PullRequest
0 голосов
/ 30 октября 2018

Я пытаюсь использовать атрибут объекта в выражении 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 s 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.

Есть ли простой, чистый способ сделать это?

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Вы можете использовать атрибут объекта __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__

0 голосов
/ 30 октября 2018

Ваша основная проблема - масштабируемость / ремонтопригодность вызова 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, потому что эти имена могли бы быть немного быстрее помещены в локальное пространство имен. Если есть вероятность столкновения атрибутов экземпляра с локальными именами в сценарии (что в значительной степени зависит от того, как вы называете свои атрибуты и что делает класс), вероятно, безопаснее передать vars как global_dict, как в вопрос (и по той же причине , как отмечено в комментарии ).

Вам все равно придется отслеживать соответствие между атрибутами экземпляра и их именами в выражениях Numberxpr, но основная часть работы может быть пропущена с помощью приведенного выше.

...