Kolcov - Python Na Primerah.793883
Kolcov - Python Na Primerah.793883
на примерах
ПРАКТИКА, ПРАКТИКА
И ТОЛЬКО ПРАКТИКА
Объектно-ориентированное
программирование ------ >
в Python
Кольцов Д. М.
PYTHON
НА ПРИМЕРАХ
Санкт-Петербург
УДК 004.42
ББК 32.973
Кольцов Д. М.
ISBN 978-5-907592-16-2
Все права защищены. Никакая часть данной книга не может быть воспроизведена в какой бы то ни было форме без письменного разрешения
владельцев авторских прав.
Издательство не несет ответственности за возможный ущерб, причиненный в ходе использования материалов данной книги, а также за
доступность материалов, ссылки на которые вы можете найти в этой книге. На момент подготовки книга к изданию все ссылки на интернет-
ресурсы были действующими.
© Кольцов Д. М.
© Издательство Наука и Техника (оригинал-макет)
Содержание
1.5. КОММЕНТАРИИ.......................................................................................................................... 27
4.2. ЦИКЛЫ............................................................................................................................................... 78
11.6. ДЕКОРАТОРЫ.............................................................................................................................236
ПЕРВЫЕ ПРИМЕРЫ И
ПРОГРАММЫ
1.1. Первая программа на Python
# Comment
print("Hello, world!")
Как только результат вам понравится, нажмите кнопку Save as New Custom
Theme. Затем включите в группе Highlighting Theme переключатель а
Custom Theme и выберите свою тему оформления.
На вкладке Fonts/Tab можно установить другие параметры шрифта —
выбрать другую гарнитуру, установить другой размер. По умолчанию ис
пользуется шрифт Courier New размером 10 пунктов.
Ctrl + F Поиск
F6 Просмотреть перезапуск
print ("Hello")
python E:\Python\samples\l.py
# - *- coding: ср1251
#!/usr/bin/python
$ which python
/usr/bin/python
$ chmod +х first.ру
$ ./first.ру
Строка с указанием пути к интерпретатору — это не инструкция Python, а
инструкция командного интерпретатора bash, который, благодаря ей, будет
знать, какая программа будет обрабатывать сценарий. Если вы не укажете
эту первую строку, bash посчитает сценарий first.py собственным сценари
ем, а поскольку синтаксис bash ни разу не похож на синтаксис Python, воз
никнет ошибка.
Если вы не хотите превращать свои программы в отдельные сценарии, вы
можете запускать их, как в Windows:
$ python <имя_программы.ру>
Ln: 8 Col: 4
print ( "Hi!")
print("Hi!");
»> а = 2; Ь 3; с = 4; х - а + Ь * с;
>>> print(х)
14
$х = 0;
while ($х < 5) {
echo "$х \п";
$х+ +;
}
echo "Все";
X = О
while х < 5:
print(х)
х += 1
print("Все")
х = а + b \
* с
х = (а + b # Comment
* с)
1.5. Комментарии
# Это комментарий
print("Привет") # Это тоже комментарий
# print("Привет")
# Многострочный
# комментарий
»> а = 1; b = 2;
>>> print(а, Ь)
1 2
print ()
sys.stdout.write("Hello\n")
Небольшой пример:
Если пользователь нажмет Ctrl + Z или будет достигнут конец файла (в дан
ном случае речь идет о файле стандартного ввода — stdin), будет сгенериро
вано исключение EOFError и программа завершит свою работу. Чтобы этого
не произошло, нужно произвести обработку этого исключения:
try:
name = input("Как тебя зовут? ")
print(name)
except EOFError:
print("EOFError raised")
import sys
args = sys.argv[:]
for n in args:
print(n)
РАБОТА С ПЕРЕМЕННЫМИ
И ТИПАМИ ДАННЫХ
Теперь, когда вы знаете, как создать и запустить программу, можно присту
пить к изучению синтаксиса языка. Прежде чем мы перейдем к рассмотре
нию переменных, вы должны знать, что типизация в Python динамическая,
то есть тип переменной определяется только во время выполнения. Данное
отличие может поначалу сбивать с толку, особенно если вы программи
ровали на языках, где требуется сначала указать тип переменной, а потом
уже присваивать ей значение (С, Pascal и др.). В то же время языки с ди
намической типизацией тоже не редкость — типичный пример РНР, где не
нужно объявлять тип переменной перед присвоением значения. Тип будет
определен автоматически — по присвоенному значению. С одной стороны,
так проще. С другой — это требует от программиста постоянно следить за
данными, которые он присваивает переменной, поскольку одна и та же пере
менная в разные моменты времени может содержать данные разных типов.
В Python имеются встроенные типы:
• Булевый;
• Строка;
• Unicode-строка;
• Целое число произвольной точности;
• Число с плавающей запятой;
• Комплексное число и некоторые другие.
program VarTest;
var
a, b : real;
begin
a : = 2; b : = 2 ;
writein(sum(a, b);
end.
Четко видно, что переменные а и b являются глобальными, поскольку
определены за пределами какой-либо функции, а переменная res является
локальной, поскольку она объявлена в функции sum. В принципе, без нее
можно было бы обойтись, но нужен был пример локальной переменной, а
усложнять код не хотелось.
В Python также есть понятие глобальной и локальной переменной.
Локальными считаются переменные, объявленные внутри функции (о функ
циях мы поговорим позднее). Простота Pascal (и многих других перемен
ных) в том, что переменные объявляются в одном блоке (var), при этом жест
ко определен тип переменной.
В Python (как и в РНР) все иначе. Какого-либо оператора или блока объявле
ния переменной просто не существует. Объявлением переменной считается
присваивание ей значения. Вот у вас может быть программа на 2000 строк, и
переменная res, хранящая результат, может встречаться лишь в предпослед
ней строке. И это будет правильно с точки зрения Python.
С типом переменной тоже не все так просто. Если в С типы определяются
жестко — при объявлении переменной, то в Python типы плавающие:
»> х = 1
>» х = "test"
>» print (х)
test
В Python есть типы данных. При присвоении переменной значения тип дан
ных выбирается автоматически, согласно присваиваемому значению. Тип
данных может меняться на протяжении программы несколько раз — столько
раз, сколько ей присваивают значения разных типов. Поддерживаемые типы
данных приведены в таблице 2.1.
function Функция
module Модуль
♦
set Множество (набор уникальных объектов)
str Unicode-строка
tuple Кортеж
>» type(x)
<class ' int'>
>>> x = "abc"
>» type(x)
<class 'str’>
»> m = [1, 2, 3]
>>> i = iter(m)
»> i.__ next__ ()
1
>>> next (i)
2
>>> next (i)
3
Использование метода__ next__ () и функции next() на практике наблюдается
редко. Чаще всего используется цикл for in:
»> for i in m:
print(i)
1
2
3
а = х
У х * а + х
• Результат вычисления функции
res = func(у)
»> а = Ь = [5, 4, 3]
»> а, b
([5, 4, 3], [5, 4, 3])
»> а[1] = 6
»> а, Ь
([5, б, 3], [5, б, 3])
»> а = b = 1
»> а = 2
>>> а, b
(2, 1)
Проверить, ссылаются ли переменные на один и тот же объект, можно с по
мощью оператора is. Например:
»> а = b = [5, 4, 3]
>>> a is Ь
True
>>> b is а
True
Как видите, оператор is вернул значение True, что означает, что переменные
а и b ссылаются на один и тот же объект в памяти. А теперь не будем ис
пользовать групповое присваивание, но присвоим переменным а и b одно и
то же значение:
»> а = [5, 4, 3]
»> Ь = [5, 4, 3]
>>> a is b
False
>>> b is а
False
>>> а = 5; b = 5; с = 5;
>>> sys.getrefcount (5)
105
Когда число ссылок на объект станет равно 0, объект будет удален из памяти.
Кроме группового присваивания в Python поддерживается позиционное
присваивание, когда нужно присвоить разные значения сразу нескольким
переменным, например:
»> а, Ь, с = 5, 4, 3
>>> а, Ь, с
(5, 4, 3)
По обе стороны оператора = можно указать последовательности (строки,
списки, кортежи, bytes и bytearray), но такие сложные операторы присваи
вания встречаются в природе довольно редко и я бы рекомендовал избегать
их использования, если вы хотите сделать программу понятной и читаемой:
»> а, ь, с = "abc"
»> х, У г Z
а, ь, с
>>> а, ь, с = [1, 2, 3]
>>> а, ь, с
(1, 2, 3)
»> [а, ь, с] = (1, 2, 3
>>> а, ь, с
(1, 2, 3)
»> a, b, с = 1, 2
Traceback (most recent call last):
File "<pyshell#49>", line 1, in <module>
a, b, c = 1, 2
ValueError: need more than 2 values to unpack
>» a, b, *с = 1, 2, 3, 4
»> а, Ь, с
(1/ 2, [3, 4])
Как уже отмечалось ранее, функция type() позволяет определить тип пере
менной. Например:
»> а = "1"
>» type (а)
Cclass 'str’>
String
Иногда нужно преобразовать один тип данных в другой. Эта операция на
зывается приведением типа. Стоит отметить, что далеко не всегда можно
преобразовать один тип данных в другой без потери самих данных. Некото
рые типы данных вообще несовместимы. Например, никак нельзя преобра
зовать вещественное число в целое без потери данных. А при преобразова
нии строки в число вы вообще увидите сообщение об ошибке:
х = input("Введите х = \п")
у = input("Введите у = \п")
print(х + у)
input()
Ln: 11 Col: 4
Пример:
»> z = 1
»> print (z)
1
»> del z
»> print (z)
Traceback (most recent call last):
File "<pyshell#72>", line 1, in <module>
print(z)
NameError: name 'z' is not defined
Чтобы удалить несколько переменных, просто перечислите их в инструкции
del через запятую:
del а, Ь, с
Глава 3.
ПРИМЕРЫ ОПЕРАТОРОВ
PYTHON
Операторы производят определенные действия с данными. Например, мате
матические операторы выполняют арифметические вычисления, двоичные
операторы — производят манипуляции с отдельными битами данных и т.д.
Оператор Действие
+ Сложение
- Вычитание
* Умножение
/ Обычное деление
и Деление с остатком
% Остаток от деления
** Возведение в степень
»> 100 / 20
5.0
> » 100 / 33
3.0303030303030303
»> 100 // 5
20
»> 100 // 33
3
»> 100 % 33
1
»> 2*2
4
»> +100, -20, -5.0
(100, -20, -5.0)
»>
60 здесь — количество минут в одном часе. После того как время вычисле
но, мы его выводим.
LA IDLE Shell 3.9.2 - □ X
1л8 Col: 4
Ln: 23 Col: 4
Вывод изображен на рис. 3.3. Явно не то, что мы хотели. По умолчанию все
введенные значения считаются строковыми, и интерпретатор просто склеил
строки в одну большую строку.
• + — конкатенация,
• * — повторение,
• in — проверка на вхождение.
»> "а" * 5
'ааааа'
»> [1] * 5
[1, lz lz 1, 1]
»> (1, 2) * 3
(1, 2, 1, 2, lz 2)
Как видите, оператор вхождения (in) возвращает True, если операнд слева
входит в состав последовательности, указанной операндом справа. В про
тивном случае оператор возвращает False.
»> а = 10; а
10
»> а += 5; а
15
>» s = "Hel"; s += "lo"; s # Для строк — конкатенация
'Hello'
»> а -= 5; а
10
»> а *= 2; а
20
»> s *= 2; s # Для строк - повтор
’HelloHello'
»> а /= 2; а
10.0
»> а //= 3; а
3.0
»> а %= 2; а
1.0
»> а **= 5; а # Возведение в степень 1 Л 5 = 1
1.0
а = 2 + 2 * 2
5. &
6. л
7. I
8. =,+=-=, *=,/=,//=, %=,**=
а = (2 + 2) * 2
Сначала будет вычислено значение в скобках (4), а потом уже будет произ
ведено умножение на 2.
3. 6. Простейший калькулятор
ЗНАКОМСТВО С ЦИКЛАМИ И
УСЛОВНЫМИ ОПЕРАТОРАМИ
4.1. Условные операторы
»> 5 == 5
True
»> 5 != 6
True
»> 5 == 6
False
»> 100 > 99
True
»> 100 < 99
False
»> 100 <= 100
True
»> 100 >= 101
False
»> 2 in [1, 2, 3]
True
»> a = b = 100
»> a is b
True
»> а = b = 100
»> not (а == 100)
False
Если нужно инвертировать значение оператора in, оператор not нужно ука
зывать непосредственно перед in — без скобок:
»> a is not b
False
х and у ,
х or у
• <, >, <=, >=, ==,! =, о, is, is not, in, not in.
• not — логическое отрицание.
• and — логическое И.
• or — логическое ИЛИ.
n = int(input("Введите N: "));
if n < 100:
print("n < 100")
else:
print("n > 100")
~ = int(input("Введите N: "));
if п < 100: print("n < 100")
else: print("n > 100")
Недостаток нашей программы — то, что она никак не реагирует, если поль
зователь введет число, отличное от чисел от 1 до 6. Исправить это можно с
помощью еще одного блока else:
if browser == 1:
print("Chrome") ;
elif browser == 2:
print("Firefox");
elif browser == 3:
print("MS IE");
elif browser == 4:
print("Opera");
elif browser == 5:
print("Safari") ;
elif browser == 6:
print("Другой");
else:
print("Неправильное значение")
Результат выполнения этого кода приведен на рис. 4.3. Как видите, сцена
рий вывел числа от 1 до 9 и в конце работы цикла вывел сообщение "Все.".
Теперь переделаем цикл так, чтобы внутри был оператор break, который
прерывает работу цикла (лист. 4.5). Результат изображен на рис. 4.4. Как ви
дите, если выполнение цикла прерывается оператором break, то операторы
из блока else не выполняются.
с:\Python39>python dict.py
а => 1
b => 2
* •
В языке Python кроме цикла for есть также и цикл while. На этот раз данный
цикл — без сюрпризов, и он работает так, как в других языках программи
рования, а именно выполняется до тех пор, пока логическое выражение ис
тинно:
Как и у цикла for, у цикла while есть блок else. Оператор while нужно ис
пользовать очень осторожно. Если в теле цикла не предусмотреть измене
ние логического выражения, то можно получить бесконечный цикл, который
приведет к так называемому "зацикливанию" программы. Ниже приведено
несколько примеров "вечных" циклов:
Цикл for более безопасен — он будет закончен тогда, когда будут перебра
ны все элементы последовательности. Бесконечных последовательностей
не бывает, поэтому рано или поздно цикл будет закончен (если, конечно, в
цикле не происходит изменения последовательности). А вот за телом цикла
while нужно следить. Чтобы не допустить бесконечного цикла, нужно или
предусмотреть условие выхода из цикла, или предусмотреть изменение ус
ловия. Перепишем два наших проблемных цикла так, чтобы они стали "ко
нечными":
Как уже было показано ранее, оператор break досрочно прерывает цикл.
Оператор continue прерывает текущую итерацию и осуществляет переход на
следующую. Пример использования этих операторов приведен в листинге
4.7.
Если у функции один параметр, то это — конец. При этом в качестве пара
метра начало используется 0. То есть range(lOO) равносильно range(0, 100).
Значение параметра конец не включается в создаваемую последователь
ность, то есть при вызове range(0, 100) в последовательности будут числа
от 0 до 99.
Параметр шаг задает инкремент. По умолчанию используется значение 1.
Шаг может быть и отрицательным, поэтому вы можете не только увеличи
вать значение, но и уменьшать его:
print ()
print ()
0123456789
0 5 10 15 20 25 30 35 40 45
10 987654321
к = 10
while к > 5:
print(к)
к = к + 1
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
Прервать выполнение зацикленной программы можно с помощью комбина
ции клавиш Ctrl + С:
k = к - 1
10
9
8
7
6
Номер Значение
Проверка условия Действия
итерации к
print(к) # 10 .
1 10 true
к = к - 1 # 9
print (к) #9
2 9 true
к = к - 1 # 8
print(k) #8
. 3 8 true
k = k - 1 # 7
print(k) # 7
4 7 true
k = k - 1 # 6
print(k) # 6
5 6 true
k = k - 1 # 5
6 5 false -
к = 10
while к < 15:
print(к)
к = к + 1
10
11
12
13
14
while True:
блок_кода
while True:
data = read_from_socket ()
if data == "quit":
break
к = О
while к < 17:
к = к + 1
if к %5 == 0:
continue
print(к)
Программа выведет:
1
2
3
4
6
7
8
9
11
12
13
14
16
17
if score:
if score > 0:
if money or score:
password = ""
while not password:
password = input("Пароль: ")
login = ""
while not login:
login = input("Логин: ")
python
password =
while not password:
password = input("Пароль: ")
if level:
print("Привет, ", login)
print("Ваш уровень доступа: ", level)
else:
print ("Доступ запрещен!")
Логин: mark
Пароль: 321
Привет, mark
Ваш уровень доступа: 5
»>
Логин: root
Пароль: 1234
Доступ запрещен!
»>
В первом случае были введены правильные логин и пароль. Программа
сообщила уровень доступа. Во втором случае логин был введен правильно,
а пароль — нет. Программа сообщила, что доступ закрыт.
Глава 5.
ПРИМЕРЫ
МАТЕМАТИЧЕСКИХ
ФУНКЦИЙ PYTHON
5.1. Поддерживаемые типы чисел
Python поддерживает следующие типы чисел: int, float, complex. Как вы уже
знаете из предыдущих глав, это целые, вещественные и комплексные числа
соответственно. При операции с числами нужно помнить, что результатом
операции является число более сложного типа. Например, вы хотите умно
жить целое число на вещественное, тогда результатом будет вещественное
число.
Самым простым числовым типом является целое число. Чуть сложнее —
вещественное, поскольку у него есть дробная часть. Конечно же, самым
сложным типом является комплексное число.
Создать числовой объект можно так же, как и объекты остальных типов:
»> а = 5; Ь = 2
>>> с = а * b
»> а = 5е10
»> Ь = 2.5е-5
Вещественная_часть+мнимая_часть J
Например:
»> а = 3+4J
Функция Описание
Пример:
»> int(5.5), int("50", 10) ,
int("0xfff", 16), int ("0o555", 8)
(5, 50, 4095, 365)
(0, 2, 1)
(6, 7)
»> а = 2625531
»> round (а, -1)
2625530
»> round (а, -2)
2625500
»> round (а, -3)
2626000
»>
»> х = 1.234567
»> format (х, '0.2f')
'1.23'
»> format (х, ' 0.3f')
'1.235'
»> 'number - {: 0.3f}'. format (х)
'number - 1.235'
»> а = 3.1
»> b = 4.2
»> с = а + b
>» с
7.300000000000001
>>> с = round(с, 2)
Для большинства приложений, работающих с плавающей точкой, просто ре
комендуется это сделать. Если для вас важно предотвращение таких ошибок
(например, в финансовых приложениях), рассмотрите использование моду
ля decimal.
»> х = 9876.54321
»> # Два десятичных места точности
»> format (х, *0.2f')
’ 9876.54'
»> # Выравнивание по правому краю, 10 символов, 1 разряд точности
»> format (х, '>10. If)
' 9876.5'
»> # Выравнивание по левому краю, 1 разряд
»> format (х, '<10. If')
'9876.5
>>> # Выравнивание по центру
»> format(х, ,A10.1f')
' 9876.5 '
>>> # Добавление разделителя тысяч
»> format (х, ',')
'9,876.54321'
»> format (х, '0,.If')
' 9, 876.5'
import math
import cmath
Пример:
»> import math
»> math.pi
3.141592653589793
»> math.e
2.718281828459045
Функция Описание
import random
Функция Описание
»> random()
0.9942452546319136
»> random.sample(seq, 3)
[6, 7, 5]
»> random, sample (seq, 3)
[2, 3, 4]
»> random.shuffle(seq)
»> seq
[5, 1, 6, 8, 3, 2, 4, 7]
random.seed()
1. inf — бесконечность;
2. NaN (Not a Nymber) — не число.
import random
random.randint(1, 10)
import random
answer =1;
score = 0;
i = 0
while answer:
i = i + 1
rand = random.randint(1, 10)
answer = int(input("Введите число: "))
if answer == rand:
score = score +1
print("Правильно! Ваш счет: ", score, " из ", i)
else:
print ("Попробуйте еще раз!")
print("До встречи!")
★ ★★★★★★★★★ ЧИСЛО
Компьютер выберет случайным образом число от 1 до 10. Попробуй
угадать это число. Для выхода введите 0
Введите число: 9
Попробуйте еще раз!
Введите число: 8
Правильно! Ваш счет: 1 из 2
Введите число: 5
Правильно! Ваш счет: 2 из 3
Введите число: 2
Попробуйте еще раз!
Введите число: О
Попробуйте еще раз!
До встречи!
if answer == 0:
break
Данную инструкцию нужно добавить в самое начало тела цикла. Если поль
зователь введет 0, выполнение будет прервано. Также было бы неплохо, что
бы программа выводила статистику по окончании игры:
import random
answer = 1;
score = 0;
i = 0
while answer:
if answer == 0:
break
if answer == rand:
score = score +1
print("Правильно!")
else:
print("Попробуйте еще раз!")
i = i + 1
РАБОТАЕМ СО СТРОКАМИ И
СТРОКОВЫМИ ФУНКЦИЯМИ
6.1. Что такое строка? Выбор кавычек
print("Привет")
print('Привет')
print("Привет, 'мир'!")
Здесь внешние кавычки (двойные) используются для ограничения строко
вого значения, а внутренние выводятся как обычные символы. Внутри этой
строки вы можете использовать сколько угодно одинарных кавычек.
Можно поступить и наоборот — для ограничения использовать одинарные
кавычки, тогда внутри можно будет использовать сколько угодно двойных
кавычек:
print(’Привет, "мир"!')
print("Привет",
"мир!")
>» s = "Привет"
>>> s.encode(encoding="utf-8")
b'\xd0\x9f\xdl\x80\xd0\xb8\xd0\xb2\xd0\xb5\xdl\x82'
»> s.encode(encoding="cpl251")
b'\xcf\xf0\xe8\xe2\xe5\xf2'
>» а = "hello"; а
'hello'
»> b = "hi!"; b
'hi! '
»> s = "HelloWnworld"; s
' HelloWnworld'
<?php
function str ($str) {
echo $str;
}
$str = "Hello";
str($str);
?>
»> print(г"с:\test\test.ру")
с:\test\test.ру
print ("""
Использование: program -if <input file> [-of <output file>]
• I II II )
Текст, заключенный между парой тройных кавычек (""" текст """), выводит
ся как есть — сохраняется форматирование, переносы строк и т.д. Тройные
кавычки существенно облегчают вывод многострочного текста.
\г Возврат каретки
\п Перевод строки
\t Табуляция
\v Вертикальная табуляция
\ь Забой
\f Перевод формата
\а Звонок (BELL)
\0 Нулевой символ
V Апостроф
\" Кавычка
\\ Обратный слеш
»> s = "123"
»> s [0] , s [1] , s [2]
*2', '3')
>» s [3]
Traceback (most recent call last):
File "<pyshell#17>" , line 1, in <module>
s[3]
IndexError: string index out of range
[<start>:<end>:<step>]
Интересна она хотя бы тем, что все три параметра являются необязательны
ми. Например, если не указан параметр <start>, то по умолчанию будет ис
пользовано значение 0. Если не указан параметр <end>, то будет возвращен
фрагмент до конца строки. И если не указан <step>, будет использоваться
шаг 1. В качестве всех трех параметров можно указать отрицательные зна
чения.
»> s = "Hello"
»> s[:] # Фрагмент от.позиции 0 до конца строки
'Hello'
»> s [ :-1: ] # Отрезаем последний символ строки
'Hell'
»> s[l: :2] # Начиная с позиции 1 до конца строки, шаг 2
'el'
>» s[l: :] # Отрезаем первый символ
'ello'
Как видите, мы получили тип tuple — кортеж, а не строку. Вот только пом
ните, что вы не можете выполнить неявную конкатенацию строки и пере
менной, например:
»> print ("3" s)
SyntaxError: invalid syntax
6.5.5. Повтор
1 2 3 4 5 6
1. Оператор %
2. Метод formatO
<Формат> % <3начения>
%[(<Ключ>)][<Флаг>][<Ширина>] [.<Точность>]<Преобразование>
Пример использования оператора форматирования:
template = """<html>
<head>
<title>%(title)s</title>
</head>
<body>
%(text)s
</body>
</html>"""
print(template % data)
Ln: 13 Col: 4
Примеры:
»> s = "Hello"
>» s.center (20)
’ Hello
>>> s.center(20, '*’)
• *******Hello* * ****** 1
>» s . 1 just (20)
'Hello
»> s . r just (20)
’ Hello'
{[<Поле>][!<Функция>][:<Формат>] }
[[<3аполнитель>]<Выравнивание>][<3нак>] [#][0][<Ширина>][,]
[.<Точность>][<Преобразование>]
• b — двоичное значение;
• с — преобразует целое число в соответствующий ему символ;
• d — десятичное значение;
• п — выводит десятичное значение с учетом настроек локали;
• о — восьмеричное значение;
• х — шестнадцатеричное значение в нижнем регистре;
• X — шестнадцатеричное значение в верхнем регистре.
Для вещественных чисел можно использовать эти модификаторы:
• f и F — вещественное число;
• е — вещественное число в экспоненциальной форме (буква "е" в нижнем
регистре);
• Е — вещественное число в экспоненциальной форме (буква "е" в верхнем
регистре);
• g — то же самое, что f или Е (используется более короткая запись числа);
• G — то же самое, что F или Е (используется более короткая запись числа);
• п — аналогично g, но с учетом настройки локали;
• % — умножает число на 100 и добавляет символ процента в конце.
Пример:
Синтаксис Описание
Примеры:
Синтаксис Описание
# Метод partition()
>>> s.partition(" ")
('поле1', ' ’, 'поле2 полеЗ')
»> s . rpartition (" ")
('поле1 поле2', ' ', 'полеЗ')
»> chr(55)
'7'
»> ord (' 7 ')
55
»> chr(5055)
'V
setlocale(<категория>, <локаль>)
Пример:
import locale
locale.setlocale(locale.LC_ALL, ('russian'))
6.9. Поиск и замена в строке
<Строка>[<Начало>:<Конец>]
Синтаксис Описание
Ok
s = " Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque
sit amet diam quis risus interdum sollicitudin. In vestibulum, libero
id maximus lacinia, leo massa pharetra mi, vitae posuere libero dui
nec lectus. Ut ac nunc sagittis, consequat eros eget, dignissim
ex. Vivamus ас nisi felis. In accumsan tristique aliquet. Morbi eu
varius urna. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur nec urna sit amet libero temper rhoncus. Nulla fringilla
erat sit amet augue laoreet volutpat. Etiam quis molestie risus.
Morbi sapien nisi, scelerisque sed finibus non, placerat sed elit. Sed
placerat turpis ac varius tincidunt. Morbi turpis metus, molestie eu
erat eu, ultricies sollicitudin lorem."
»> import os
»> os . get_terminal_size () . columns
80
ПРИМЕРЫ РЕГУЛЯРНЫХ
ВЫРАЖЕНИЙ
I
import re
• А или ASCII — классы \w, \W, \b, \В, \d, \D, \s и \S будут соответствовать
обычным символам;
• L или LOCALE — учитывает настройки текущей локали;
• I или IGNORECASE — поиск без учета регистра;
f» python
»> import re
# Игнорируем регистр
> >> р = re.compile(г"Л[a-z]+$", re.I)
»> print("Найдено" if р.search("ABC") else "Not found")
# Найдено, хотя в строке символы в верхнем регистре, а в шаблоне - в нижнем
Найдено
р = re.compile(г"Л\а+$")
нужно будет записать так:
р = re.compile("Л\\а+$")
»> dt = "01.01.2021"
»> р = re.compile(г"Л[0-3] [0-9] . [01] [0-9] . [12] [09] [0-9] [0-9]$")
»> if р. search (dt) : print(" + ")
+
Примеры:
# Точка не соответствует \п
»> р = re . compile (г"Л .+$")
»> р.findall ("sl\ns2\ns3")
[]
f® python
# Точка соответствует \п
>>> р = re.compile(г"л.+$", re.S)
>>> p.findall ("sl\ns2\n\s3" )
[’sl\ns2\n\\s3 ']
Привязка к началу или концу строки используется, только если строка долж
на полностью соответствовать регулярному выражению. Давайте напишем
программу, которая проверяет, является ли строка числом:
import re
р = re.compile(г"Л[0-9]+$", re.S)
num = "123"
snum = "sl23"
if p.search(num):
print("Число")
else:
print("Строка" )
if p. search(snum):
print("Число")
else:
print("Строка")
Число
Строка
»> s = "<i>Ofli4H</i><i>flBa</i><i>Tpn</i>"
Как видите, была найдена вся строка. Это немного не то, что мы хотели.
Чтобы ограничить "жадность" регулярных выражений, нужно использовать
символ ?:
»> р = re.compile('[0-9]+')
> >> print("Найдено" if р.match("sl23") else "He найдено")
He найдено
»> print("Найдено" if p.match("123s") else "He найдено")
Найдено
»>
Пример:
import re
email = "[email protected]"
pattern = r"A([a-z0-9_.-]+)@(([a-zO-9-]+\.)+[a-z]{2,6})$"
p = re.compile(pattern, re.I I re.S)
m = p.search(email)
if not m:
print("He совпадает")
else:
print ("Совпадает")
I» python :
import re
def mult(m):
x = int(m.group(0))
x *= 2
return "{0}".format(x)
p = re.compile(r"[0-9]+")
# умножаем все числа на 2
print(р.sub(mult, "2, 3, 4, 5, б, 7"))
# умножаем первые три числа
print(р.sub(mult, "2, 3, 4, 5, б, 7", 3))
Результат:
4, б, 8, 10, 12, 14
4, б, 8, 5, 6, 7
Представим, что у нас есть строка и нам ее нужно разделить на поля, исполь
зуя разделители, например пробелы. Чтобы задача была менее тривиальной,
о.............................................
будем считать, что разделители и пробелы вокруг них противоречивы по
всей строке.
В самых простых случаях можно использовать метод split() объекта строки.
Но он не позволяет использовать несколько разделителей и учитывать воз
можное пространство вокруг разделителей. В нашем случае нужна большая
гибкость, поэтому нам нужно использовать метод split() из модуля ге:
»> # В OS X (Мас)
»> fnmatch (' rep. txt ’ , ' * . TXT')
False
»> # В Windows
»> fnmatch (' rep. txt' , ' * . TXT')
True
»> import os
»> filenames = os . listdir (' . ')
»> filenames
[ 'Makefile', 'foo.c', 'bar.py', 'spam.c', 'spam.h' ]
»> [name for name in filenames if name.endswith(('.c', '.h')) ]
['foo.c', 'spam.c', 'spam.h'
»> any(name.endswith('.py') for name in filenames)
True
»> text = 'yeah, but no, but yeah, but no, but yeah'
>>> # Точное совпадение
»> text == 'yeah'
False
»> # Совпадение в начале или в конце
»> text, startswith ('yeah')
True
»> text. endswith ('no ')
False
»> # Поиск позиции первого вхождения искомого текста в строку
»> text. find (' no')
10
Для более сложного соответствия используйте регулярные выражения и мо
дуль ге. Чтобы проиллюстрировать основную механику использования регу
лярных выражений, предположим, что вы хотите найти даты, определенные
как цифры, например "03/19/2021". Вот как это можно сделать:
да
»> if re.match(r'\d+/\d+/\d+', text2):
... print('да')
... else:
... print('нет')
нет
»>
да
»> if datepat .match (text2) :
... print('да')
... else:
... print('нет')
нет
»>
Метод match() всегда пытается найти совпадение в начале строки. Если вам
нужно найти все вхождения, используйте метод findall(). Пример:
»> m = datepat.match('ll/27/2021abcdef')
»> m
<_sre.SRE_Match object at 0xl005d27e8>
»> m. group ()
'11/27/2021'
»>
Если вам нужно точное совпадение, убедитесь, что шаблон в конце содер
жит маркер $, например:
»> datepat = re. compile (r' (\d+) / (\d+) / (\d+) $')
»> datepat.match('ll/27/2021abcdef')
»> datepat .match ('11/27/2021')
<_sre.SRE_Match object at 0xl005d2750>
»> text = 'yeah, but no, but yeah, but no, but yeah'
»> text. replace (' yeah' , ' yep')
'yep, but no, but yep, but no, but yep'
»> import re
»> datepat = re.compile(г'(\d+)/(\d+)/(\d+)')
»> datepat. sub (r'\3-\l-\2 ' , text)
'Сегодня 2021-12-19. Завтра 2021-12-20.'
def matchcase(word):
def replace(m):
text = m.group()
if text.isupper():
return word.upper()
elif text.islower():
return word.lower()
elif text[0].isupper():
return word.capitalize()
else:
return word
return replace
»> re . sub (' python ' , matchcase (' snake ') , text, flags=re . IGNORECASE)
'UPPER SNAKE, lower snake, Mixed Snake'
»> s.lstrip()
'привет мир \п'
»> s. г str ip ()
' привет мир'
»>
Если вам нужно сделать что-то во внутреннем пространстве, вам нужно ис
пользовать другую технику, например, использовать метод гер1асе() или за
мену с использованием регулярных выражений. Например:
»> s . replace (' ' , ' ')
'приветмир '
»> import re
»> re. sub ('\s+' , ' ' , s)
'привет мир'
with open(filename) as f:
lines = (line.strip() for line in f)
for line in lines:
Здесь выражение lines = (line.strip() for line in f) действует как своего рода
преобразование данных. Это эффективно, потому что оно фактически
сначала не считывает данные в какой-либо вид временного списка. Мы
просто создаем итератор, где ко всем считанным строкам сразу применяется
strip().
Глава 8.
СПИСКИ
8.1. Что такое список?
Можно указать все элементы списка в квадратных скобках, как уже было по
казано. Обратите внимание, что элементы могут быть разных типов:
»> 1st = []
»> 1st. append (1)
»> 1st. append (2)
»> 1st.append(3); 1st
[1/ 2, 3]
»>
lst[] = новый_элемент
»> a is Ь
True
Если вам нужно создать вложенные списки, то это лучше делать с помощью
метода append(), например:
»> 1st = []
>» for i in range (3): 1st. append ([] )
»> 1st[0].append(1)
»> 1st
[[1], [], []]
»> а, b, *с = [1, 2, 3, 4]
»> lst[4]
Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
1st[4]
IndexError: list index out of range
[<Начало>:<Конец> :<Шаг>]
>» 1st
[1, 8, 9, 4, 5, б, 7]
»> lst2 = [10, 11, 12]
»> lst3 = 1st + lst2; lst3
[1, 8, 9, 4, 5, 6, 7, 10, 11, 12]
Любой элемент списка может содержать любой объект, в том числе и другой
список, кортеж, словарь и т.д. Вот как можно создать список, состоящий из
трех списков:
»> 1st
[[1, 2, 3], ['а', ’Ь’, ’С’]/ [9, 8, 7]]
»> for i in 1st: print (i, end=" ")
[1, 2, 3] ['a', 'b', ’c'] [9, 8, 7]
Пример:
>>> 1st
[[1, 2, 3], ['а’, 'Ь', 'с'], [9, 8, 7]]
»> 2 in 1st
False
»> 1st = [1, 2, 3, 4]
»> 2 in 1st
True
»> lst.index(7)
Traceback (most recent call last) :
File "<pyshell#72>", line 1, in <module>
1st.index(7)
ValueError: 7 is not in list
insert(<индекс>, <объект>)
Примеры:
»> 1st
[1, 2, 3, 4, 5, 6, 7]
»> 1st. insert (0, 0) # Вставили ноль в начало списка
»> 1st
[0, 1, 2, 3, 4, 5, 6, 7]
»> 1st. insert (8, 8) # Вставили 8 в позицию 8
r® python
»> 1st
[О, 1, 2, 3, 4, 5, б, 7, 8]
»> 1st
[О, 1, 2, 3, 4, 5, 6, 7, 8]
»> Ist.pop(O)
О
»> 1st
[1, 2, 3, 4, 5, б, 7, 8]
»> 1st.pop ()
8
»> 1st
[1, 2, 3, 4, 5, б, 7]
»> 1st
[4, 2, 2, 1, 3]
»> 1st. reverse ()
»> 1st
[3, 1, 2, 2, 4]
sort([key=None] [, reverse=False])
f® python Глава 8. Списки
1st.sort(key=str .lower)
Пример:
»> np.sqrt(an)
array([1.41421356 , 1.41421356, 1.73205081, 1.73205081 ])
»> np.cos(an)
array([-0.41614684, -0.41614684, -0.9899925 , -0.9899925])
Использование универсальных функций может быть в сотни раз быстрее,
чем перебор массива в цикле поэлементно и выполнение необходимых опе
раций над каждым элементом отдельно. Поэтому если вам нужно выполнить
операции с использованием функций из модуля math над элементами масси
ва, взгляните на аналогичные функции модуля пр. Вы должны предпочесть
их, если это возможно.
"За кулисами" массивы NumPy выделяются таким же способом, как и в С
или Fortran. А именно они являются большими, непрерывными областями
памяти, состоящими из однородного типа данных. Именно поэтому вы мо
жете сделать массивы просто огромными, гораздо больше, чем вы себе мо
жете представить. Например, если вы желаете сделать двумерную таблицу
10 000 х 10 000, состоящую из чисел с плавающей запятой, это не проблема.
»> а = пр. array ([ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11,
12]])
»> а
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>» # Ряд 0
»> а[1]
аггау([1, 2, 3, 4])
»> # Колонка 1
»> а[:,1]
array([ 2, 6, 10])
Вывод программы:
Вывод программы:
Как уже было сказано, списки индексируются. Ничего нового нет. Индекса
ция начинается с 0 (то есть первый элемент списка имеет индекс 0), поддер
живаются положительные и отрицательные индексы.
Пример работы с индексами:
start = -len(cars)
end = len(cars)
for i in range(start,end,1):
print("cars[", i, "] = ", cars[i])
f* python Глава 8. Списки
Вывод программы:
cars [ -5 ] = audi
cars [ -4 ] = VW
cars [ -3 ] = lexus
cars [ -2 ] = gtr
cars [ -1 ] = m5
cars [ 0 ] = audi
cars [ 1 ] = VW
cars [ 2 ] = lexus
cars [ 3 ] = gtr
cars [ 4 ] = m5
cars = []
responce = 1
while responce:
print("""Выберите действие:
1 - Добавить авто
Python на примерах •» python
2 - Удалить авто
3 - Вывести список авто
4 - Поиск
5 - Сортировка гаража
О - Выход’"’")
responce = int (input ("» "))
if responce == 1:
car = input("Новое авто: ")
cars.append(car)
elif responce == 2:
car = input("Удалить авто: ")
cars.remove(car)
elif responce == 3:
print(cars)
elif responce == 4:
car = input("Поиск: ")
if car in cars:
print("Такая машина есть в гараже!")
else:
print("Нет такой машины в гараже!")
elif responce == 5:
cars.sort()
print("Отсортировано!")
else:
print("Пока!")
КОРТЕЖИ
Python на примерах
tup = (1, 2, 3, 4, 5, 2, 7)
tup.index(2)
>>> tup.index(2, 2)
5
if not cars:
print("У вас нет машины!")
if "Nissan" in cars:
print("У вас есть Nissan!")
Глава 9. K’op i ежи
О кортежах вам нужно знать еще две вещи. Первая — они, как и строки,
неизменяемые'.
import itertools
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
it.tee ( [1,2,3,4], 2)
(<itertools._tee object at 0x04756558>, citertools._tee object at
0x04756508>)
>»
»> р = (4, 5)
»> х, у = р
»> X
4
»> у
5
»> р = (4, 5)
»> X, у, Z = р
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 2 values to unpack
»> s = 'Hello’
»> a, b, c, d, e = s
>» a
•H'
»> b
' e'
»> e
' о'
Стоит отметить, что переменная phone numbers всегда будет списком, не
зависимо от того, сколько телефонных номеров распаковано (даже если ни
один). Таким образом, любой код, использующий phone numbers, должен
всегда считать ее списком или хотя бы производить дополнительную про
верку типа.
Переменная со звездочкой может также быть первой в списке. Например,
скажем, что у вас есть последовательность значений, представляющая
объемы продаж вашей компании за последние 8 кварталов.
Если вы хотите видеть, как самый последний квартал складывается в сред
ний по первым семи кварталам, вы можете выполнить подобный код:
records = [
(’foo', 1, 2),
(’bar', 'hello'),
('foo', 3, 4),
.1
def do_bar(s):
print('bar', s)
»> а = (1, 2, 3, 4, 5, 6)
»> b = [1, 2, 3, 4, 5, б]
»> а.__ sizeof__ ()
36
»> Ь.__ sizeof__ ()
44
»> d = { (1, 1, 1) : 1}
»> d
{ (1, 1, 1) : И
»> d = { [1, 1, 1] : 1}
Python на примерах python
МНОЖЕСТВА И СЛОВАРИ
В PYTHON
Python на примерах python
»> d = diet ()
»> d = diet(name='Иван’, surname='Иванов'); d
{’name': 'Иван', 'surname': 'Иванов'}
»> d = diet({"name": "Иван", "surname": "Иванов"}); d
{'name': 'Иван', 'surname': 'Иванов'}
»> d = diet([["name", "Иван"], ["surname", "Иванов"]]); d
{'name': 'Иван', 'surname': 'Иванов'}
»> d = diet([("name", "Иван"), ("surname", "Иванов")]); d
{'name': 'Иван', 'surname': 'Иванов'}
>»
»> d
»> d["name"] = "Иван"
>» d["surname" = "Иванов"
Если вам удобно, вы можете указать все элементы словаря в фигурных скоб
ках:
»> d = {}
>» d = {"name": "Иван", "surname": "Иванов"}; d
{'name': 'Иван', 'surname': 'Иванов'}
»> d["name"]
'Иван'
»> d["lastname"]
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
d["lastname"]
KeyError: 'lastname'
»> "surname" in d
True
»> "lastname" in d
False
»>
»> d
{'name': 'Иван', 'surname': 'Иванов'}
>» d [ "lastname" ] = "Иванов"
»> d
{'lastname': 'Иванов', 'name': 'Иван', 'surname': 'Иванов'}
Если ключ есть в словаре, то ему будем присвоено новое значение. Если
ключа нет, то он будет добавлен в словарь.
Удалить ключ из словаря можно с помощью оператора del:
»> d
{'lastname': 'Иванов', 'name': 'Иван', 'surname': 'Иванов'}
»> del d["lastname"] ; d
{'name': 'Иван', 'surname': 'Иванов'}
»> d["lastname"]="Иванов"
»> d["zip"]="109011"
»> d
{'zip': *109011', 'lastname': 'Иванов', 'name': 'Иван', 'surname': 'Иванов'}
»> keys = list (d. keys () )
»> keys. sort()
»> for key in keys:
print("({0}=> {1})".format(key, d[key]), end=" ")
»> d.get("lastname")
'Иванов'
»> d [ "lastname" ]
'Иванов'
Особого смысла в этом методе нет, как и в методе с1еаг(), который очищает
словарь. А вот метод рор() может пригодиться. Он удаляет элемент и воз
вращает его значение:
if "bus" in diet:
print(diet["bus"])
else:
print ("Слова нет в словаре!")
diet = {
"apple" : "яблоко",
"bold" : "жирный",
"bus" : "автобус",
"cat" : "кошка",
Г* python Глава К). Множества и словари в Python
"саг" "машина"}
word = ""
while word != "q":
word = input ("Введите слово или q для выхода: ")
if word != "q":
if word in diet:
print(diet[word] )
else:
print("He найдено")
choice = ""
while choice != "q":
choice = input("(h - help)>> ")
if choice == "s":
word = input ("Введите слово: ’’)
res = diet.get(word, "He найдено!")
print(res)
elif choice == "a":
word = input("Введите слово: ’’)
value = input("Введите перевод: ")
diet[word] = value
print("Слово добавлено!")
elif choice == "r":
word = input ("Введите слово: ")
del diet[word]
print("Слово удалено")
elif choice == "k":
print(diet.keys())
elif choice == "d":
for word in diet:
print(word, ": ", diet[word])
elif choice == "h":
print(help_message)
elif choice == "q":
continue;
else:
print("Нераспознанная команда. Введите h для справки")
choice = ""
while choice != "q":
choice = input (”(h - help)» ")
f3 python Глава 10. Множества и словари в Python
if choice == "s":
word = input("Введите слово: ")
res = diet.get(word, "He найдено!")
print(res)
А вот вывод всех слов подойдет разве что для отладки. При желании вы
можете модифицировать код, чтобы он выводил список слов в удобном для
человека формате:
(h - help)>> k
dict_keys(['bus', 'apple', 'cat', 'bold', 'phone', 'car'])
Python на примерах python
с:\temp\ру>python dict.py i
=------ Diet V 0.2 --^--^ = = ^xS==
(h - help)>> h
s - Поиск
а Добавить новое слово
г Удалить слово
к - Показать все слова
d - Показать весь словарь
h - Справка
q Выход
(h help)>> k
diet keys((’apple’, 'bold*, ’bus’, ’cat’, ‘car’])
(h - help)>> d
apple ; яблоко
bold : мирный
bus : автобус j
cat : кошка
c ar :
(h - help)>> s
Введите слово: bus
автобус
(h help)>>
»> s = set ()
»> s
set ()
Мы только что создали пустое множество. Однако функция set() может пре
образовать во множество другие типы данных — строки, кортежи, списки.
При преобразовании других типов данных помните, что во множестве оста
нутся только уникальные элементы:
1 о e H
»> len(s)
4
»> si = set([l, 2, 3] )
»> s2 = set([3, 4, 5])
»> s3 = si I s2; s3
{1/ 2, 3, 4, 5}
»> si |= s2; si
{1, 2, 3, 4, 5}
»> si
{1, 2, 3, 4, 5}
»> s2
{3, 4, 5}
»> si - s2
{1, 2}
»> si Л s2
{1, 2, 4, 5}
»> si
{1, 2, 3}
»> 3 in si
True
»> 4 in si
False
»> si == s2
False
»>
»> si
(1, 2, 3}
»> s2
{3, 4, 5}
»> si <= s2
False
»> si
{1, 2, 3}
> » sl.add(4)
> » si. remove (4) ; si
{1, 2, 3}
»> si. remove (4)
Traceback (most recent call last):
File "<pyshell#100>", line 1, in <module>
si.remove(4)
KeyError: 4
> » si. discard (4)
Глава 11.
ПРИМЕРЫ ПОЛЬЗОВАТЕЛЬСКИХ
ФУНКЦИЙ
Python на примерах pythor
def <Имя_функции>([Параметры]):
<Тело функции>
[return <3начение>]
k = msum(3,5)
print(к)
s = msum
k = s (3, 5)
def msum(x, у)
return х + у
k = fsum(msum, 3, 5)
Как видите, если второй параметр не задан, то его значение будет равно 2.
Обратите внимание, что все необязательные параметры должны следовать
после обязательных. Смешивать их нельзя, иначе получите сообщение об
ошибке.
1 python Глава 11. Примеры пользовательских функций
msum(4, 5)
»> 11 = (2, 3)
»> msum(*ll)
5
return х
Python на примерах python
»> у = 2
»> test (у)
1
»> у
2
import html
Примеры использования:
# Создаем '<p><Car></p>'
make_element('p', '<Car>')
»> add(2,2)
4
»> х = 10
>» а = lambda у: х + у
»> х = 20
>>> b = lambda у: х + у
Теперь задайте себе вопрос. Каковы значения а( 10) и b( 10)? Если вы думае
те, что 20 и 30, то вы ошибаетесь.
»> а(10)
30
>» Ь(10)
30
»> х = 15
»> а(10)
25
>>> х = 3
»> а(10)
13
»> х = 10
»> а = lambda у, х=х: х + у
Python на примерах python
»> х = 20
>» b = lambda у, x=x: x + у
»> a(10)
20
»> b(10)
30
»>
Как видите, функция print result() принимает только один аргумент, кото
рый является результатом. Никакая другая информация не передается в нее.
Такой недостаток информации иногда может представлять проблему, напри
мер, когда вы хотите, чтобы функция обратного вызова взаимодействовала с
другими переменными или частями среды.
Один из способов хранить дополнительную информацию в функции обрат
ного вызова — использовать метод (и, соответственно, класс) вместо функ
ции. Например, следующий класс хранит внутренний номер последователь
ности, который вызывается при каждом вызове метода handler():
class ResultHandler:
def __ init__ (self):
self.sequence = 0
def handler(self, result):
self.sequence += 1
print('[{}] Результат: {}'.format(self.sequence, result))
»> г = ResultHandler ()
»> apply_async(add, (2, 3), callback=r.handler)
[1] Result: 5
>» apply_async(add, ('hello', 'world'), callback=r.handler)
[2] Result: helloworld
11.5. Функции-генераторы
11.6. Декораторы
def deco(f) :
print("my_func is running")
return f
@deco
def my_func(x):
return x * 2
print(my_func(5))
f® python Глава II. Примеры пользовательских функций
11.7. Рекурсия
def fact(n):
if n == 0 or n == 1: return 1
else:
return n * fact(n - 1)
11.8.1 . Инкапсуляция
def fun():
res = 10
return res
def funl():
res = 10
print(res)
def fun2 ()
res = 20
print(res)
I® python Глава 11. Примеры пользовательских функций
res = 30
print(res)
funl ()
fun2 ()
print(res)
30
10
20
30
def funl():
global res
print(res)
def fun2 () :
res = 20
print(res)
Python на примерах f® python
res = 30
print(res)
funl ()
fun2 ()
print(res)
30
30
20
30
def fun2 () :
global res
print(res)
res = 30
print(res)
funl ()
fun2 ()
print(res)
после функции funl(), получает уже новое значение — 50. Поскольку функ
ция funl() изменила значение переменной res() в глобальной области, то
последний оператор print() отобразит также 50. В итоге вывод программы
будет таким:
30
50
50
50
def warning(message):
Выводит сообщение, заданное параметром message,
обрамленное символами * для привлечения внимания """
print ("*" * 10, message, * 10)
def fun():
return 1, 2, 3
a, b, с = fun()
print(a, b, с)
12 3
»> х = fun ()
»> X
(1, 2, 3)
»>
hello("Марк", "Санкт-Петербург")
hello("Санкт-Петербург", "Марк")
I
Тогда параметру name будет передано значение "Санкт-Петербург", а пара
метру city — "Марк". В итоге вывод будет не таким, как мы ожидали:
Это у нас еще простой случай, а представьте, если бы второй параметр был
числом и далее шла его обработка как числа. Тогда мы бы получили ошибку,
и выполнение программы было бы остановлено!
Специально для таких случаев предназначены именованные аргументы.
Они позволяют указывать аргументы в любом порядке при условии, что мы
задаем имя аргумента. Вызовем функцию так:
def rss_reader(url):
from urllib.request import urlopen
from xml.etree.ElementTree import parse
print (title)
print(date)
print(link)
print ()
rss_reader('http://example.com/rss.php')
Итак, у нас есть функция rss_reader(), которой нужно передать адрес новост
ной ленты. Посмотрим, что происходит внутри функции. Первым делом им
портируются модули urlopen и parse. Первый нужен для открытия удален
ного документа, второй — для разбора (парсинга XML-формата, в котором и
распространяется новостная лента).
Далее в переменную и мы читаем новостную ленту, адрес которой задается
параметром url. После мы выполняем парсинг этой ленты и результат
сохраняем в doc.
Переменная doc содержит уже "разобранную" новостную ленту. Функция
xml.etree.ElementTree.parse() парсит весь XML-документ в объект докумен
Python на примерах python
РАЗБИРАЕМСЯ С
МОДУЛЯМИ И ПАКЕТАМИ
В PYTHON
Python па примерах python
Например:
itertools.count()
Например:
import itertools as it
it.count ()
import math as m
a = m.pi * 10
# coding: utf-8
a = О
# coding: utf-8
import module as m
a = 2
print(a)
print(m.a)
input ()
Пример:
а = pi * 10
# coding: utf-8
from module import *
a = 2
print(a)
input()
В каких каталогах Python будет искать модули? В самом простом случае мо
дули размещаются в одном каталоге с вашей программой. В этом случае нет
необходимости настраивать пути поиска, поскольку текущий каталог авто
матически включается в путь поиска.
Просмотреть текущий путь поиска можно с помощью следующих команд:
С:\projects\my_libs
С:\python\my_py
Модуль загружается только один раз — при первой операции импорта. Все
последующие вызовы import будут возвращать уже загруженный объект мо
дуля, даже если сам модуль был изменен. Допустим, вы изменили модуль,
как его загрузить заново?
Для этого нужно использовать функцию reload() из модуля imp:
12.6. EGG-файлы
Например,
python easy_install .ру -Z pytz.egg
Пусть у нас есть модуль, который нам нужно разделить на несколько файлов.
Необходимо это сделать, не повредив существующий код, сохраняя отдель
ные файлы объединенными как единственный логический модуль.
Программный модуль можно разделить на отдельные файлы, превратить его
в пакет. Рассмотрим следующий простой модуль:
# mymodule.py
class А:
def test(self):
print('A. test')
class В(A) :
def bar(self) :
print('B.bar')
mymodule/
_init__ .ру
а.ру
Ь.ру
# а.ру
class А:
def test(self):
print('A.test')
python Глава 12. Разбираемся с модулями и пакетами и Python
# Ь.ру
from .a import А
class В(А):
def bar(self):
print('В.bar')
Наконец, в файл__ init .ру поместите код, соединяющий все это вместе:
# init__ .ру
from .a import А
from .b import В
На этот раз у нас есть много кода, разделенного на части и, возможно, обслу
живаемого и распределяемого разными людьми. Каждая часть кода органи
зована как каталог файлов, подобно пакету. Однако вместо того, чтобы уста
новить каждую часть как отдельный именованный пакет, вы хотите, чтобы
все части были объединены под одним общим префиксом пакета.
По существу, задача заключается в том, что нужно определить пакет Python
верхнего уровня, который служит пространством имен для большого коли
чества отдельно сохраняемых подпакетов. Эта проблема часто возникает в
больших фреймворках, где разработчики хотят поощрить пользователей рас
пределять плагины или дополнительные пакеты.
Чтобы объединить отдельные каталоги под общим пространством имен,
нужно организовать код в виде обычного пакета, но опустить файлы__ init__ .
ру в каталогах, где будут объединяться компоненты. Рассмотрим небольшой
пример. Предположим, что у вас есть два разных каталога кода:
f® python Глава 12. Разбираемся с модулями и пакетами в Python
fоо-package/
test/
id.ру
bar-package/
test/
run.py
В этих каталогах имя test используется как общее пространство имен. Обра
тите внимание, что здесь нет файлов__ init__ .ру — ни в одном из каталогов.
Теперь посмотрим, что произойдет, если вы добавите оба каталога —
foo-package и bar-package — в модуль Python и попытаетесь вызвать некото
рые операторы импорта:
my-package/
test/
custom.ру
»> test
cmodule 'test' (namespace)>
python Глава 12. Разбираемся с модулями и пакетами в Python
# test.ру
def bar():
print('bar')
def run () :
print('run')
myapplication/
test.ру
bar.ру
run.ру
_main__ .ру
$ python3 myapplication
$ 1s
test.py bar.py run.py __ main__ .py
$ zip —r myapp.zip *.py
$ python3 myapp.zip
... вывод из __ main__ .py ...
# myapplication.pth
/some/dir
/other/dir
import sys
sys.path.insert(0, '/some/dir')
sys.path.insert(0, '/other/dir')
import sys
from os.path import abspath, join, dirname
sys.path.insert(0, abspath(dirname('__ file__ '), 'src'))
projectname/
README.txt
Doc/
documentation.txt
projectname/
__init__ .py
foo.py
bar.py
utils/
_init__ .py
test.py
run.py
examples/
helloworld.py
# setup.ру
from distutils.core import setup
setup(name='projectname',
version='1.0' ,
author='Ваше имя',
author_email='[email protected]',
url='http://www.you.com/projectname',
packages=['projectname', 'projectname.utils'],
)
# MANIFEST.in
include *.txt
recursive-include examples *
recursive-include Doc *
ОБРАБОТКА ИСКЛЮЧЕНИЙ
Python на примерах f® python
»> а = 10 / О
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
a = 10 / 0
ZeroDivisionError: division by zero
>>> "Hello".index('hi')
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
"Hello".index('hi')
ValueError: substring not found
»> а = [1, 2, 3]
»> а[6] = 1
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
a[6] = 1
IndexError: list assignment index out of range
Разные типы ошибок генерируют разные типы исключений. Как было по
казано ранее, при попытке открыть несуществующий файл было сгенериро-
Python на примерах python
Исключение Описание
BaseException
GeneratorExit (в Python 2.6 и выше)
Keyboardinterrupt
SystemExit
Python на примерах Г* python
Exception
GeneratorExit (в Python 2.5)
Stopiteration
Warning
BytesWarning (в Python 2 ..6 и выше)
DeprecationWarning, Futurewarning, Importwarning
PendingDeprecationWarning, Runtimewarning, Syntaxwarning
UnicodeWarning, UserWarning
StandardError
ArithmeticError
FloatingPointError, OverflowError , ZeroDivisionError
AssertionError
AttributeError
BufferError (в Python 2.6)
EnvironmentError
lOError
OSError
WindowsError
EOFError
ImportError
LookupError
IndexError, KeyError
MemoryError
NameError
UnboundLocalError
ReferenceError
RuntimeError
NotImplementedError
SyntaxError
IndentationError
TabError
SystemError
TypeError
ValueError
UnicodeError
UnicodeDecodeError , UnicodeEncodeError
UnicodeTranslateError
try: .
а = int(input("Введите целое а: "))
b = int(input ("Введите целое Ь: "))
print("а/b = ", а/Ь)
except ValueError:
print("Нужно ввести целое!!!")
except ZeroDivisionError:
print("Деление на О!")
»
try:
а = int(input("Введите целое а: "))
b = int(input("Введите целое Ь: "))
print("а/b = ", а/Ь)
except ValueError:
print("Нужно ввести целое!!!")
except -ZeroDivisionError as е:
print("Деление на О!")
print("Сообщение Python:")
print(е)
Python на примерах python
На рис. 13.1 показано, что, кроме наших сообщений, самим Python будет
выведено сообщение division by zero.
Ln: 10 Col: 4
try:
<Код, в котором могут возникнуть исключения>
[except [<Исключение1> [as <0бъект исключения>]]:
<Код, выполняемый при перехвате исключения 1>]
[•••
[except [<ИсключениеЫ> [as <0бъект исключения?»] ] :
<Код, выполняемый при перехвате исключения N>]]
[else:
<Код, который будет выполнен, если исключение не возникло>]
[finally:
<Код, который будет выполнен в любом случае>]
try:
а = 10 / О
except ZeroDivisionError:
print('ZeroDivisionError ')
a = 0
print(a)
try:
х = 10 / 0
except ZeroDivisionError:
print(’ZeroDivisionError')
else:
print('Оператор Else')
finally:
print('Оператор Finally')
ZeroDivisionError
Оператор Finally
Затем замените 0 на 5:
х = 10 / 5
Оператор Else
Оператор Finally
class SampleClass:
def __ enter___(self):
print('Enter') .
return self
def __ exit__ (self, Type, Value, Trace):
print(’Exit')
if Type is None: # Исключения не было
print(’Нет исключений')
else:
print('Значение = ', Value)
return False # False - исключение не обработано
with SampleClass():
print('Внутри')
raise TypeError('TypeError Exception')
Пример:
try:
raise ValueError("Info")
except ValueError as msg:
print(msg) # Выведет: Info
if __ debug_
if not Логическое выражением
raise AssertionError(<Инфо>)
Пример:
try:
х = -5
assert x >= 0, "Error"
except AssertionError as err:
print(err) # Выведет Error
Глава 14.
ООП И PYTHON
L
Python на примерах python
class SampleClass:
def __ init__ (self):
print("Constructor")
self.nm = "SampleClass"
def printName(self):
print(self.nm)
obj = SampleClass()
obj.printName()
»>
Constructor
SampleClass
SampleClass
<Объект>.<Метод>([Параметры])
<Объект>.<Атрибут>
14.4. Наследование
•
obj = Child ()
obj.print_name()
obj.print_child()
А что, если в дочернем классе вам захочется определить такой же метод, как
и в родительском? Например:
obj = Child ()
obj.print_name()
Какой метод будет вызван? Будет вызван метод дочернего класса, поскольку
он переопределит метод с таким же именем родительского класса. Если нуж
но вызвать именно метод родительского класса, тогда нужно явно указать
имя класса, например:
def print_name(self):
print("Потомок")
Parent.print_name()
Метод Описание
QBE
1 python Глава 14 ООП и Python
class IterClass:
def __ init__ (self, x) :
self.massiv = x
self.ind =0 # Индекс
def iter (self):
return self
def next (self):
if self.ind >= len(self.massiv):
self.ind = 0 ' # Сбрасываем индекс
raise Stopiteration # Генерируем исключение
else:
item = self.massiv[self.ind]
self.ind += 1
return item
Внутри класса можно создать метод, который будет доступен без создания
экземпляра класса. Для определения статического метода используется де
коратор @staticmethod. Вызывается статический метод так:
Пример:
class StaticSample:
@staticmethod
def ssum(x, y):
return x + у
def msum(self, x, y) :
return x + у
f® python
class Sample:
def func(self, x, у):
raise NotlmplementedError("Not implemented")
def msum(self, x, y):
return x + у
class Sample:
@abstractmethod
def func(self, x, y):
pass
def msum(self, x, y):
return x + у
|в python Глава 14. ООП и Python
class ReloadClass:
def __ init__ (self):
self.x = 0
self.a = [1, 2, 3]
def __ eq__ (self, x):
return self.x == у
def __ contains__ (self, y):
return у in self.a
о = ReloadClass()
if о == 10:
print("True")
else:
print("False" ) # Выведет False
if 3 in o:
print("True") # Выведет True
else:
print("False")
Метод Оператор
x. floordiv__ (у) х Ну
x._eq_(y) х==у
x.__ ne (y) х != у
Глава 14. ООП и Python
x._lt_(y) X <y
x._gt_(y) X >y
x._le_(y) X <:=y
x-_ge_(y) X ->=y
class PropertySampleClass:
def __ init__ (self, x):
self.__ p = x
def get_p(self):
return self.__ p
def set_p(self, x) :
self.__ p = x
def del_p(self) :
del self._p
prop = property(get_p, set_p, del_p, "Info")
о = PropertySampleClass (1)
print (o.prop) # Вызывается метод get_p
o.prop - 5 # Вызывается метод set_p
del o.prop # Вызывается метод del_p
Python на примерах |ЯЬ python
def deco(d):
print("Декоратор")
return d
@deco
class SampleClass:
def __ init__ (self, value):
self.v = value
о = SampleClass(1)
print(o.v)
Глава 15.
ПРИМЕРЫ ИТЕРАТОРОВ
И ГЕНЕРАТОРОВ
Python на примерах python
line = next(f)
print(line, end=’’)
except Stopiteration:
pass
with open(’cron.log') as f:
while True:
line = next(f, None)
if line is None:
break
print(line, end='')
class Node:
def __ init___ (self, value) :
self._yalue = value
self.—Children = []
# Пример
if __ name__ == '__ main__ ' :
root = Node(O)
childl = Node(l)
child2 = Node(2)
root.add—child(childl)
root.add—child(child2)
for ch in root:
print(ch)
# Выводит Node(l), Node(2)
Чтобы использовать эту функцию, вам нужно итерировать по ней в цикле for
или использовать ее с другой функцией, работающей с итерируемым (напри
мер, sum(), list() и т.д.). Например:
0
0.5
Python на примерах python
1.0
1.5
2.0
2.5
3.0
3.5
»> list (my_range (0 , 1, 0.125))
[0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875]
class Node:
def __ init___ (self, value) :
self._value = value
self._children = []
# Пример
if __ name__ == '__ main__ ' :
root = Node(O)
childl = Node(l)
child2 = Node(2)
root.add—child(childl)
root.add—child(child2)
Python па примерах python
childl.add_child(Node(3))
childl.add_child(Node(4))
child2.add_child(Node(5))
for ch in root.depth_first():
print(ch)
# Выведет Node(O), Node(l), Node(3), Node(4), Node(2), Node(5)
class Node:
def __ init__ (self, value) :
self._value = value
self.—Children = []
def depth—first(self):
return DepthFirstlterator(self)
class DepthFirstlterator(object):
9 9 9
Обход в глубину
9 9 9
def __ init__ (self, start_node) :
self.—node = start_node
python Глава 15. Примеры итераторов и генераторов
»> а = [1, 2, 3, 4]
»> for х in reversed (а) :
print(х)
Python на примерах f® python
4
3
2
1
Обратная итерация работает только, если объект имеет размер, который мо
жет быть определен, или же у объекта реализован специальный метод
reversed (). Если для вашего объекта не выполняется ни то, ни другое,
вам нужно сначала конвертировать ваш объект в список. Например:
class Countdown:
def __ init__ (self, start) :
self.start = start
# Итератор вперед
def __ iter__ (self) :
n = self.start
while n > 0:
yield n
n -= 1
# Итератор назад
def __ reversed__ (self):
n = 1
while n <= self.start:
yield n
n += 1
python Глава 15. Примеры итераторов и генераторов
class linehistory:
def __ init__ (self, lines, histlen=3) :
self.lines = lines
self.history = deque(maxlen=histlen)
def clear(self):
self.history.clear ()
# Comment line 1
# Comment line 2
Line 1
Line 2
Line 3
»>
Если вам нужно пропустить все начальные комментарии, вам нужно сделать
это:
Line 1
Line 2
Line 3
1
4
10
15
»>
Python на примерах python
('a’, ’b')
('a', 'c')
f* python Глава 15. Примеры итераторов и генераторов
(’ Ь ’, ’ а ’)
ГЬ’, ’с')
(’с’, 'а')
('С, ' b')
»>
Ln: 15 Col: 4
('a', ’b’)
('a’, 'c')
('b', 'c')
»> for c in combinations (items, 1) :
. .. print(c)
(’a',)
('b',)
<’c’,)
Python на примерах python
МЕТАПРОГРАММИРОВАНИЕ В
PYTHON
Python на примерах python
class Person(models.Model) :
name =^models.CharFieId(max_length=30)
age = models.IntegerField()
он не вернет объект IntegerField. Он вернет код int и даже может взять его
непосредственно из базы данных.
r* python Глава 16. Метанрограммирование в Python
16.2. Декораторы
import time
def timeit_all_methods(cis) :
class NewCls:
def __ init__ (self, *args, **kwargs):
# Проксируем полностью создание класса
# Создаем декорируемый класс
self._obj = cls(*args, **kwargs)
# Метод ли он?
if isinstance(attr, type(self.__ init__ )):
# Да, обернуть его в измеритель времени
return timeit(attr)
else:
# Не метод, что-то другое
return attr
return NewCls
@time_all_class_methods
class Foo:
def a(self):
print("метод а начинает работу")
time.sleep(0.888)
print("метод а завершает работу")
f = Foo()
f .a()
def parametrized_short_mtd(max_width=8) :
"""Параметризованный декоратор, сокращающий представление"""
def parametrized(cis):
"""Внутренняя функция-оболочка, которая по сути является декоратором"""
class ShortlyRepresented(cis) :
"""Подкласс, представляющий поведение декоратора"""
def __ mtd__ (self):
return super().__ mtd__ ()[:max_width]
return ShortlyRepresented
return parametrized
f* python Глава 16. Метапрограммирование в Python
@parametrized_short_mtd (10)
class ClassWithLittleBitLongerLongName :
pass
16.3. Метаклассы
def method(self):
return 1
class MyCls:
def method(self) :
return 1
I •
class CIMeta(metaclass=type) :
pass
Почему имя type() пишется со строчной буквы? Скорее всего, это вопрос
соответствия со str — классом, который отвечает за создание строк, и int —
классом, создающим целочисленные объекты, type — это просто класс, соз
дающий объекты класса. Проверить можно с помощью атрибута__ class__ .
Все, что вы видите в Python, — объекты. В том числе и строки, числа, классы
и функции. Все это объекты, и все они были созданы из класса:
ctype 'str’>
»> age = 38
»> age.__ class_
ctype ’int’>
»> def foo(): pass
»> foo.__ class_
ctype 'function'>
>>> class Cis(object): pass
>» c = cis ()
>» c.__ class_
cclass '__ main__ .Cls'>
Итак, метакласс создает объекты класса. Это можно назвать "фабрикой клас
сов". type — встроенный метакласс, который использует Python. Програм
мист может также создать свой собственный метакласс.
Вернемся к атрибуту_ metaclass__ . При определении класса вы можете ука
зать этот атрибут:
class Foo(object):
_metaclass__ = something...
[...]
После этого Python будет использовать метакласс для создания класса Foo.
Если написать class Foo(object), объект класса Foo не сразу создастся в памя
ти. Python будет искать__ metaclass__ . Как только атрибут будет найден, он
будет использоваться для создания класса Foo. В том случае, если этого не
произойдет, Python будет использовать type для создания класса.
Python на примерах f" python
Рассмотрим пример:
class Foo(Bar):
pass
# в верхний регистр
uppercase_attr = (}
for name, val in future_class_attr.items():
if not name.startswith ('__ '):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
print(hasattr(Foo, 'bar'))
# Выводит: False
print(hasattr(Foo, 'BAR'))
# Выводит: True
f = Foo()
print (f.BAR)
# Выводит: ’bip'
uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__ '):
uppercase_attr[name.upper()] = val
else:
Python на примерах t® python
uppercase_attr[name] = val
uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__ ’):
uppercase_attr[name .upper()] = val
else:
uppercase_attr[name] = val
class UpperAttrMetaclass(type):
uppercase_attr = {}
for name, val in det.items():
if not name.startswith('__ '):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
class UpperAttrMetaclass(type):
uppercase_attr = {}
for name, val in det.items():
if not name.startswith('__ '):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
Собственно, это все, что вам нужно знать о метаклассах. Причина сложно
сти кода, который использует метаклассы, даже не в самих метаклассах. Код
становится сложным, поскольку обычно метаклассы используют для слож
ных задач, основанных на наследовании и манипуляции такими переменны
ми, как__ diet__ . Также посредством метаклассов вы можете:
Как видите, exec тоже успешно выполняет байт-код (не обязательно пере
давать строку). Поскольку переменная кода на самом деле является объек
том типа code, а не строкой. Второй аргумент для компиляции — подсказка
имени файла. Если мы компилируем из реальной строки, мы должны указать
значение, заключенное в угловые скобки, потому что это то, что будет делать
Python. <string> и <stdin> — общие значения. Если у вас есть файл, укажите
здесь фактическое имя файла. Последний параметр может быть одним из
"exec", "eval" или "single". Первый — это то, что использует ехес, второй
— то, что использует функция eval. Разница в том, что первый может содер
жать операторы, второй — только выражения, 'single' — это разновидность
гибридного режима, который бесполезен для всего, кроме интерактивных
оболочек. Он существует исключительно для реализации таких вещей, как
интерактивная оболочка Python, и очень ограничен в использовании.
Однако здесь мы уже использовали функцию, которую вы никогда не долж
ны использовать: выполнение кода в пространстве имен вызывающего кода.
Что делать вместо этого? Выполнить в новой среде:
Зачем так делать? Более понятное средство для начинающих, поскольку ехес
без словаря должен обойти некоторые детали реализации в интерпретаторе.
Мы поговорим об этом позже.
Python на примерах f® python
Однако в Python 3 оператор ехес ... in исчез, и вместо этого вы можете ис
пользовать новую функцию ехес, которая принимает глобальные и локаль
ные словари в качестве параметров.
А вот теперь мы можем поговорить о производительности. Насколько
быстрее выполняется байт-код по сравнению с созданием байт-кода и его
выполнением:
В 32 (!) раза быстрее даже на таком простом примере. И чем больше у вас
кода, тем хуже становится ситуация. Почему так происходит? Поскольку
синтаксический анализ кода Python и преобразование его в байт-код —.
дорогостоящая операция по сравнению с оценкой байт-кода.
Хорошо, урок усвоен. Сначала компиляция, а затем выполнение уже отком
пилированного кода. Но что еще нужно учитывать при использовании ехес?
Следующее, что вы должны помнить, это огромная разница между глобаль
ной и локальной областью видимости. Хотя и глобальная, и локальная об
ласть видимости используют словари в качестве хранилища данных,
последняя на самом деле нет. Локальные переменные в Python просто бе
рутся из локального словаря фрейма и помещаются туда по мере необхо
димости. Для всех вычислений, которые происходят между ними, словарь
никогда не используется. Вы можете быстро убедиться в этом сами.
Выполните в интерпретаторе Python следующее:
»> а = 42
»> locals ()['а' ] = 23
»> а
23
python Глава 16. Meiaiipoi раммнрование в Python
»> foo ()
42
Совсем не то, что мы ожидали, правда? Но это еще раз красочно демонстри
рует, что локальные переменные — не совсем локальные, по крайней мере,
в контексте программы, а не функции. Об этом нужно помнить просто при
программировании, не говоря уже об использовании exec/eval.
А что можно сказать о производительности кода, выполняемого в глобаль
ной области, по сравнению с кодом, который выполняется в локальной обла
сти? Это намного сложнее измерить, потому что модуль timeit по умолчанию
не позволяет нам выполнять код в глобальной области видимости. Поэтому
нам нужно будет написать небольшой вспомогательный модуль, который
эмулирует это:
code_global = compile('''
sum = О
for х in xrange(500000) :
sum += x
'<string>’, 'exec')
code_local = compiled''
def f () :
sum = 0
for x in xrange(500000):
Python на примерах f® python
sum += x
' ' ', '<string>', 'exec')
def test_global():
exec code_global in {}
def test_local():
ns = { }
exec code_local in ns
ns['f ' ] ()
Если вы используете exec для выполнения кода Python, будьте готовы к тому,
что некоторые модули, такие как pickle, inspect, pkgutil, pydoc и, возможно,
некоторые другие, которые зависят от них, не будут работать должным об
разом.
Python на примерах 1 python
class Foo(object):
def __ del___(self):
print 'Deleted'
foo = Foo()
$ python test.py
Deleted
Теперь, когда мы знаем причину, почему этого не происходит, если у вас есть
модуль? Причина в том, что Python выполняет некоторый трюк при закрытии
модуля. Он переопределит все глобальные значения, которые не начинаются
с подчеркивания с None. Мы можем легко убедиться в этом, если введем зна
чение foo вместо Deleted'.
class Foo(object):
def __ del__ (self):
print, foo
foo = Foo()
$ python test.py
None
Уважаемые авторы!
PYTHON
НА ПРИМЕРАХ
Python НА ПРИМЕРАХ
ПРАКТИКА, ПРАКТИКА И ТОЛЬКО ПРАКТИКА
Книга будет полезна как для тех, кто только заинтересовался Python, так и для
тех, кто хочет улучшить свои навыки в программировании на Python.