Краткое руководство с примерами по Python 2

Данное руководство ни в коем случае не предентует на полноту изложения :). Официальная документация Python 2: http://docs.python.org/2/ . Официальное руководство с примерами: http://docs.python.org/2/tutorial/index.html

Простейшие типы данных и арифметичекие операции

Помимо обычного присваивания значения переменной, есть еще т.н. множественное присваивание, когда переменные записываются через запятую. Однострочные комментарии выделяются знаком #. Вывод на экран нескольких аргументов выводит их через запятую. Подряд идущие выводы на экран разделяются переводом строки.

In [14]:
a = 10
print a
b, c = 3.1, 4
print b, c
b, c = c, b
print b, c
print type(a), type(b), type(c)
10
3.1 4
4 3.1
<type 'int'> <type 'int'> <type 'float'>

В Python есть как и обычные для других языков арифметические операции, так и довольно редкие. Например, возведение в степень. К тому же в язык встроена длинная арифметика неограниченной точности.

In [15]:
print 2 ** 300
print type(2 ** 100)
2037035976334486086268445688409378161051468393665936250636140449354381299763336706183397376
<type 'long'>

Как и, например, в C, существует различие между целочисленным типом и вещественным.

In [12]:
a = 2
print a ** 3 / 4
print a ** 3.0 / 4
print a ** 3 / 4.0
2
2.0
2.0

Аналогично языку C++, написав название типа с круглыми скобками после него, мы вызовем конструктор "простейшего" объекта указанного типа. Так же можно преобразовывать один тип к другому.

In [18]:
print int()
print float()
print float(3)
print int(12.7)
0
0.0
3.0
12

Также в Python есть логический тип, строки и особый тип с всего одним значением None.

In [19]:
print 'Hello world!'
print 'Hello world!' == "Hello world!"
a = None
print a
Hello world!
True
None

Списки

В Python есть аналог массивов в других языках программирования - список. Этот список не стоит путать со списком, как структурой данных (где обращение по индексу происходит за O(N)). Список в Python может включать в себя объекты разных типов.

In [17]:
print [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print range(10)
a = [123, 12.0, None, [1, [], []], 'qwerty']
print a[0], a[2]
print [[0, 1, 0], [1, 2, 1], [0, 1, 0]][1][1]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
123 None
2

Мощные инструменты Python - срезы и отрицательные индексы.

In [20]:
a = range(10)
print a
print a[0:5] # elements from 0 to 4
print a[:5] # elements from begin to 4
print a[:] # elements from begin to end
print a[2:8:3] # every third element from 2 to 7 
print a[-1] # last element
print a[::-1] # reverse list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 5]
9
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

А еще можно, например, отсортировать список.

In [23]:
a = range(10, 0, -1)
print a
b = sorted(a)
print a, b
b.sort(reverse=True)
print a, b
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Управляющие конструкции

Условный оператор if-elif-else. Все логические блоки выделяются отступами (общепринято ставить 4 пробела).

In [24]:
name = 'Kolya'
if name == 'Petya':
    print 'Romov', name
elif name == 'Sasha':
    print 'Fonarev', name
elif name == 'Vasya':
    print 'Pupkin', name
else:
    print 'Unknown man'
Unknown man

А вот цикл while с удобным постусловием для проверки наличия элемента в списке чисел.

In [25]:
data = [19, 2, 4, 6, 7, 3]
element_to_find = 10
i = 0
while i < len(data):
    if data[i] == element_to_find:
        print "Found!"
        break
    i += 1
else:
    print "Not found!"
Not found!

Вот способ реализовать такую же проверку с помощью цикла for.

In [26]:
data = [19, 2, 4, 6, 7, 3]
element_to_find = 10
for i in range(len(data)):
    if data[i] == element_to_find:
        print "Found!"
        break
else:
    print "Not found!"
Not found!

Таким образом i здесь пробегает по всем элементам списка из индексов. А почему бы тогда не пробегать сразу по элементам списка data?

In [27]:
data = [19, 2, 4, 6, 7, 3]
element_to_find = 10
for element in data:
    if element == element_to_find:
        print "Found!"
        break
else:
    print "Not found!"
Not found!

Хотя, конечно, вот самый простой способ проверки, встроенный прямо в Python.

In [28]:
data = [19, 2, 4, 6, 7, 3]
element_to_find = 10
if element_to_find in data:
    print "Found!"
else:
    print "Not found!"
Not found!

Строки

Строчки в Python неизменяемы.

In [32]:
s = 'Machine leerning is cool'
s[10] = 'a'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-32-8a215097b04c> in <module>()
      1 s = 'Machine leerning is cool'
----> 2 s[10] = 'a'

TypeError: 'str' object does not support item assignment

Так что, символ в строчке можно изменить, например, так.

In [33]:
s = 'Machine leerning is cool'
s = s[:10] + 'a' + s[11:]
print s
Machine learning is cool

Также у строк есть удобный метод для их разделения и склейки.

In [35]:
s = 'Machine learning is cool'
splitted = s.split(' ') 
print splitted
print '_'.join(splitted)
['Machine', 'learning', 'is', 'cool']
Machine_learning_is_cool

Кортежи

В Python есть неизменяемый аналог списков - кортежи.

In [37]:
first = ('Masha', 24)
first[0] = 'Nastya'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-18567edae165> in <module>()
      1 first = ('Masha', 24)
----> 2 first[0] = 'Nastya'

TypeError: 'tuple' object does not support item assignment

Кроме того, часто можно встретить подобное извлечение элементов из кортежей (на самом деле, то же самое работает и на списках).

In [39]:
first = ('Masha', 24)
second = ('Vasya', 30)
third = ('Kolya', 20)
data = [first, second, third]
print data

for name, age in data:
    print name + ' is ' + str(age) + ' years old'
[('Masha', 24), ('Vasya', 30), ('Kolya', 20)]
Masha is 24 years old
Vasya is 30 years old
Kolya is 20 years old

Хэширование

От каждого неизменяемого объекта в Python можно взять встроенную хэш-функцию. На них основываются многие сложные встроенные в Python структуры данных.

In [41]:
print hash(1543)
print hash(-15.43)
print hash('Kolya')
print hash(('Masha', 24))
1543
-2156747735
1363750548686578661
3035629031057941006

Список является изменяемым, так что посчитать для него хэш не получится.

In [42]:
hash(['Masha', 24])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-42-2496e8430051> in <module>()
----> 1 hash(['Masha', 24])

TypeError: unhashable type: 'list'

Множества и словари

В Python можно создавать множества.

In [43]:
print {1, 2, 2, 1, 3}
set([1, 2, 3])

Множества могут содержать в себе только неизменяемые объекты.

In [44]:
print {1, 2, 3, [5, 6]} 
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-44-2db7d440495c> in <module>()
----> 1 print  {1, 2, 3, [5, 6]}

TypeError: unhashable type: 'list'

С помощью множеств можно, например, удалять дубликаты из списков. Так же над ними можно выполнять логические операции.

In [45]:
print sorted(list(set([1, 2, 2, 2, 1, 4, 6, 4])))
print sorted(list(set(range(10)) & set(range(7, 20, 2))))
[1, 2, 4, 6]
[7, 9]

Можно использовать словари (ассоциативные массивы, аналог map в C++). Ключи тоже должны быть неизменяемыми (хотя значения могут быть и изменяемыми).

In [50]:
a = {None: 10, 'Masha': [1, 2, 3], (-1, 1): 0}
a['Masha'][1] = 10
print a
{(-1, 1): 0, None: 10, 'Masha': [1, 10, 3]}

Обратите внимание, что пустые фигурные скобки - пустой словарь.

In [46]:
print {} == set()
print {} == dict()
False
True

Вот небольшой пример генерации списка чисел и посчета их количеств с помощью словаря.

In [55]:
import math
data = [round(math.sin(i) * 2) for i in range(100)]

counter = dict()
for element in data:
    if not element in counter:
        counter[element] = 1
    else:
        counter[element] += 1
        
print counter
print counter.keys()
print counter.values()
print counter.items()
{0.0: 15, 1.0: 20, 2.0: 23, -1.0: 18, -2.0: 24}
[0.0, 1.0, 2.0, -1.0, -2.0]
[15, 20, 23, 18, 24]
[(0.0, 15), (1.0, 20), (2.0, 23), (-1.0, 18), (-2.0, 24)]

Выше был использован так называемый генератор для создания списка одной строкой кода. Подобные конструкции оказываются очень удобны на практике. Ниже приведено еще несколько примеров их использования.

In [58]:
print [i ** 2 for i in range(20)]
print [[] for i in range(3)]
print [s + ' is cool' for s in ['Yandex', 'Google', 'Yahoo'] if s[0] == 'Y']
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361]
[[], [], []]
['Yandex is cool', 'Yahoo is cool']

