# -*- 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