Tuesday, February 28th, 2012
Долго не писал, был крайне занят в разных проектах, получая madskillz в различных областях программирования. Ну что могу сказать, программировать мне пока нравится больше чем предыдущие занятия SEO. Сама оптимизация канешно весьма полезное умение и имеет скажем так прикладное значение, но я считаю трЪ вебмастер должен уметь собственно делать сайты. Причем не на вордпрессе или на какой-нибудь сраной point-and-click CMS, а уметь писать легковесные, быстрые, заточенные под задачу решения.
Это было интро, собственно переходим к сути статьи. Итак, как правило программист нуждается в редакторе в котором он будет набирать код. Некоторые предпочитают огромный монстроподобные, тяжеловесных, кросплатформенных java-IDE (eclipse, netbeans и т.д.) весь функционал которых как правило не исползуется, в то время лаги gui достаточно ощутимы, кто бы что не говорил. Однако линуксу уже не первый год и на нем существуют достаточно хорошие нэйтивные решения, которым уже по 30 (с хуем) лет, но которые тем не менее активно развиваются и многие предпочитают набирать код именно в этих редакторах, я имею в виду Emacs и Vim. Звезды сложились так что я стал использовать emacs, сначала для того чтобы набирать небольшие программки параллельно с netbeans, затем понял что netbeans мне уже не нужен.
Собственно уже не первый раз устанавливая Ubuntu на разные компьютеры я сталкиваюсь с необходимостью заново создавать рабочее окружение Emacs’а.
И вот в очередной раз решил записать последовательность действий.
Установка и настройка Emacs для разработки на Python

