LINUX.ORG.RU

Как вызвать функцию с не-родным global namespace?

 ,


0

1

Есть какая то функция пользователя, скажем

def f(): return a+1    

Я хочу ее вызвать так, что бы при вызове у нее глобальное пространство имен, откуда тянется переменная a, было не родным (того модуля где определена f) а каким то моим. В качестве альтернативы пойдет повесить как то на замыкание f мое пр-во имен.

В общем хочется, что бы при вызове функции неизвестные переменные в коде ф-ии тянулись из моего пр-ва имен (объекта, эмулирующего словарь).

★★★★★
Ответ на: комментарий от true_admin

На ночь глядя такие кошмары???

Это система для генерации кода числодробилок. В питоне вводится числ схема в виде алгебраических выражений для экземпляров хитровыкрученного класса var, при этом схема интепретатором раскручивается в AST (у var перегружены операции и пр). Затем из этого AST генерится код. Сейчас речь идет о вводе.

Схема разбита на секции. У каждого экземпляра var есть в частности тип (C-шный, при генерации кода они превращаются в поля структуры) и индекс (набор чисел) указывающий на его местоположение в пространстве-времени (не спрашивайте меня зачем это надо - это надо).

Сейчас все работает так:

mkvars('a b c', ... ) # создает a b c в текущем намеспайсе, я знаю что это плохо, но альтернатива еще хуже

section('CCC') #задаем секцию
a[1,1,1] = (a[0,1,1]+b[0,1,1])*c

Т.е. все работает через хитровыкрученные var.__get/setitem__. Чего хочется:

1) избавится от mkvar - при эмуляции намеспейса экземпляры var выдаются по необходимости.

2) перейти с a[1,0,1] на a101 - при этом опять таки разгружается var, ему не надо лазить по таблицам + упрощается синтаксис

3) группировать секции по функциям (альтернатива по кускам кода в виде строк, это это ИМНО хуже). Ф-ии вызываются при кодогенерации, возможно будет декоратор @section

4) Шоколаду, а остался только мед... в магазин идти лень;-)

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv
$ cat foo.py 
def f():
    return x + 1

$ cat bar.py
class Boo:
    def __init__(self, v):
        self.x = v

    def call_f(self):
        import foo
        foo.__dict__.update(self.__dict__)
        print foo.f()

boo = Boo(10)
boo.call_f()
$ python bar.py
11

Оно?

anonymous
()
Ответ на: комментарий от shty

Во первых, это тот еще гемор, с учетом того что у нас никто не умеет этого делать.

Во вторых, зачем писать то что уже написано - питон тут как раз не мешает а помогает (в коде можно юзать всякие питоновские конструкции). То, что кажется тут кривым, на самом деле ожин раз делается и потом прекрасно работает. У меня с такой идеологией между прочим роскошная оболочка для гнуплота работает, гоняет выражения из питона в тех и одной командой графики типографского какчества лабает;-)

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

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Вообще говоря можно, они лежат в func_code.co_names

Но это к сожалению всех проблем не решает... в частности не позволяет перехватывать конструкции вида a = ...

А так хотелось;-)

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Ну в таком случае придется ходить по AST. Или вообще свой язык сгородить.

anonymous
()
Ответ на: комментарий от AIv

Во первых, это тот еще гемор, с учетом того что у нас никто не умеет этого делать.

не пойму откуда такая неприязнь к весьма безобидному слову :)
Вы и так уже делаете трансляцию, осталось назвать теперь это своим именем и перестать насиловать питон, выдаивая из него то, чего в нём никогда не было

В третьих и главных - категорически не хочется писать еще один 100500 язык

я и не предлагаю писать язык

shty ★★★★★
()
Ответ на: комментарий от shty

тогда трансляцию откуда нам делать?;-)

Зашли бы как будете в наших краях, а то чего тут...

AIv ★★★★★
() автор топика

Как насчет такого костыля?

$ cat foo.py
def f():
    return a + b + c
$ cat bar.py
def ktulkhu(mod, f, mapping):
    globalstate = vars(mod)
    backup_globalstate = globalstate.copy()
    globalstate.clear()
    globalstate[f.func_name] = f
    flag = True
    while flag:
        try:
            f()
        except NameError, e:
            name = e.message.split("'", 2)[1]
            globalstate[name] = mapping[name]
            continue
        else:
            flag = False
        finally:
            if not flag:
                globalstate.update(dict(backup_globalstate))


import foo
ktulkhu(foo, foo.f, {'a': 1, 'b': 2, 'c': 3,})

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Только я что-то не уверен, что у меня там неймспейс foo к дефолтному виду пригодится в итоге.
Лень разбираться уже.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Я когда то так делал, когда не умел эмулировать пр-ва имен своими объектами;-)

На самом деле используемые в функции индетификаторы известны (есть кортеж в объекте кода). Но вот команды вида a = ... перехватывать не удается. Я пока склоняюсь к идее tailgunnera - выдирать из файла кусок кода отвечающий функции, и ехес-ать его как текст. Это выгялит наиболее прямым подходм в данной ситуации.

AIv ★★★★★
() автор топика
Ответ на: комментарий от Virtuos86

вот так, кажется, получше: очищаем неймспейс перед его восстановлением

...
finally:
            if not flag:
                globalstate.clear()
                globalstate.update(dict(backup_globalstate))

Virtuos86 ★★★★★
()
Ответ на: комментарий от AIv

Зашли бы как будете в наших краях, а то чего тут...

ох, с удовольствием зашёл бы на чаёк, но что-то тут беготня такая - работаю практически 18x7, и ещё столько же не хватает :)

shty ★★★★★
()
Ответ на: комментарий от shty

А я бы хотел иметь 18х21;-)

AIv ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Оказывается в модуле inspect есть много всего няшного, в т.ч. getsource() возвращает исходный код ф-ии (класса и пр.). В общем напишу декоратор который все делает - достает код ф-ии, откусывает голову и ехес-ает его в нужном окружении.

Всем спасибо за обсуждение!

AIv ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.