Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Красота и изящность стандартной
библиотеки Python
Примеры использования
Макс Усачев
m_usachev@wargaming.net
Про группировку
элементов
Группировка элементов
Дана произвольная строка
import string
import random
RANDOM_STRING_LENGTH = 999
choices = string.asc...
Группировка элементов
Первое, что приходит людям на ум
и они так это и оставляют:
result = {}
for index in xrange(len(rand...
Группировка элементов
После тревожной ночи иногда
код становится чуть лучше:
result = {}
for index, element in enumerate(r...
Группировка элементов
А потом ты понимаешь...
Что кода слишком много!
result = {}
for index, element in enumerate(random_s...
Группировка элементов
Казалось бы, куда уже короче ...
result = {}
for index, element in enumerate(random_string):
result....
Группировка элементов
Модуль collections !
Модуль collections реализует высокопроизводительные
контейнерные типы данных.
C...
Группировка элементов
Примеры использования defaultdict
Когда фабричная функция is None
>>> from collections import defaul...
Группировка элементов
Примеры использования defaultdict
Когда фабричная функция is not None
>>> d = defaultdict(int)
>>> d...
Группировка элементов
Примеры использования defaultdict
Когда фабричная функция is not None
>>> d = defaultdict(list)
>>> ...
Группировка элементов
Теперь все ясно ;)
result = {}
for index, element in enumerate(random_string):
result.setdefault(ele...
Группировка элементов
Действительно, высокопроизводительный контейнер
Результаты timeit
Самый простой подход, (if key in r...
Про именование
Назови меня по имени
Знакомая картина?
# pure Python
elements = [
(subelement1, subelement2, ....),
(subelement11, subelem...
Назови меня по имени
Более "живой" пример
from mock import Mock
database = Mock()
database.make_query = Mock(return_value=...
Назови меня по имени
Дальше только хуже ...
{% for publication in publications %}
<div>publication[0]</div>
<span>publicat...
Назови меня по имени
Модуль collections!
namedtuple - фабричная функция для кортежей с именованными
полями.
Именованные ко...
Назови меня по имени
Как оно работает
>>> from collections import namedtuple
>>> Person = namedtuple('Person', 'name surna...
Назови меня по имени
Как оно работает еще
>>> person._asdict()
OrderedDict([('name', 'Max'), ('surname', 'Usachev'), ('age...
Назови меня по имени
Дополненный начальный пример
from collections import namedtuple
...
Publication = namedtuple('Publica...
Про сортировку
sortируй правильно
Все та же randomная строка
Знаем что и как часто
# DON'T COUNT THIS WAY
letters = [(letter, random_stri...
sortируй правильно
Самое распространенное решение
sorted(letters, key=lambda element: element[1])
sortируй правильно
Но все-таки лучше так:
sorted(letters, key=itemgetter(1))
И timeit уверен в этом!
С использованием lamb...
sortируй правильно
Модуль operator
Модуль operator предлагает набор эффективных функций,
соответствующих внутренним операт...
sortируй правильно
Как работает operator.itemgetter
>>> from operator import itemgetter
>>> getter = itemgetter(0)
>>> get...
sortируй правильно
Как работает operator.attrgetter
>>> from operator import attrgetter
>>> getter = attrgetter('name')
>>...
Про фильтрацию
filtруй правильно
Часто нужно принять решение на основе содержимого списка,
а точнее, проверить, не пустой ли он
elements ...
filtруй правильно
Для начала так:
if [element for element in elements if condition(element)]:
# do something
* Но список м...
filtруй правильно
Вот оно!
if any(element for element in elements if condition(element)):
# do something
Т.е. any вернет T...
filtруй правильно
Как работает any:
def any(iterable):
for element in iterable:
if element:
return True
return False
filtруй правильно
И если вдруг:
>>> nums = [0, 22, 15]
>>> condition = lambda x: x < 10
>>> any(num for num in nums if con...
filtруй правильно
Решение:
>>> any(condition(num) for num in nums)
True
делай все правильно
* Пишите красивый код
* Пишите правильный код (cпрашивайте себя "Не ХХХXХ ерунду ли я
пишу?")
* Изучай...
Upcoming SlideShare
Loading in …5
×

Красота и изящность стандартной библиотеки Python

5,958 views

Published on

Красота и изящность стандартной библиотеки Python.
Автор: Максим Усачев

  • 'Про сортировку' - далеко не идеальное конечное решение. Для поиска часто встречающегося символа есть collections.Counter
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Красота и изящность стандартной библиотеки Python

  1. 1. Красота и изящность стандартной библиотеки Python Примеры использования Макс Усачев m_usachev@wargaming.net
  2. 2. Про группировку элементов
  3. 3. Группировка элементов Дана произвольная строка import string import random RANDOM_STRING_LENGTH = 999 choices = string.ascii_letters + string.digits random_string = [random.choice(choices) for i in xrange(RANDOM_STRING_LENGTH)] Найти позиции каждого уникального символа этой строки в исходной строке.
  4. 4. Группировка элементов Первое, что приходит людям на ум и они так это и оставляют: result = {} for index in xrange(len(random_string)): element = random_string[index] if element in result.keys(): result[element].append(index) else: result[element] = [index]
  5. 5. Группировка элементов После тревожной ночи иногда код становится чуть лучше: result = {} for index, element in enumerate(random_string): if element in result: result[element].append(index) else: result[element] = [index]
  6. 6. Группировка элементов А потом ты понимаешь... Что кода слишком много! result = {} for index, element in enumerate(random_string): result.setdefault(element, []).append(index)
  7. 7. Группировка элементов Казалось бы, куда уже короче ... result = {} for index, element in enumerate(random_string): result.setdefault(element, []).append(index)
  8. 8. Группировка элементов Модуль collections ! Модуль collections реализует высокопроизводительные контейнерные типы данных. Counter, deque, OrderedDict и defaultdict, а также функция для создания типов данных - namedtuple(). Контейнеры, создаваемые при помощи этого модуля, представляют собой альтернативу встроенным в Python контейнерам общего назначения: dict, list, set и tuple. Документация: http://docs.python.org/2/library/collections.html#module-collections Исходный код: http://hg.python.org/cpython/file/2.7/Lib/collections.py http://hg.python.org/cpython/file/2.7/Lib/_abcoll.py
  9. 9. Группировка элементов Примеры использования defaultdict Когда фабричная функция is None >>> from collections import defaultdict >>> d = defaultdict() >>> d['foo'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'foo' new in Python v2.5 Если фабричная функция не указана, при обращении по несуществующему ключу ведет себя как обычный dict.
  10. 10. Группировка элементов Примеры использования defaultdict Когда фабричная функция is not None >>> d = defaultdict(int) >>> d['foo'] 0 >>> d['foo'] += 1 >>> d defaultdict(<type 'int'>, {'foo': 1}) >>> d['foo1'] += 5 >>> d defaultdict(<type 'int'>, {'foo': 1, 'foo1': 5})
  11. 11. Группировка элементов Примеры использования defaultdict Когда фабричная функция is not None >>> d = defaultdict(list) >>> d['foo'].append('foo') >>> d defaultdict(<type 'list'>, {'foo': ['foo']}) >>> d = defaultdict(set) >>> d['foo'].add('foo') >>> d['foo'].add('bar') >>> d['foo'].add('foo') >>> d defaultdict(<type 'set'>, {'foo': set(['foo', 'bar'])}
  12. 12. Группировка элементов Теперь все ясно ;) result = {} for index, element in enumerate(random_string): result.setdefault(element, []).append(index) Используем defaultdict result = defaultdict(list) for index, element in enumerate(random_string): result[element].append(index)
  13. 13. Группировка элементов Действительно, высокопроизводительный контейнер Результаты timeit Самый простой подход, (if key in result ...): 3.07053208351 С использованием setdefault: 3.91122484207 С использованием defaultdict: 2.63944602013
  14. 14. Про именование
  15. 15. Назови меня по имени Знакомая картина? # pure Python elements = [ (subelement1, subelement2, ....), (subelement11, subelement22, ....), (subelement111, subelement222, ....), (subelement1111, subelement2222, ....), ] # Django Model.objects.all().values_list('name', 'surname', 'age')
  16. 16. Назови меня по имени Более "живой" пример from mock import Mock database = Mock() database.make_query = Mock(return_value=[ ('Book1', 'Author1', '10/01/2001'), ('Book2', 'Author2', '10/02/2002'), ('Book3', 'Author3', '10/03/2003'), ('Book4', 'Author4', '10/04/2004'), ('Book5', 'Author5', '10/05/2005')]) publications = data.make_query() # pass publications as template context
  17. 17. Назови меня по имени Дальше только хуже ... {% for publication in publications %} <div>publication[0]</div> <span>publication[1]</span> <b>publication[2]</b> {% endfor %}
  18. 18. Назови меня по имени Модуль collections! namedtuple - фабричная функция для кортежей с именованными полями. Именованные кортежи позволяют определить имена для каждой позиции в кортеже. Использование именованных кортежей позволяет создавать более читаемый и понятный код. Они могут быть использованы в тех же случаях, что и обычные кортежи, а обращаться к полям можно не только по индексу, но и по имени. Именованные кортежи используют памяти не больше, чем обычные кортежи. new in Python v2.6
  19. 19. Назови меня по имени Как оно работает >>> from collections import namedtuple >>> Person = namedtuple('Person', 'name surname age') >>> person = Person(name='Max', surname='Usachev', age=25) >>> person = Person('Max', 'Usachev', 25) >>> person.name, person.surname, person.age ('Max', 'Usachev', 25) >>> person[0], person[1], person[2] ('Max', 'Usachev', 25)
  20. 20. Назови меня по имени Как оно работает еще >>> person._asdict() OrderedDict([('name', 'Max'), ('surname', 'Usachev'), ('age', 25)]) >>> Person.full_name = property(lambda self: ' '.join((self.name, self.surname))) >>> person.full_name 'Max Usachev' >>> Person._make(('Max', 'Usachev', 25)) Person(name='Max', surname='Usachev', age=25) >>> Person._fields ('name', 'surname', 'age')
  21. 21. Назови меня по имени Дополненный начальный пример from collections import namedtuple ... Publication = namedtuple('Publication', 'name author date') publications = map(Publication._make, database.make_query()) {% for publication in publications %} <div>publication.name</div> <span>publication.author</span> <b>publication.date</b> {% endfor %}
  22. 22. Про сортировку
  23. 23. sortируй правильно Все та же randomная строка Знаем что и как часто # DON'T COUNT THIS WAY letters = [(letter, random_string.count(letter)) for letter in set(random_string)] Какой символ встречается чаще всего?
  24. 24. sortируй правильно Самое распространенное решение sorted(letters, key=lambda element: element[1])
  25. 25. sortируй правильно Но все-таки лучше так: sorted(letters, key=itemgetter(1)) И timeit уверен в этом! С использованием lambda: 4.4638299942 С использованием itemgetter: 3.61604499817
  26. 26. sortируй правильно Модуль operator Модуль operator предлагает набор эффективных функций, соответствующих внутренним операторам Python: - add(a,b) - div(a, b) - not(a) - ... А также такие полезные функции, как: - attrgetter(*attrs) - itemgetter(*items) - methodcaller(name[, args...]
  27. 27. sortируй правильно Как работает operator.itemgetter >>> from operator import itemgetter >>> getter = itemgetter(0) >>> getter('abc') 'a' >>> getter([0, 1, 2]) 0 >>> getter = itemgetter(0, -1) >>> getter('abc') ('a', 'c') >>> getter([1, 2, 3]) (1, 3) new in Python v2.4
  28. 28. sortируй правильно Как работает operator.attrgetter >>> from operator import attrgetter >>> getter = attrgetter('name') >>> class Foo(object): pass >>> foo = Foo() >>> foo.name = 'foo' >>> getter(foo) 'foo' >>> foo.weight = 20 >>> getter = attrgetter('name', 'weight') >>> getter(foo) ('foo', 20) new in Python v2.4
  29. 29. Про фильтрацию
  30. 30. filtруй правильно Часто нужно принять решение на основе содержимого списка, а точнее, проверить, не пустой ли он elements = [...] condition = lambda x: ... if len([element for element in elements if condition(element)]): # do something
  31. 31. filtруй правильно Для начала так: if [element for element in elements if condition(element)]: # do something * Но список может быть большим * А если нашли первый подходящий элемент, то зачем искать дальше? Напрашивается решение на основе генераторов!
  32. 32. filtруй правильно Вот оно! if any(element for element in elements if condition(element)): # do something Т.е. any вернет True как только встретит первый трушный элемент Внимание, вопрос: что тут не так?
  33. 33. filtруй правильно Как работает any: def any(iterable): for element in iterable: if element: return True return False
  34. 34. filtруй правильно И если вдруг: >>> nums = [0, 22, 15] >>> condition = lambda x: x < 10 >>> any(num for num in nums if condition(num)) False
  35. 35. filtруй правильно Решение: >>> any(condition(num) for num in nums) True
  36. 36. делай все правильно * Пишите красивый код * Пишите правильный код (cпрашивайте себя "Не ХХХXХ ерунду ли я пишу?") * Изучайте стандартную библиотеку Python * Используйте collections, operator, itertools ... * Приходите снова!

×