17
«Вингардиум левиоса» Основы декларативной магии Сергей Матвеенко

"Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

  • Upload
    it-

  • View
    137

  • Download
    3

Embed Size (px)

DESCRIPTION

Матвеенко Сергей - Ведущий разработчик / Positive Technologies / Россия, Санкт-Петербург Декларативное программирование на Python, метаклассы, YAML и прочие неприятности. Популярные применения. Подводные камни. http://www.it-sobytie.ru/events/2040

Citation preview

Page 1: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

«Вингардиум левиоса»Основы декларативной магии

Сергей Матвеенко

Page 2: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

«Harry Potter and the Philosopher's Stone»

Page 3: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

http://xkcd.com/353/

Page 4: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

➢ Описания: существительные и прилагательные, а не глаголы

➢ Независимость от реализации➢ Валидация без компиляции➢ Не нужно уметь программировать➢ GUI для редактирования➢ Потому что это модно :)

Декларативное программирование

Page 5: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

➢ Декораторы➢ Метаклассы

○ Атрибуты классов○ Аргументы классов○ Аннотации аргументов методов

➢ Import hooks○ Модификация AST○ Генерация кода

➢ Внешние описания○ YAML

Декларативность в Python

Page 6: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Декораторы@this_is_decorator(safe_mode=True)def method(arg1, arg2): # we will have just a few lines here return arg1 + arg2

@abstractclassclass ObjectBase:

def foo(self): return NotImplemented

Page 7: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Метаклассы: атрибуты классовclass MyClass(ObjectBase): sequence = True sorted = False

seq = MyClass()

seq.extend([3, 2, 5])

print(seq)> [3, 2, 5]

Page 8: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Метаклассы: атрибуты классовclass ObjectMeta(type): def __new__(cls, name, bases, attrs): type_new = type.__new__(cls, name, bases, attrs) if attrs.get('sequence', False): # add sequence realization if attrs.get('sorted', False): # add sorted realization return type_new

class ObjectBase(metaclass=ObjectMeta): pass

class MyClass(ObjectBase): sequence = True sorted = False

Page 9: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Метаклассы: аргументы классовclass SequenceMeta(type): def __new__(cls, name, bases, attrs, sorted=False): type_new = type.__new__(cls, name, bases, attrs) if sorted: # add sorted realization return type_new

class SortedSequence(metaclass=SequenceMeta, sorted=True): pass

seq = SortedSequence()

Page 10: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Метаклассы: аннотацииimport inspect

class StrictMeta(type): def __new__(cls, name, bases, args): type_new = type.__new__(cls, name, bases, args) for attr_name in dir(type_new): method = getattr(type_new.attr_name) if callable(method): parameters = inspect.signature(method).parameters.values() # construct decorated method setattr(new_type, attr_name, method) return new_type

class TextNumber(metaclass=StrictMeta): value = "0" def __add__(self, value: r'[\d\.]+'): # add implementation return self.value

Page 11: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Import hooks: модификация AST# smart_sql.pyclass MyImporter: def load_module(self, name): # modify AST return modulesys.path_hooks.insert(0, MyImporter)

# prog.pyimport smart_sqlquery = (

id, Point(x, y)for id, x, yin "sql_table_name"if len([(x0, y0), (x, y)]) < 3)

Page 12: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Import hooks: генерация кода# smart_sql.pyclass MyImporter: def find_module(self, fullname, path=None): # find path to DSL source file self.path = path return self def load_module(self, name): # generate and compile python module from DSL return modulesys.meta_path.insert(0, MyImporter)

# prog.pyimport smart_sqlfrom dsl_queries import queryresult = query.find(radius)

Page 13: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

YAML# pytest-yamlwsgitest_index:

- path: / assert_status: 200 assert_contains: Hello

- path: / assert_contains: Hello

- path: / assert_status: 200

Page 14: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Django ORMfrom django.db import models

class Musician(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) instrument = models.CharField(max_length=100)

class Album(models.Model): artist = models.ForeignKey(Musician) name = models.CharField(max_length=100) release_date = models.DateField() num_stars = models.IntegerField()

Page 15: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Django class-based generic viewsclass PublisherDetail(DetailView): context_object_name = 'publisher' queryset = Publisher.objects.all()

class BookList(ListView): queryset = Book.objects.order_by('-publication_date') context_object_name = 'book_list'

class AcmeBookList(ListView): context_object_name = 'book_list' queryset = Book.objects.filter(publisher__name='Acme') template_name = 'books/acme_list.html'

Page 16: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Function annotations# http://code.activestate.com/recipes/578528/

@typecheckdef happy1(a:int, b:list, c:tuple=(1,2,3)) -> float: return 3.14

@typecheckdef happy_wo_annotation(a:int, b, c:tuple=(1,2,3)) -> float: return 3.14

@typecheckdef unhappy1(a:int, b:str) -> float: return 314 # This can never succeed in return type

Page 17: "Вингардиум Левиоса”. Или основы декларативной магии (Матвеенко Сергей)

Вопросы?

github.com/lig

ptsecurity.com