Ввод и вывод

Считывание из стандартного потока ввода всех строк, отрезание крайних пробельных символов и вывод с стандартный поток вывода (по умолчанию print тоже выводит в стандартный поток вывода sys.stdout).

In [59]:
from sys import stdin
from sys import stdout
for line in stdin:
    line = line.strip()
    print >> stdout, line + '!'

Считывание данных из файла с данными, разделенными запятой, и вывод в другой файл только 2го и 4го столбца через табуляцию.

In [ ]:
in_file = open('in_file.txt')
out_file = open('out_file.txt', 'w')

title = in_file.readline()
for line in in_file:
    cells = line.split(',')
    print >> out_file, '\t'.join([cells[1], cells[3]])

Функции и менеджер памяти

В Python имя каждого объекта - ссылка на соответствующую область памяти. При присваивании сложных объектов (например, списков) происходит копирование ссылки, а не содержимого объекта.

In [61]:
a = range(5)
b = a
b[3] = 100
print a, b
b = range(10)
print a, b
[0, 1, 2, 100, 4] [0, 1, 2, 100, 4]
[0, 1, 2, 100, 4] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

В Python можно заводить обычные функции и лямбда-функции.

In [63]:
def get_degrees(n):
    return n ** 2, n ** 3
print get_degrees(12)
print (lambda n: (n ** 2, n ** 3))(12)
(144, 1728)
(144, 1728)

А вот как может неочевидно, но объяснимо может вести себя менеджер памяти.

In [64]:
def change_list(a, flag=True):
    if flag:
        a[0] = 'qwerty'
        return
    a = [15, 43]
    
x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
change_list(x)
change_list(y, False)
print x, y
['qwerty', 2, 3, 4] [1, 2, 3, 4]

Также можно, не помня порядок параметров у функции, использовать при вызове их названия.

In [65]:
def my_func(param1, param2='ML', param3=10):
    print param1, param2, param3
my_func(param2='Data Mining', param1=[0, 0])
[0, 0] Data Mining 10

Классы

Синтаксис для создания классов прост. Служебные методы принято называть с двумя подчеркиваниями в начале и конце. Так, например, init - конструктор. Первый параметр каждого метода - сам объект, для которого вызывает метод. Принято называть этот параметр self.

In [68]:
class MyClass:
    def __init__(self, param):
        self.field = param

    def get_squared_param(self):
        return self.field ** 2

a = MyClass(10)
print a
print a.field
print a.get_squared_param()
<__main__.MyClass instance at 0x1046ba098>
10
100