Python

"о Python" или "о-о-о, Python!"

Python - это интерпретируемый язык. Очень простой и очень глубокий. В стандраных средствах языка есть очень-очень много возможностей. На Python быстро и приятно писать, а скрипты легко отлаживать. На Python труднее написать плохой код, чем хороший. Python используется в качестве скриптового языка в различных графичесских программах (GIMP, Blender). Python - это очень динамичнеский язык. В процессе выполнения программы можно менять вообще всё: созданные классы, модифицировать функции, генерировать код и на лету компилировать в исполняемые выражения.

Из-за огромных возможностей, удобства и логичности языка, после Python трудно писать на других языках, т.к. они будут казаться примитивными. Предупреждение тут .

Что можно написать на Python?

На Python можно написать GUI; управляющую логику сервера, написанного на C++; можно сделать самостоятельный сервер. Можно использовать Python для разработки сайтов. Благодаря  множеству фреймвёрков и скорости выполнения скриптов, Python набирает популярность среди web-разработчкиков. Есть wsgi - стандарт взаимодействия Python с web-серверами, поэтому неважно работает ли ваш скрипт под apache или другим сервером.

Часто я использую Python для своих практических целей. Например, получить код html-страницы, распарсить содержимое, вытащить ссылки. Или для обработки пачки фотографий перед выкладыванием в каталог.

На мой взгляд, Python просто идеальный язык для разработки корпоративных баз данных. Можно написать сервер, работающий с базой данных, графические клиенты пользователей, обращающиеся к серверу по сети, распечатка документов. В программу можно быстро вносить доработки (создавать новые отчёты), в случае проблем очень быстро устранять ошибки.

Фичи языка Python

Официальный coding style

Когда только открываешь для себя Python, то немного удивляет синтаксис. Нет привычных фигурных скобок для определения границ блоков. Чтобы отделить блоки друг от друга - используются отступы от начала строки. Отсупы могут задаваться пробелами или табуляциями. Если отсуп стал больше, то значит начался блок. Если отсуп уменьшился, то блок закончился. Так очень круто был разрешён вечный спор о том, где надо размещать фигурную скобку, открывающую блок, - на той же строке или на следующей.

Кроме того, в Python есть официальные рекомендации по coding style и специальная тулзина для проверки синтаксиса - pylint. Эта тулзина может быть прикручена к разным Python IDE, например, к PyScripter.

Генератор

Генератор - это функция, которая запоминает своё состояние

def a():
    i = 1
    while i:
        yield i
        i += 1
b = a()
for i in xrange(10):
    print b.next(),

>>> 1 2 3 4 5 6 7 8 9 10

Построение регулярных выражений

выбрать все div, внутри которых не содержится span

<div([^s]|s[^p]|sp[^a]|spa[^n])*/div>

Экранирование спецсимоволов

>>> print re.escape( "\(\*%%_dd|\.|\\)$" )
\\\(\\\*\%\%\_dd\|\\\.\|\\\)\$

выражение в квадратных скобках [] - символьный класс.
спецсимволы ".", "?" и т.д.  внутри символьного класса не надо экранировать:

import re
cre = re.compile( "^d[.?$\s]+dd$", re.DOTALL )
print cre.search("d. ? .dd").group()

 

Built-in functions

super

super - это функция для обращения к родительскому классу. Вроде понятно. А что будет если родительских классов несколько?

class my1(object):
    a = 1
    b = 1
    def __init__(self):
        print 1,
class my2(object):
    a = 2
    def __init__(self):
        print 2,
class my3(object):
    def __init__(self):
        print 3,
class my(my3, my2, my1):
    def __init__(self):
        super(my, self).__init__()
        # вроде бы то же самое:
        # super(self.__class__, self).__init__()
        print super(my, self).a,
        print super(my, self).b,
my()
>>> 3 2 1

К родительскому классу обратиться по имени, т.к. родительский класс всё равно должен быть доступен из того же модуля, где мы пишем класс. Но говорят, что положительно использовать функцию super; я не смог оценить её прелестей, т.к. при двухкратном наследовании возникают баги. По-моему, проще вызывать ClassName.__init__(self)

property

С помощью этой функции реализуются getter-ы и setter-ы

class GetterSetterTest(object):
    def __init__(self, value):
        self._value = value
    def get_value(self):
        return self._value
    def set_value(self, value):
        self._value = value
    value = property(get_value, set_value)

v = GetterSetterTest(2)
print v.value
v.value = 3
print v.value

 

Оптимизация кода

Для проверки скорости выполнения каких-либо кусков кода есть специальный модуль, который называется timeit. Я его не использую, и мои результаты могут оказаться не совсем верными с точки зрения этого модуля. А проверяю я скорость так:
a= detetime.now()
{тут кусок кода, загнанный в цикл, например, 1000 раз}
b = datetime.now()
print b-a
Всё просто, и Вы можете экспериментировать также или через timeit.

dict-ы

if "key" in MyDict:
    value = MyDict["key"]
else:
    value = None
эквивалентно и лучше:
value = MyDict.get("key")

list

Иногда при обходе списка нужно ещё знать текущий номер, для этих целей предназначен итератор enumerate:

for num, value in enumerate([3,4,6]):
    print num

Для прохода по списку я часто использую списковые выражения:
a = [x.param for x in myList if x.test is not None]
и так я к ним привык, что сильно удивился, когда оказалось, что:
a = map(str, myList)
работает гораздо быстрее, чем то же самое, реализованное через списковое выражение. Очевидно, что map не просто так оказался в языке.

Другие эквиваленты

До После
a = vasia if vasia else petia a = vasia or petia