Для начала все свои настройки и плагины я храню в репозитории на гитхабе, который доступен мне из любой точки мира где есть интернет.
Сперва поставим сам емакс, открываем терминал и пишем:
sudo apt-get install emacs
Поставим гит если его нет (а если система совсем новая то нужно еще перед этим сделать sudo apt-get update)
user@machine:~$ sudo apt-get install git-core
Coбственно осталось кланировать репозиторий куда-нибудь в папке юзера.
user@machine:~$ cd ~
user@machine:~$ mkdir temp
user@machine:~$ cd temp
user@machine:~$ git clone https://github.com/istinspring/iemacs
Затем копируем файлы конфигурации в папку юзера
user@machine:~$ cp -r iemacs ~/.emacs.d
user@machine:~$ cd iemacs
user@machine:~$ cp .emacs ~/.emacs
Если сейчас запустить Emacs он покажет ошибку, т.к. нет нужных плагинов.
Ставим их:
user@machine:~$ sudo apt-get install pymacs
user@machine:~$ sudo apt-get install python-ropemacs
user@machine:~$ sudo apt-get install python-mode
Все. Остальные плагины уже установленны в папочке. Я использую минимальный набор плагинов, хотя можно при желании наворотить очень много всякого, и проверку синтаксиса на лету и соответствие PEP8.
YASnippets – сниппеты. очень удобно вбить туда повторяющиеся паттерны кода. Например у меня вбиты сниппеты для быстрого создания скелета паука – grab:spider.
Autocomplete – тут и сказать нечего автокомплит. Так же ускоряет процесс набивание кода.
Далее можно начать разбираться и потихоньку выстраивать удобное окружение для работы с кодом.
Posted in Code, Linux, Notes, Python | 4 Comments »
Monday, July 4th, 2011
Soooo, mini-cms for mfa sites – на жанге! Джанго отличный фреймворк (говорят даже что это один из лучших продуктов что сейчас вообще есть), там предусмотрено все что нужно для быстрой разарботки веб-сайтов, каждая мелоч, а философия фрэймворка предполагает многократно использовать приложения (apps почти как плагины в вордпрессе) которых наваяли уже тысячи и почти все что может понадобится можно найти на гитхабе и без проблем подключить на свой сайт.
Вообщем какие требования для начала к mini cms?
- Желательно иметь возможность менять themes. Ок, не вопрос.
- Урлы вида http://site.com/article-name или http://site.com/category/article-name
- сайтмап
- рсс фид
Предлагайте в комментах, что еще можно добавить.
Чтобы быстро начать я воспользовался уже готовым шаблоном для проектов который я составил для себя и любезно выложил на гитхб – базовый шаблон для django сайта.
Можно скопировать себе, поставить джангу и поиграться, на линуксе все просто, поставил git и…
git clone https://github.com/istinspring/mini-cms-for-mfa.git mini-cms-for-mfa
Как там в виндовс, хз, win как платформа не предназначена для вебразработки, линукс гораздо удобнее и все к чему вы привыкли на винде, кроме игр, есть и на линуксе.
Описание, фичи, процесс разработки
Ситуацию с земами (themes) разруливал впервые, поэтому пришлось поэкспериментировать. Хотел сначала написать themes engine который отдавал файлы в соответствии с текущей активной темой, типа как в вордпрессе, но это долго, мутно и генерирует лишние запросы к базе данных, что как бы не очень круто. Поэтому решил сделать по другому, оптимальным решением, как мне кажется будет загружать зип архив с темой, файлы из которого при активации будут копироваться в соответствующие папки django, таким образом cms лишний раз не будет обстукивать sqlite базу данных, но при этом можно легко поменять текущий зем и загрузить новый.
Сам движок cms на джанге писать одно удовольствие. Я уже кучу раз делал подобное в своих проектах и теперь просто модифицировал/доработал/улучшил код который у меня был. Тут все просто – нужно создавать страницы которые будут отображаться в соответствии с заданными категориями, или без них (подумал что сайт вполне может разрастись до 50 страниц, а как бы 50 страниц уже нуждаются в сортировке по каким-то признакам).
Для создания RSS и Sitemap фрэймворк django любезно предоставляет удобные инструменты которыми я воспользовался. Ммм… что еще? Написал контекст процессор который передаёт данные по сайту и категориям при рендере каждой страниц, это позволяет достаточно просто создавать новые земы на основе произвольного html кода, прописывая логику отображения элементов сайта.
Почти готово…
Стал писать с момента публикации прошлого поста, с перерывами, естественно на сон, покушать и бытовые нужды, сегодня с утра пушнул проект в репозиторий на гитхабе, поднял демо сайт на сервер и написал пост. Вроде получилось неплохо, а главное быстро на пределе возможностей, что всегда означает массу опыта и дальнейшее развитие навыков.
Вообщем вот демо – mini-cms-for-mfa demo site
Вот код – Mini CMS for MFA
Логин/Пасс – test/test вход в админку через http://wtfisgoingon.co.cc/admin
Уже есть идеи по поводу улучшений :
- сделать менеджер рекламы (чтобы рулить размещением из админки)
- добавить темлейт тэги чтобы можно было очень просто обозначить рекламные блоки и какие-либо элементы интерфейса внутри шаблона
- статистику
- апи интерфейс
- рендер в статику, чтобы эту статику потом размещать где угодно
- интерфейс для добавления ссылок в сайдбар
- кэширование
Если у кого-то есть пожелания, то пишите в комменты или на мыло, как будет время доработаю.
Posted in Advertising, OpenSource, Python | 10 Comments »
Wednesday, June 29th, 2011
Дело было вечером делать было нечего…
Но на самом деле делать всегда есть что и как правило времени катострофически не хватает. Вот и на этот раз появилась идея совместно с lorien‘ом сделать сайт-каталог предприятий, чтобы он индексировался поисковыми системами и приносил траффик в дальнейшем возможно превратившись во что-то полезное для пользователей.
Собственно сам сайт – Каталог предприятий Екатеринбурга.
Что внутри? Как это делалось?
Сайт решили сделать заточенным под конкретный регион – с учетом того, что в региональной выдаче с топом как-то попроще. К тому же подобных сайтов можно сделать много – под каждый город. + в этом случае можно повесить на сайт фиды от региональных форумов, погоду от gismeteo и т.д. Т.е. первое требование писать не сколько сам сайт – сколько простой двиг.
Изначально, как это принято у серьезных людей был обстоятельно составлен план действий и техническое задание – с помощью google documents. Если кто забыл – гугл докс позволяет одновременно работать над документом нескольким пользователям. С помощью этого инструмента удалось учесть множество факторов еще на этапе планирования.
Как правило любой проект без должной мотивации разваливается если делается долго, ну я имею в виду программирование, поэтому ограничить цикл разработки одной неделей – очень хорошая идея.
Для совместной работы над кодом был создан приватный репозиторий на bitbucket, я уже писал о нём.
Где взять данные для сайта? Для начала можно спарсить, был написан бот с использованием scrapy который ползал по сайтам и писал данные в базу данных используя SQLAlchemy. Затем эта база данных перегонялась в нужный формат django модели, естественно не сама а с помощью написанной для этого утилиты.
Далее на основе полученной базы данных писался фронтенд на Django, с текстом и яндекс картами (yandex maps api). Одна из “фишек” – генерация QR кодов, которые можно считать с помощью современных гаджетов (мобилы, планшета). Для генерации кодов использована библиотека PyQRNative, по возможности в формате MECARD – созданном специально для организаций.
На сайте есть поиск, поисковый индекс был составлен с помощью Xapian и Haystack
Вариантов развития можно придумать очень много : форма “добавить предприятие в каталог”, раздел “объявления”, но для начала нужно развернуть еще парочку и подождать пока поисковые системы все это проиндексируют.
Posted in Advertising, Mashup | 3 Comments »
Tuesday, May 31st, 2011
Давным-давно, в доисторические времена, программистам приходилось изучать и конструировать сложные запросы к реляционным базам данных, что несколько усложняло работу с базой данных. А когда появилось ООП увязать SQL запросы, код и новый стиль программирования стало еще сложнее. Впрочем, многие пхп проекты как-то обходятся и без ORM, что несомненно свидетельствует о высоком скилле и безмерном трудолюбии разработчиков.
Итак что же такое ОРМ (orm)? Это не более чем абривиатура от Object Relational Mapping и по простому обозначает работу с таблицами баз данных как с объектами языка программирования. ОРМ является по сути дела высокоуровневой надстройкой над драйвером БД который переводит ваши запросы в язык SQL; может быть где-то и проигрывая в производительности, но зато существенно упрощая разработку и поддержку проектов, делая работу с базами данных простой и понятной.
ORM (англ. Object-relational mapping, русск. Объектно-реляционное отображение) — технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования, создавая «виртуальную объектную базу данных». Существуют как коммерческие, так и свободные реализации этой технологии.
На текущем этапе своей карьеры программиста я использую sqlite практически в каждом скрипте, это гораздо удобнее и быстрее чем работать с кучей текстовых файлов. Если возникает потребность в редактировании данных – нет проблем существует отличный плагин для FF – http://code.google.com/p/sqlite-manager/
Итак к делу. Для питона есть отличная реализация ORM с подробнейшей документацией – SQLAlchemy
Базово работа с БД выглядит так :
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine
from sqlalchemy import MetaData
from sqlalchemy.orm import mapper
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, Text, String
Base = declarative_base()
# определяем формат таблицы в БД.
# как бы пост для блога.
class CData(Base):
__tablename__ = 'cdata'
id = Column(Integer, primary_key=True)
url = Column(String)
image = Column(String)
title = Column(String)
text = Column(Text)
def __init__(self, url, image, title, text):
self.url = url
self.image = image
self.title = title
self.text = text
def __repr__(self):
return "CData '%s'" % (self.url)
db_engine = create_engine('sqlite:///data.db', echo=True)
# создадём таблицы
Base.metadata.create_all(db_engine)
# начинаем новую сессию работы с БД
Session = sessionmaker(bind=db_engine)
session = Session()
# таким образом можно добавить новый элемент
new_element = CData("http://blog.com", "http://coolpix.com/img434.jpg", "Nice Post", "Mark spomoni as a faggot")
session.add(new_element)
# посмотрим что уже есть в базе данных
for instance in session.query(CData).order_by(CData.id):
print instance.title
# совершаем транзакцию
session.commit()
Как видите все достаточно просто. Работать с базой данных становится так же легко и естественно как и со структурами языка программирования. В современных фрэймворках для разработки сайта так или иначе используется ОРМ, в джанге это своя реализация django-orm, но во множестве других, таких как flask, pyramids используется как раз SQLAlchemy.
Дополнительные материалы.
Еще одна хорошая статья на русском языке SQLAlchemy: как втянуться
Официальная документация SQLAlchemy
Posted in Code, Python | No Comments »
Saturday, May 21st, 2011
Многие (почти все) используют такую замечательную библиотеку как curl (ну, или в нашем случае pycurl), работать с ней конечно можно – но не слишком удобно. Приходится думать о разных вещах – куках, установке параметров и т.д. а ведь это время и в конечном итоге – деньги. Как правило, на определенном этапе многие пишут свои “функции” разной степени кривости облегчающие работу с curl’ом .
Однако грамотные программисты предпочитают реюзать чужой код и не изобретать колесо, особенно в том случае если он хорошо написан и часто обновляется.
(установка в убунте – sudo pip install grab)
Grab идеально подходит для большинства типичных задач (парсинг, регистрации), фактически освобождая программиста от рутины прямой работы с курлом и значительно сокращает размер кода. Я бы сказал, что Grab в какой-то степени эмулирует браузер (естественно без js). Итак, что внутри?
- Отправка разных HTTP запросов
- Обработка HTTP ответа
- Парсинг и заполнение HTML форм
- Работа с HTML DOM через XPath.
- XPath для обхода html
Использование XPath сильно упрощает задачу выбора элементов, это гораздо более удобно чем иметь дело с мутными регулярками.
Более подробно про XPath - http://www.w3schools.com/xpath/default.asp
В качестве примера – простой код.
# выделяем каждый элемент td с классом "postbody"
for item in document.xpath('//td[@class="postbody"]//'):
print item.text
Документация по Grab достаточно подробна, примеры использования тут и тут (в этих примерах граб создается в объекте parser). Как орудовать самим грабом можно посмотреть тут (парсинг форума), пример не рабочий, сразу предупреждаю, служит только для наглядной демонстрации того как можно его использовать.
Posted in Code, OpenSource, Python | No Comments »
Sunday, May 8th, 2011
Решил потратить свободное воскресенье на написание чего-нибудь интересного, размять мозги, освоить какие-нибудь новые приемы, короче говоря разбавить рутину повседневных дел. Задача достаточно тривиальна – написать аналог Hello World используя генетические алгоритмы.
Выложил код на github – Hello World генетическими алгоритмами. Там же лог где можно посмотреть как происходит решение задачи.

