All pastes #1085001 Raw Edit

python metaprogramming demo

public python v1 · immutable
#1085001 ·published 2008-07-28 08:20 UTC
rendered paste body
# -*- coding: utf-8 -*-"""Этот модуль предназначен для самых интересных возможностей языкапрограммирования python (именно языка, для того, чтобы описать егоинфаструктуру, даже в пределах стандартной поставки, пришлось бынаписать книгу). В основном, здесь демонстрируются различные приемыметапрограмирования. Кстати, это - пример документации к модулю. Python навязываетдокументирование интерфейсов. Естественно, что эту документацию потомможно почитать, работая за пределами конкретного модуля, что широкоиспользуется, например, во всяких IDE """import functools as ftimport sys#Пример метапрограммирования на Python. Для простоты мы просто#вручную создадим класс. Хотя это можно сделать и в во время выполнения.class foo():    """Некоторый пустой класс, который мы превратим в непустой.    Кстати, это тоже пример документирования, но уже класса. """    passdef _checkValue(fun):    """Это еще одно орудие из арсенала метепрограммирования - декоратор.    Применяется здесь исключительно для проверки типа входного значения,    с целью демонстрации возможности  изменения функций или методов без    внесения изменений непосредственно в них.    Механизм декораторов основан на том, что функции в python - т.н. объекты    первого класса т.е. их можно передавать, как параметры и возвращать, как    значения. Модули, кстати, тоже объект первого класса."""    def _check(*args, **kwargs):        if 'b' in kwargs and not isinstance(kwargs['b'], str):            raise TypeError ('The argument should be an string!')        elif args[1] and not isinstance(args[1], str):            raise TypeError ('The argument should be an string!')        return fun(*args, **kwargs)    return _check@_checkValue#Здесь использован простой декоратор, без переданных в него значенийdef func0(self, b=None):    """Функция, которая просто возвращает переданные в нее значения"""    return bdef func1(self):    """Функция, которая манипулирует полями класса"""    self.someField = self.someField + 2    return self.someField#На самом деле это - тоже функция. Только анонимная. Кроме того#тут демонстрируется так называемые списочные включенияfunc2 = lambda self, value : [item for item in value]def func3(self, val=200):    """Это - демонстрация генераторов. Они запоминают точку в теле функции    из которой происходил последний вызов и при повторном вызове возвращается    в нее"""    while val > 0:        val -= 50        v = yield valdef addPrototipe(self, other):    """Перегрузка операции сложения. Тут мы опишет такую реализацию операции,    которая нам нравится. В python можно переопределить почти все, например можно    переопределить операции сравнения (= < <=; > >= == !=), так что они будут    возвращать не только истину/ложь, но вообще любой объект – список, матрицу и т.д    Само собой злоупотреблять этим не стоит.    """    if isinstance(other, foo):        try: return self.someField+other.someField        except:            raise ValueError, "Field someField not found!"def testPartial(f, s):    """Функция предназначена для демонстрации каррирования.    Каррирование (currying) -это преобразование функции от пары аргументов    в функцию, берущую свои аргументы по одному. Практическое применение    каррирования - это получение из одной функции другой функции, путем    частичного применения первой"""    return f + sdef strRunner():    """Демонстрация выполнения строки как кода"""    x = 2;    exec("""y=10for i in (1, 2):    x = x+i    print x""")    return x+y# Этот участок кода выполняется только когда запущен этот модульif __name__ == "__main__":    #Функция, которая добавляем поле или метод в класс    print dir(foo) # Пустой, пока, класс    setattr(foo, "someMethod", func0) #Добавили метод    setattr(foo, "someField", 13) #Добавили поле    setattr(foo, "someMethod1", func1) #Добавили метод    setattr(foo, "someMethod2", func2)     setattr(foo, "someGenMethod", func3)    setattr(foo, "__add__", addPrototipe)     # Это самый простой способ создавать классы во время выполнения. Для более     # изощренной работы требуется знание умение работать с метаклассами    print dir(foo) #Теперь класс не пустой    v = foo()    #И работаем с новым классом    print 1, v.someMethod("It work")    #Раскомментируйте это для проверки работы декоратора.    #print 1, v.someMethod(1)     print 2, v.someField     print 3, v.someMethod1()    print 4, v.someMethod2([1, 2, 3])    gen = v.someGenMethod()    while 1:        try:            #Последовательно вызываем генератор из func3            print "generator value", gen.next()        except StopIteration: break    #Демонстрация каррирования. В это реализовано в partial из модуля funktool    #но работает только для последнего аргумента. Интересующимся гуглить    #на тему Xoltar Toolkit.     a = ft.partial(testPartial, 1)    b = a; c = a    print "test curring-1", b(2)    print "test curring-2", b(3)    #Проверка работоспособности перегрузки функций    a = foo()    setattr(foo, "someField", 15) #Добавили поле    print "add test", a+v