Доступ к готовым решениям

Переход в группу "Пользователь"

300.00 ₽
Одноразовый платёж
Быстрый переход в группу "Пользователи", без надобности написания постов и ожидания.

Покупка дает возможность:
Быть полноправным участником форума
Нормальное копирование кода
Создавать темы
Скачивать файлы
Доступ к архиву Pawno-Info

Python Функтор с генерацией байтокода

Статус
В этой теме нельзя размещать новые ответы.

#Gromov

Мастер
Пример эффективной реализации функтора, основанный на генерации байтокода во время исполнения. Этот пример демонстрирует следующие возможности/особенности Python:

Возможность реализации специфических средств функционального программирования наработками, уже имеющимися в языке
-Работать с байтокодом в Python достаточно просто
-Зачастую генерация байтокода способна значительно ускорить исполнение.
-то только пример, он реализует всего одну операцию — сложение и имеет несколько других ограничений.


PHP:
#-------------------------------------------------------------------------------
import byteplay        # специальный модуль для удобной работы с Python-байтокодом
import new             # для создания функции во время исполнения
import functools       # для update_wrapper
import inspect         # для получения информации о параметрах, принимаемых функцией
#-------------------------------------------------------------------------------
class FastFunctor(object):
    def __init__(self,func,code = None):
        self.func = None                # здесь будем хранить результирующую функцию
        self.ofunc = func               # а здесь исходную(original) функцию
        if code is None:     
            # конструируем байтокод для вызова функции
            self.code = [(byteplay.LOAD_CONST,func)]
            rparams = inspect.getargspec(func)[0] # получаем список параметров, принимаемых функцией
            self.code.extend((byteplay.LOAD_FAST,i) for i in rparams)
            self.code.append((byteplay.CALL_FUNCTION,len(rparams)))
        else:
            # если же функтор создан из другого функтора, 
            # то только копируем переданный байтокод
            self.code = code
        # создаем новый объект кода
        self.ocode = bp.Code.from_code(func.func_code)
    def __add__(self,obj):   # этот метод вызывается для операции '+'
        code = self.code[:]  # копируем байтокод
        if isinstance(obj,FastFunctor):  # если прибавляемый объект - функтор
            # просто дописываем его код к нашему
            # после своего исполнения он "оставит" в вершине стека результат
            code.extend(obj.code) 
        else:
            # иначе загружаем объект в стек
            code.append((byteplay.LOAD_CONST,obj))
        # дописываем байтокод, складывающий два верхних элемента в стеке
        code.append((byteplay.BINARY_ADD ,None )) 
        # создаем новый функтор, с байтокодом получения суммы
        return self.__class__(self.ofunc,code = code)
    def __call__(self,*dt,**mp):        # этот метод будет вызван для операции вызова object()
        return self.fast()(*dt,**mp)    # конструируем и вызываем функцию
    def fast(self): # конструируем функцию из байтокода
        if self.func is None:           # если функция не была создана раннее
            code = self.code + [(bp.RETURN_VALUE,None)] # добавляем байтокод возврата
            oc = self.ocode
            # создаем объект кода из байтокода и другой информации
            bin_code =  byteplay.Code(code,
                                oc.freevars,
                                oc.args,
                                oc.varargs,
                                oc.varkwargs,
                                oc.newlocals,
                                "<just_code_%s>" % id(self),
                                "<auto_gen_%s>" % id(self),
                                0,
                                "auto_generated code")
            # конструируем новую функцию из объекта кода
            self.func = new.function(bin_code.to_code(),globals())
            # после этой операции для всех средств интроспекции 
            # созданная функция будет выглядеть как оригинальная
            self.func = functools.update_wrapper(self.func,self.ofunc)
        return self.func
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху Снизу