Что представляют собой эти генетические алгоритмы? Они решают задачи точно так же как это делает природа, т.е. через “естественный отбор”, соответственно критерии этого отбора должны быть достаточно просто вычисляемы – в моём случае это так называемая fitness функция которая посимвольно сравнивает решение с оригинальной строкой, чем лучше решение – тем ближе выход функции к нулю.
def fitness(dnk, goal):
f = 0
for index, gene in enumerate(dnk):
if gene != goal[index]:
f -= 1
return f
Решение задачи представляется в виде вектора значений [a, b, c, d, ..., x] (в нашем случае это строка) длина которого известна, я обернул это в класс методы которого предоставляют интерфейс для взаимодейтсвия (class GeneticCode), на начальном этапе создаётся “популяция” (скажем 100) этих векторов инициализируемых случайными значениями.
self.pool = [GeneticCode(goal=goal) for item in range(self.pool_size)]
Затем fitness функция делает оценку каждого вектора популяции в коде, и далее лучшие образцы (скажем 10% от всей популяции) переходят на следующий круг. Существуют разные вариации генетических алгоритмов, кто хоть немножко разбирается в биологии и знает как происходит естественный отбор без труда могут придумать различные улучшения. Напоминаю, на данный момент у нас, после “естественного отбора” осталось 10% от популяции, где-то нужно взять остальные 90%, я решил на этом этапе провести “скрещивание”, т.е. различные простейшие рекомбинации исходных векторов данных (одна часть берется от одного вектора, другая от второго и в результате получается, что-то новое). Детали этого этапа реализованы в методе def darvin(self, winners=0.1) класса GenePool.
Далее происходит “эволюция”, т.е. кажый вектор испытывает какие-то случайные мутации (не затрагивая те элементы которые уже совпадают с оригинальной строкой). Затем опять приходит старик Дарвин, выбирает лучшие решений и процесс начинается заново. И так до тех пор пока решение не будет найдено. Если строка достаточно длинная + популяция мала и слишком много решений проходит отбор – генетический алгоритм может работать очень долго, поэтому неплохо будет ограничить кол-во итераций, скажем 1000 будет вполне достаточно.
Собственно классический “Hello world” получился примерно так (каждая строчка – лучший результат на каждом шаге) :
s(_soclbi!P*
{k&soclbil^!
oiYloC>otPC!
Evlso$>oil^!
EvlmoC>oild!
oil!oC>orld!
?vlloC>orld!
?elloCqorld!
GelloCqorld!
GelloCqorld!
Tello qorld!
oello qorld!
Tello world!
Tello world!
Tello world!
Hello world!
Естественно я только немного коснулся этой темы, спектр применений генетических алгоритмов достаточно широк, в том числе их используют совместно с нейросетями.
- Оптимизация функций
- Оптимизация запросов в базах данных
- Разнообразные задачи на графах (задача коммивояжера, раскраска, нахождение паросочетаний)
- Настройка и обучение искусственной нейронной сети
- Задачи компоновки
- Составление расписаний
- Игровые стратегии
- Теория приближений
- Искусственная жизнь, проекты типа EvoGrid
- Биоинформатика (свертка белков)
Для тех кто хочет попробовать, есть уже готовые библиотеки для python которые избавят вас от рутины написания лишнего кода.
http://www.freenet.org.nz/python/pygene/
http://pyevolve.sourceforge.net/
Posted in Code | No Comments »
Tuesday, March 22nd, 2011
Очень часто нужно обработать файл и удалить дубли. Особенно это актуально при работе с кейвордами и урлами. Самый быстрый (без шуток!) способ сделать это – использовать следующий скрипт.
# -*- coding: utf-8 -*-
__author__ = "istinspring"
__version__ = "1.0"
import os
import sys
import time
import logging
from optparse import OptionParser
logger = logging.getLogger('uniqkeylist')
def uniq(seq):
"""The fastest way to unique list"""
seen = set()
seen_add = seen.add
return [ x for x in seq if x not in seen and not seen_add(x)]
def main():
usage = '%s [options] [source]' % sys.argv[0]
parser = OptionParser(usage)
parser.add_option('-d', '--dst', default='',
help='redirect logs to file')
parser.add_option("-l", "--log", default="-",
help="Write logs to file (default: stdout)")
opts, args = parser.parse_args()
# setup logging
if opts.log == "-":
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
else:
logging.basicConfig(stream=opts.log, level=logging.DEBUG)
if args:
src = os.path.abspath(args[0])
if not os.path.isfile(src):
logger.info("Can't locate file")
sys.exit(1)
else:
logger.info("Enter source filename")
sys.exit(1)
# open source file
try:
with open(src, "r+") as f:
lines = f.readlines()
except IOError:
logger.info("Can't open file")
sys.exit(1)
result = uniq(lines)
logger.info("In\t:\t{0}".format(len(lines)))
logger.info("Out\t:\t{0}".format(len(result)))
dst = opts.dst or (os.path.splitext(src)[0] + ".unq")
# save result
try:
with open(dst, "w+") as f:
for item in result:
f.write(item)
except IOError:
logger.info("Can't save file")
sys.exit(1)
start_time = time.time()
main()
print "Elapsed time:\t%s" % (time.time() - start_time)
использовать python scriptname.py имя файла
Posted in Code, Python | 2 Comments »
Monday, December 13th, 2010
Как получить список всех папок и файлов в определенной директории? Очень просто – используя функцию os.walk()
import os
def getsubs(dir):
# get all
dirs = []
files = []
for dirname, dirnames, filenames in os.walk(dir):
dirs.append(dirname)
for subdirname in dirnames:
dirs.append(os.path.join(dirname, subdirname))
for filename in filenames:
files.append(os.path.join(dirname, filename))
return dirs, files
Posted in Code, Python | 2 Comments »
Sunday, December 5th, 2010
В рамках программы публикации полезных сниппетов (кусочков кода). Распространенная задача – нужно собрать все URL со страницы, например, это нужно чтобы спарсить сайт. Для разбора xml/html есть замечательная библиотека – BeautifulSoup, которая будет работать даже в том случае, если документ не валидный (с ошибками, типа пропущены тэги, перепутан порядок и т.д.) Воспользуемся BeautifulSoup и Python’ом :
# get all urls
import BeautifulSoup
def get_all_urls(html):
soup = BeautifulSoup.BeautifulSoup(html)
urls = [tag['href'] for tag in soup.findAll('a')]
result = []
for val in urls:
if (val[:7] == "http://") or (val[:8] == "https://"):
result.append(val)
return result
или так (с помощью filter и lambda):
# get all urls
import BeautifulSoup
def get_all_urls(html):
soup = BeautifulSoup.BeautifulSoup(html)
urls = [tag['href'] for tag in soup.findAll('a')]
f = lambda x: True if (x[:7] == "http://") or (x[:8] == "https://") else False
return filter(f, urls)
Posted in Code, Python | 4 Comments »
Thursday, November 25th, 2010
Бывает различные сервисы используют url-прокладку тем самым скрывая оригинальный url ссылки, а узнать оригинальный урл очень хочется. Примеров масса – различные сервисы сокращения ссылок (shorurl), ссылки feedburner через feedproxy.google.com. Короче, очень жизненный пример : мне нужно получать данные из кучи RSS, часть из них проходит через этот самый feedburner который преобразует ссылки таким образом – http://feedproxy.google.com/~r/somesite/~3/H_xFNwC1ikE/ не, ну это блядство, срочно нужна ссылка на оригинал.
Как получить оригинальный url ссылки shorturl?
Делается это элементарно, дергаем этот линк, проходим все редиректы и возвращаем тот url куда в конечном итоге пришли.
Используя urllib2. Самый простой метод, поэтому наиболее предпочтительный.
import urllib2
fp = urllib2.urlopen('http://feedproxy.google.com/~r/somesite/~3/H_xFNwC1ikE/')
print fp.geturl()
Используя httplib. Замороченный, нужно разбивать урл на части, что как бы не очень удобно.
import httplib
""" http://feedproxy.google.com/~r/somesite/~3/H_xFNwC1ikE/ """
conn = httplib.HTTPConnection('feedproxy.google.com')
conn.request('HEAD', '/~r/somesite/~3/H_xFNwC1ikE/')
response = conn.getresponse()
print response.getheader('location')
Используя культовый curl
import pycurl
conn = pycurl.Curl()
conn.setopt(pycurl.URL, 'http://feedproxy.google.com/~r/somesite/~3/H_xFNwC1ikE/')
conn.setopt(pycurl.FOLLOWLOCATION, 1)
conn.setopt(pycurl.CUSTOMREQUEST, 'HEAD')
conn.setopt(pycurl.NOBODY, True)
conn.perform()
print conn.getinfo(pycurl.EFFECTIVE_URL)
Кстати, первый спамм на .РФ – онлайн-гипермаркет.рф
Posted in Code, Notes, Python | No Comments »
Thursday, November 25th, 2010
Первая пачка ответов на вопросы из этого поста. Тут все элементарно, если знать немножко про функциональное программирование и ориентироваться в стандартных функциях.
1. Как получить список всех атрибутов объекта?
Очень просто, используя стандартную функцию dir. В качестве аргумента передаем тот самый объект, в данном случае (ради примера) объект string.
import string
print dir(string)
# Или так
import inspect
print [name for name,thing in inspect.getmembers(string)]
Модуль inspect предоставляет несколько очень классных методов которые позволяют собирать информацию о объектах Python.
Используя inspect можно получить содержимое класса. получить исходный код метода, выделить формат и список аргументов функции и т.д.
2. Как получить список всех публичных атрибутов объекта?
Private методы в Python начинаются с “__” поэтому все что нужно сделать чтобы получить список публичных это отфильтровать все что начинается с “__”. Тут будут очень к месту элементы функционального программирования – функция filter(f, lst) которая формирует новый список элементов последовательности – lst руководствуясь функцией f.
import sting
# так проще для понимания
def f(x):
if x[:2] == "__":
return False
else:
return True
print filter(f, [atr for atr in dir(string)])
# а это то же самое в одну строчку
print filter(lambda x : False if not cmp(x[:2], "__") else True, [atr for atr in dir(string)])
3. Как получить список методов объекта?
Используя функцию callable() которая как бы говорит реально ли вызвать объект или нет. если вызвать реально – то это метод, если нет – то свойство
print filter(lambda x : callable(getattr(string, x)), [atr for atr in dir(string)])
4. В какой “магической” переменной хранится содержимое help?
В __doc__
print string.__doc_
5. Есть два кортежа, получить третий как конкатенацию первых двух.
Элементарно.
a = (1,2)
b = (3,4)
print a + b
6. Есть два кортежа, получить третий как объединение уникальных элементов первых двух кортежей.
Сначала преобразуем конкатенацию (операция склеивания объектов линейной структуры, обычно строк) в объект – множество (элементы которого уникальны, т.е. не могут повторятся, это свойство объекта) а затем преобразуем обратно в кортеж.
a = (1,2,3)
b = (5,3,6)
print tuple(set(a + b))
7. Почему если в цикле меняется список, то используется for x in lst[:], что означает [:]?
[:] означает, что берется копия списка и далее делается цикл по его элементам, таким образом получаем возможность работать с оригинальным списком, без опасений что изменения в нем повлияют на работу цикла.
a = [1,2,3,4]
print a
for i,elem in enumerate(a[:]):
a[i] = elem * elem
print a
8. Есть два списка одинаковой длины, в одном ключи, в другом значения. Составить словарь.
Преобразуем в пары (a,1) и т.д. c помощью zip и далее преобразование в тип данных – словарь с помощью функции dict()
a = ['a','b','c']
b = [1,2,3]
print dict(zip(a,b))
9. Есть два списка разной длины, в одном ключи, в другом значения. Составить словарь. Для ключей, для которых нет значений использовать None в качестве значения. Значения, для которых нет ключей игнорировать.
Посидел, полумал, записал в одну строчку. Все просто если немножко понимать основы функционального программирования. Наверняка можно записать короче.
# можно так но тогда не выполняется 2ая часть условия. игнорирование значений для которых нет ключей.
a = ['a','b','c','d']
b = [1,2,3]
print dict(map(None, a, b))
a = ['a','b','c']
b = [1,2,3,4]
# выполняет все требования задания.
print dict(filter(lambda x : False if x is False else True, map(lambda x, y : (x, y) if x is not None else False, a, b)))
10. Есть словарь. Инвертировать его. Т.е. пары ключ: значение поменять местами — значение: ключ.
На помощь приходит метод items() который возвращает элементы словаря в виде кортежа (в виде пар) – (key, value)
a = {'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4}
print dict([(y,x) for (x,y) in a.items()])
11. Есть строка в юникоде, получить 8-битную строку в кодировке utf-8 и cp1251.
str = u'unicode sting'
print str.encode('utf-8')
print str.encode('cp1251')
12. Есть строка в кодировке cp1251, получить юникод строку.
str = 'cp1251 string'
print str.decode('cp1251')
Чтобы более детально осознать о чем идет речь :
http://docs.python.org/library/inspect.htm
http://docs.python.org/reference/datamodel.html
http://docs.python.org/tutorial/datastructures.html
http://docs.python.org/library/stdtypes.html
http://docs.python.org/library/functions.html
http://docs.python.org/howto/unicode.html
Posted in Code, Python | 1 Comment »
Thursday, November 25th, 2010
Рыская по просторам интернетов, натолкнулся на “Вопросы и задания по Python”. Польза этих вопросов очевидна – подобные задания могут предлагать вам в качестве теста на человека который более менее разбирается в вопросе. + ответы на эти несложные вопросы помогут вам систематизировать свои знания.
Полностью список можно найти тут http://pyobject.ru/blog/2010/02/04/python-quiz/
Вопросы и задания по Python
- Типы данных, основные конструкции
- Функции
- Итераторы
- Модули
- Классы
- Метаклассы и дескрипторы
Posted in Code, Notes, Python | 1 Comment »
Saturday, November 20th, 2010
Для тех кто ранее изучал php и привык к тому, что код как бы встраивается в страницу при переходе на Python становится актуальным вопрос : а как сделать подобное на Pyhton? Тут сделано немного не так, но тоже достаточно удобно. Дело в том, что Python изначально проектировался как полнофункциональный язык программирования, в отличии от PHP забацаного чтобы студенты могли по быстрому написать Home Page (aka хомяк). Существует несколько подходов к тому как отображать контент в веб :
- Модель статических страниц (static page model). В первой половине 90х годов все страницы веба были статическими, то есть содержали в себе готовый документ в формате HTML. Соответственно, страницы не требовали предварительной обработки и не зависели от аргументов.
- CGI — сценарии. Исполняемые на сервере программы используют для вывода результата библиотечные функции записи в стандартный вывод(print для языков С/C++, write для языка Pascal и т.п.). Код представления данных разбросан среди кода программы в аргументах вызовов этих функций.
- Модель динамических страниц (dynamic page model). Не зависящая от аргументов часть страницы пишется в HTML-коде, а функциональная часть встраивается в код страницы с помощью специальных тегов — скриптлетов.
- Модель MVC. Реализация шаблона проектирования модель-представление-контроллер (Model-View-Controller), для разделения зависимости кода представления и кода программного обеспечения, работающего с ресурсами сервера.
Последний подход все больше входит в моду и становится популярным среди web-девелоперов. Впрочем, в PHP так же есть средства (фрэймворки) позволяющие использовать эту модель по полной программе, в частности Zend Framwork.
Питон в свою очередь может похвастаться большим количеством грамотно построенных фрэймворков пользоваться которыми одно удовольсвие. Местная звезда – фрэймворк Django, на основе которого собирается сайт практически любой сложности, от форумов до блогов. И все же в чем преимущества MVC? Их несколько, одно из самых существенных – разделение кода/данных/дизайна
Ближе к делу. MVC.
Как это работает? Очень просто как следует из названия у системы 3и компонента Model, View и Controller. Каждый компонент отвечает за свою область, поэтому достаточно легко разделить усилия программистов и дизейнеров между этими частями, пусть каждый занимается своим делом.
MVC определяет способ разработки программного обеспечения при котором код для определения и доступа к данным (модель – model) отделён от логики приложения (управление – controller), которая в свою очередь отделена от интерфейса пользователя (представление – view).
Model – отвечает за представление и обработку данных. Часто используется ORM что значительно упрощает разработку.
View – отвечает за отображение информации, за представление её пользователю в удобном виде.
Controller – связывает модель и представление. Передает данные, введённые пользователем в модель другими словами является средством, при помощи которого пользователи взаимодействуют с системой.

Рассмотрим View подробнее, ведь это именно то, что визуализирует сухие данные. Для представления используют так называемые Template Engines. Выглядит это примерно так :
<title>{% block title %}{% endblock %}</title>
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
Их достаточно много, отдельно можно выделить Jinja2 и Mako. В чистом виде движки шаблонов позволяют вам генерировать статические страницы (html код). Т.е. используя движек шаблонов можно располагая какими-то данными написать код который будет собирать готовый сайт. Нужно было сгенерировать несколько сайтов используя каталог товаров, получилось примерно так :
env = Environment(loader=FileSystemLoader(TEMPLATE_FOLDER))
sitemap_list = []
# render index pages
for page, items in zip(index_pages, grouper(shop_items, ITEMS_PER_PAGE)):
page_data = form_nav_panel(page, index_pages)
template = env.get_template('index_pages.html')
random_5 = random.sample(shop_items, 5)
html = template.render(
index_page=True,
page_data=page_data,
index_pages=index_pages,
items_in_store=len(shop_items),
current_page = page,
items=items,
random_5=random_5,
current_date=datetime.now().strftime("%d. %B %Y")
)
with open("./sites/mystaticsite/%s" % str(page['fname']), "w") as f:
f.write(html.encode("utf-8"))
sm = {
'url' : page["fname"],
'title' : "Item list : " + str(page['id'])
}
sitemap_list.append(sm)
Т.е. берется шаблон (html + тэги движка шаблонов) загружается с помощью Jinja2, далее в функцию рендера передаются нужные данные, на выходе имеем готовый html код. Получать уникальные шаблоны несложно, используя плагины вроде ScrapBook. Грабим понравившуюся страницу, меняем дизайн по вкусу, расставляем тэги. Зачастую типовые страницы отличаются друг от друга в строении, но не на много (header + content + sidebar + footer). Чтобы не копировать полностью html код, переписывая тэги, Jinja2 предоставляет такую мощную фичу как наследование.
{% extends "index.html" %}
{% block title %}Fuck you spomoni{% endblock %}
{% block page_title %}(^_^){% endblock %}
{% block navigation_bar_top %}
<div id="navigation_bar">
<h1>Items in store : {{ items_in_store }}</h1>
<span>{% if page_data['prev_page_id'] is defined %}<a href="{{ page_data['prev_page_fname'] }}" rel="prev">« Previous </a>{% else %}« Previous {% endif %}</span>
{% for item in index_pages %}
{% if item['id'] == current_page['id'] %}
<span>{{ item['id'] + 1 }}</span>
{% else %}
<span><a href="{{ item['fname'] }}">{{ item['id'] + 1 }}</a></span>
{% endif %}
{% endfor %}
<span>{% if page_data['next_page_id'] is defined %}<a href="{{ page_data['next_page_fname'] }}" rel="next"> Next »</a>{% else %}Next »{% endif %}</span>
</div>
{% endblock %}
К предыдущему примеру. Это файл представляет собой шаблон “как он есть”, невооруженным глазом можно заметить что он наследуется от index.html переопределяя некоторые блоки, об этом явно говорит строчка : {% extends “index.html” %}
Вот таким образом и происходит построение сайта используя Template Engine. Если к этому добавить еще работу с БД и контроллер получится как раз таки этот самый MVC. Однако если нет необходимости часто менять контент на сайте, лучше генерировать его на стороне сервера за раз вытягивая данные из текстовых файлов или базы данных. Генерация статических сайтов, которые порадуют гугл и юзера своей скоростью загрузки, помимо этого существенно снижая скриптовую нагрузку на сервер.
Posted in Code, Python | 1 Comment »