автор: Дьяконов Александр www.dyakonov.org
для поддержки курсов автора, в частности https://github.com/Dyakonov/IML
Python ("питон" или "пайтон") в честь комедийных серий BBC "Летающий цирк Монти-Пайтона"
создатель: голландец Гвидо ван Россум (Guido van Rossum) в 1991 году
Поддерживаемые парадигмы:
Ветки (несовмесимые) языка:
Особенности:
# ---
print ('ответ =', \
3) # комментарий
"""
нет
многострочных
комментариев
"""
ответ = 3
'\nнет\nмногострочных\nкомментариев\n'
# функция
# if - условный оператор
def sgn(x):
"""
функция 'знак числа'
+1 - для положительного аргумента
-1 - для отрицательного аргумента
0 - для нуля
Пример: sgn(-2.1) = -1
"""
if x > 0:
a = +1
elif x < 0:
a = -1
else:
a = 0
return a
sgn(2.1), sgn(0), sgn(-2)
(1, 0, -1)
# вывод по команде help
help (sgn)
Help on function sgn in module __main__: sgn(x) функция 'знак числа' +1 - для положительного аргумента -1 - для отрицательного аргумента 0 - для нуля Пример: sgn(-2.1) = -1
# ещё вариант if-a
x = 0.01
"nonzero" if x != 0 else "zero"
'nonzero'
# помощь по функции
help (sgn)
Help on function sgn in module __main__: sgn(x) функция 'знак числа' +1 - для положительного аргумента -1 - для отрицательного аргумента 0 - для нуля Пример: sgn(-2.1) = -1
# цикл
# строки
# s = "1234567"
s = input("Введите строку:")
while s: # s != "":
print (s)
s = s[1:-1]
# цикла repeat - нет!
Введите строку:abc abc b
# for - цикл
for i in range(1, 4):
s = ""
for j in range(1, 4):
s += ("%i " % (i * j))
#print ("%i" % (i*j),)
print (s)
1 2 3 2 4 6 3 6 9
# можно много по чему итерироваться
for i in [10, 20]:
for j in 'ab':
print (i, j)
# нет явного счётчика - об этом позже
10 a 10 b 20 a 20 b
# Пример решения задачи на Питоне
import math
def primes(N):
"""Возвращает все простые от 2 до N"""
sieve = set(range(2, N))
for i in range(2, round(math.sqrt(N))):
if i in sieve:
sieve -= set(range(2 * i, N, i))
return sieve
primes(20)
{2, 3, 5, 7, 11, 13, 17, 19}
continue # нет примера
break # нет примера
[1, 2, 3]
[1, 2, 3]
_[0] # предыдущая ячейка
1
sum(__) # пред-предыдущая ячейка
6
Out[7] # конкретная ячейка
[1, 2, 3]
pwd # unix-dos-команды
u'C:\\tmp\\notebooks'
i, j = 1, 2
print("%i" % (i * j))
print("%i" % i * j) # % и * имеют один приоритет! Поэтому ответ '1'*2
2 11
i = j = k = 1 # одновременное присвоение
i -= 2 # аналоги +=
j *= 2
k /=2
print (i, j, k)
s = 'one'
s += 'two'
s *=3
print (s)
-1 2 0.5 onetwoonetwoonetwo
from модуль import *
# лучше так не делать!
# помощь
help(len)
Help on built-in function len in module builtins: len(obj, /) Return the number of items in a container.
# помощь
print (len.__doc__)
Return the number of items in a container.
s1 = "abcde"
s2 = "abcde"
s3 = "ab" + "cd" + "e"
print ("hash:", hash(s1), hash(s2), hash(s3))
print ("hash:", id(s1), id(s2), id(s3))
# а раньше id(s1) = id(s2) != id(s3)
hash: 6612913437847469369 6612913437847469369 6612913437847469369 hash: 139905333472760 139905333472760 139905333472760
#--
x = None # ничего
if x is None: # или x is not None
pass # ничего не делать
else:
print (x)
# is - используется только для None
# интерпретатор кэширует числа от -5 до 256 - для каждого числа есть лишь один объект
print (int("-5") is -5)
print (int("-6") is -6)
True False
a = 257
b = 257
print (a is b)
def f(): # умный интерпретатор сделает это одним объектом
a = 257
b = 257
print (a is b)
f()
False True
print (1000+0 is 1000+0)
print (1000 is 1000)
False True
# байткод
import dis
def myf(x):
return(x+1,x-1)
dis.dis(myf)
5 0 LOAD_FAST 0 (x) 3 LOAD_CONST 1 (1) 6 BINARY_ADD 7 LOAD_FAST 0 (x) 10 LOAD_CONST 1 (1) 13 BINARY_SUBTRACT 14 BUILD_TUPLE 2 17 RETURN_VALUE
%timeit x, y = 1, 2
# второй вариант быстрее
%timeit x = 1; y = 2
#timeit - на время измерений отключается сборщик мусора
17 ns ± 1.68 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) 12.9 ns ± 0.0339 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
x = 10
%timeit "x = x * 2"
# второй вариант чуть быстрее
%timeit "x = x + x"
6.46 ns ± 0.213 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) 6.79 ns ± 0.967 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
x = 10
%timeit "x = x ** 2"
# второй вариант чуть быстрее
%timeit "x = x * x"
6.45 ns ± 0.162 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) 6.39 ns ± 0.0943 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
x = 10
%timeit "a = x > 1.0"
# второй вариант чуть быстрее - не будет приведения типов
x = 10.
%timeit "a = x > 1.0"
6.94 ns ± 0.104 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) 6.37 ns ± 0.015 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
x = "one"
y = "two"
print (x + '+' + y)
print ("".join((x, '+', y)))
print ("%s+%s" % (x, y))
print ("{0}+{1}".format(x, y))
print (f"{x}+{y}")
%timeit x + '+' + y
%timeit "".join((x, '+', y))
%timeit "%s+%s" % (x, y)
%timeit "{0}+{1}".format(x, y)
%timeit f"{x}+{y}"
one+two one+two one+two one+two one+two 104 ns ± 23.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 134 ns ± 0.809 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) 156 ns ± 0.279 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) 106 ns ± 0.202 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) 9.78 ns ± 1.38 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
def f():
l = []
for i in range(10000):
l.append(i) # будет искать этот метод... (в хеш-таблице...)
return (l)
%timeit f()
# этот вариант быстрее!
def g():
l = []
li = l.append # сразу сообщим функцию - чтобы не искать в цикле
for i in range(10000):
li(i)
return (l)
%timeit g()
1000 loops, best of 3: 675 µs per loop 1000 loops, best of 3: 440 µs per loop
# неожиданное поведение... не увлекайтесь функциональным программированием
l = [lambda: x for x in "abcdefg"]
for r in l:
print (r())
# объяснение - особенности лямбда-функций
print (id(lambda: 1) == id(lambda: 2))
g g g g g g g True
import this
The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!
стилистические рекомендации по оформлению кода
x = -0.1
b = (x / 2) + 1
lst = ['one','two'
'three'
]
x, y = True, False
print (x and y)
print (x or y)
print (not y)
print (x and y)
print ((1 == 2) | (2 == 2))
print ((1 < 2) & (2 != 2))
False True True False True False
# приведение типов
print (bool('True') == bool(1))
True
# проверка списка на пустоту
lst = []
if not lst:
print ('empty-1')
lst = [False]
if not lst:
print ('empty-2')
lst = [True]
if not lst:
print ('empty-3')
empty-1
print(1 < 2 < 3 < 4)
print(1 < 3 < 3 < 4)
x = 4
if 3 < x < 5: # можно без скобок
print ('четыре')
# или
if 3 < x and x < 5:
print ('четыре')
True False четыре четыре
лучше не применять
a = input()
print (a*3) # будет строкой!
01 010101
# исключения
class MyError(Exception): # Exception - класс, от которого должны наследоваться все исключения
pass
try:
a = 1
b = 2
print (a / b)
raise (MyError) # поднимаем исключение
# else: не работает! и в Python3
# print ("Не было исключения")
except ZeroDivisionError: # принимаем исключение
print ("Деление на 0")
except KeyboardInterrupt:
print ("Прерывание с клавиатуры")
except (MyError):
print ("Моя ошибка")
except:
print ("Ошибка")
finally:
print ("Последние действия")
# тут можно, например, закрыть файл
0.5 Моя ошибка Последние действия
# Обработка любого исключения
import traceback
try:
1 / 0
except Exception as e:
print (e.args) # переданные аргументы
traceback.print_tb(e.__traceback__) # информация о стеке вызовов на момент исключения
# pass
print ('выполнение программы продолжается')
('division by zero',) выполнение программы продолжается
File "<ipython-input-9-d79c6f494502>", line 5, in <module> 1 / 0
# менеджер контекста
with resource_1() as r1, \
resource_2() as r2:
do_smth(r1, r2)
# в случае с файлами - не надо явно закрывать
# можно самому написать менеджер контекста
class m_c:
def __init__(self):
print ('init')
# возвращает None
def __enter__(self):
# тут можно, например, открыть файл
print ('enter')
# возвращаемое значение доступно по имени with ... as NAME:
return ('m_c-name')
def __exit__(self, *exc_info):
# вызывается в конце
# аргументы:
# - тип исключения
# - исключение
# - объект типа traceback
print ('exit')
with m_c() as name:
print ('working... with ' + name)
init enter working... with m_c-name exit
print (2 ** 1000)
# print (2L ** 1000) # не работает
# в третьем int имеет произвольную точность!
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376
# type(3)
type(2 ** 1000)
int
print (type(1))
print (type(1.0))
print (type(int(1.0))) # преобразование типов
print (type(-1.2+3.7j + 5))
<class 'int'> <class 'float'> <class 'int'> <class 'complex'>
имя = 10 # не рекомендуется
print(имя)
del имя # удаление объекта
# print (имя) - ошибка
10
print(10 // 3) # Python 3 - деление нацело
print(10 % 3) # остаток
from __future__ import division
print(10 / 3) # в Python 2 - нацело
3 1 3.3333333333333335
нет понятия символ (-- это одноэлементная строка)
в Python3 строка - последовательность символов Юникод
s = u'\u043f\u0440\u0438\u0432\u0435\u0442'
print(s)
s2 = """раз
два\nтри"""
print(s2)
s2
привет раз два три
'раз\nдва\nтри'
s = '\u043f\u0440\u0438\u0432\u0435\u0442'
print(s)
s
привет
'привет'
# операции
print ('A' + 'B') # конкатенация
print ('A' * 3) # повтор
print ('A%s%i' % ('B', 7)) # форматирование
AB AAA AB7
# задание одной и той же строки
s1 = "string"
s2 = 'string'
s3 = """string"""
s4 = 'st' 'rin' 'g' # будет склейка (аналогично операции +)
s5 = 'st' + 'rin' + 'g'
print (s1, s2, s3, s4, s5)
string string string string string
print (s1, s2, s3, s4, s1 == s2, s1 == s3, s1 == s4)
s4 = '\1\2'
s5= r'\1\2'
print (s4, '--', s5)
s5
string string string string True True True -- \1\2
'\\1\\2'
# форматирование
print('%010.3g' % (1 / 3))
print('%+10.4g' % (1 / 3))
print('%-10.5g' % (1 / 3))
print('%-10.5e' % (1 / 3))
000000.333 +0.3333 0.33333 3.33333e-01
# другой способ форматирования (более гибкий)
print ("a={:0.4e}, b={:+2.3f}, c={}".format(1 / 3, 1 / 7, 1 / 11))
print ("a={:>5s}, b={:%}, c={:06.2f}".format('one', 1 / 7, 1 / 11))
a=3.3333e-01, b=+0.143, c=0.09090909090909091 a= one, b=14.285714%, c=000.09
# вывод в блоке одной длины
print ("{:~^10}".format("a"))
print ("{:~^10}".format("aaa"))
print ("{:~^10}".format("aaaaa"))
~~~~a~~~~~ ~~~aaa~~~~ ~~aaaaa~~~
# разные форматы чисел
print ("int - {0:d}, hex - {0:x}, bin - {0:b}".format(12))
# можно именовать аргументы и использовать индексы
print ("x={0[0]}, y={0[1]}, z={z}".format([1,2], 3, z=4))
int - 12, hex - c, bin - 1100 x=1, y=2, z=4
# индексация
s = 'string'
print (s[0], s[:3], s[-2:])
s str ng
s = 'one,two,three'
s2 = s.split(',') # расщепление в список
print (s, s2)
print (";".join(s2)) # объединение через разделитель
one,two,three ['one', 'two', 'three'] one;two;three
# методы работы со строками
s = 'one,one'
print (s.count('on')) # подсчёт вхождения подстроки
print (s.find('on')) # поиск подстроки (есть ещё index - с исключениями)
print (s.rfind('on')) # поиск последней подстроки (последнее вхождение)
print (s.isalpha()) # только буквы
print (s.islower()) # только строчные / isupper / istitle / isspace
print (s.isdigit()) # число
print (s.isalnum()) # только буквы и цифры
print ("+".join([s,'two','three'])) # соединение через разделитель
print (s.replace('on','off')) # замена подстрок
print (s.translate({ord('o'): 'a', ord('n'): 'b'})) # Python3 множественная замена символов
print (' 12 '.strip()) # удаление первых и последних пробелов, ещё - lstrip, rstrip
print (s.upper()) # в верхний регистр
print ('file.txt'.endswith('.exe')) # startwith
2 0 4 False True False False one,one+two+three offe,offe abe,abe 12 ONE,ONE False
print(s.capitalize()) # первую букву в верхний регистр, ост. - в нижний
print (s.rpartition(',')) # расщепление по разделителю
One,one ('one', ',', 'one')
# выравнивание в блоке фиксированной длины
s = 'my string'
print (s.ljust(13, ' '))
print (s.center(13, '-'))
print (s.rjust(13)) # пробел можно не указывать
my string --my string-- my string
# вхождение подстроки (проверка, а не поиск)
s = "one,two,three"
print ('on' in s)
print ('ab' not in s)
print ('o,' in s)
True True True
x = b"\00\01\10"
x
b'\x00\x01\x08'
s = "строка"
s.encode("utf-8")
b'\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0'
x = b'\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0'
x.decode("utf-8")
'строка'
неизменяемый тип
a = 1
b = 2
a, b = b, a
print (a, b)
2 1
a, b, c = 1, 2, 3 # это tuple (см. дальше)
print (a, b, c)
(x, y), (z, t) = [1, 2], [3, 4]
print (x, y, z, t)
x, (x, x) = 1, (2, 3) # сработает последнее присваивание
print (x)
1 2 3 1 2 3 4 3
a = 1, 2, 3
# a = (1, 2, 3)
# a = tuple((1, 2, 3))
for x in a:
print (x)
1 2 3
# пустой кортеж
a = () # раньше (,)
a
()
a = (None, True, 2, "-1") # м.б. разные типы
# in - для всех контейнеров
print (2 in a)
print (2.0 in a)
print (-1 in a)
True True False
x = (2,) # одноэлементный кортеж
print (x)
[y] = x # элемент этого кортежа
y
(2,)
2
person = ("Иван", "Иванов", 22, "мая", 2001)
NAME, BIRTHDAY = slice(2), slice(2, None)
print (person[NAME], person[BIRTHDAY]) # вместо :2 и 2:
('Иван', 'Иванов') (22, 'мая', 2001)
x = (1, 2, 3)
print(x[::-1])
print(tuple(reversed(x)))
(3, 2, 1) (3, 2, 1)
x = (1, 2)
y = (3, 4)
x + y # конкатенация
(1, 2, 3, 4)
# сравнение (лексикографический порядок)
print ((1, 2) < (1, 3))
print ((1, 2) < (1, 2))
print ((1, 2) < (1, 2, 1))
print ((2,) < (1, 3))
True False True False
# именованный кортеж
from collections import namedtuple
Person = namedtuple("Person", ["name", "age"])
p = Person("Иван", age=16)
p
Person(name='Иван', age=16)
print ([1, 2, 3]) # список
print ([x for x in range(3)])
# преобразование типов
print (list(range(3))) # из генератора
print (list(u'строка')) # из строки
print (list({1, 3, 1, 2})) # из множества
print (list((1, 1, 2))) # из кортежа - меньше скобок нельзя
[1, 2, 3] [0, 1, 2] [0, 1, 2] ['с', 'т', 'р', 'о', 'к', 'а'] [1, 2, 3] [1, 1, 2]
s = [1, 2, 3] # это список
print (len(s)) # длина списка!
print (2 in s) # принадлежность списку
print (s + s) # создаётся новый список!
print (s * 2) # "удоение"
print (s[:2]) # "срез"
print (s[0:3:2])
print (max(s)) # максимальный элемент
3 True [1, 2, 3, 1, 2, 3] [1, 2, 3, 1, 2, 3] [1, 2] [1, 3] 3
del s[1]
s[0] = 100
s
[100, 3]
s = [4] * 3 # [4, 4, 4]
s.remove(4) # удаление первого вхождения элемента
print(s)
s.append(2) # добавление элемента
print(s)
s.extend([3, 3]) # добавление последовательности
print(s)
print(s.count(4)) # сколько элементов
print(s.index(2)) # индекс элемента (первое вхождение), если не входит - исключение ValueError
s.reverse() # инвертирование
print(s, s[::-1])
s.sort() # сортировка
print(s)
print (s.pop(1)) # возвращает с удалением элемент (по индексу) pop() - последний
print(s)
s.insert(0, 1) # вставка элемента
print(s)
s.insert(-1, 5) # вставка элемента
print(s)
s[-4:] = [0]*4 # вставка элементов
print(s)
# вставка элемента
del s[-3:] # удаление элементов
print(s)
[4, 4] [4, 4, 2] [4, 4, 2, 3, 3] 2 2 [3, 3, 2, 4, 4] [4, 4, 2, 3, 3] [2, 3, 3, 4, 4] 3 [2, 3, 4, 4] [1, 2, 3, 4, 4] [1, 2, 3, 4, 5, 4] [1, 2, 0, 0, 0, 0] [1, 2, 0]
# хождение по списку
y = []
for x in [1, 2, 3]:
y.append(x**x)
print (y)
[1, 4, 27]
# при *n не происходит копирования списка!
x = [[0]]*2 # делаем список
print(x)
x[0][0] = 1 # меняем один элемент ... а поменялись оба
print(x)
x = x + x
x[0][0] = 2 # такой же эффект
print(x)
[[0], [0]] [[1], [1]] [[2], [2], [2], [2]]
from copy import copy
x = [copy([0]) for i in range(2)]
x[0][0] = 1
x
[[1], [0]]
from copy import copy
x = [[0] for i in range(2)]
x[0][0] = 1
x
[[1], [0]]
# двусторонняя очередь
from collections import deque
# добавление / удаление - константное время
q = deque([1,2,3,4])
q.appendleft(0)
q.appendleft(-1)
q.append(5)
print (q.popleft())
print (q)
-1 deque([0, 1, 2, 3, 4, 5])
s = [0, 1, 2, 3, 4, 5]
print(s[2]) # третий! элемент
print(s[:2]) # первые два элемента
print(s[2:]) # после второго
print(s[:-2]) # без двух элементов
print(s[-2:]) # последние два
print(s[0:4:2]) # от : до : шаг
print(s[::3]) # все через шаг
print(s[::-1]) # в обратном порядке
2 [0, 1] [2, 3, 4, 5] [0, 1, 2, 3] [4, 5] [0, 2] [0, 3] [5, 4, 3, 2, 1, 0]
# нетривиально!
s = [0, 1, 2, 3, 4, 5]
s[0:0] = [-2, -1]
print(s)
s[-1:0] = [0.1, 0.2]
s
[-2, -1, 0, 1, 2, 3, 4, 5]
[-2, -1, 0, 1, 2, 3, 4, 0.1, 0.2, 5]
s = list(range(5))
del s[1:3] # удаление среза
s
[0, 3, 4]
# кстати
print ([0,0] * 3)
print ([[0,0]] * 3)
[0, 0, 0, 0, 0, 0] [[0, 0], [0, 0], [0, 0]]
# вложенные списки
a = [1, 2, 3]
b = [4, 5, 6]
lst = [1, [a, b]]
lst[1][0][2]
3
# контейнер для разнородных элементов
s = [1, 'string', [1,2,3], True]
s[1]
'string'
# исчерпание списка в цикле
s = list('list')
while s:
print (s.pop())
t s i l
print([1, 2] < [1, 3])
print([1, 2] < [1, 2, 1])
print([2] < [1, 3])
True True False
person = ["Иван", "Иванов", 22, "мая", 2001]
NAME, BIRTHDAY = slice(2), slice(2, None)
print(person[NAME], person[BIRTHDAY]) # вместо :2 и 2:
['Иван', 'Иванов'] [22, 'мая', 2001]
Для хранения (key, value) Порядок не важен
dct = {'a': 1, 'b': 2} # словарь
print (dct)
dct = dict(a=1, b=2) # другой способ
print (dct)
dct = dict(dct, a=3, d=2) # добавление к словарю
print (dct)
dct = dict([('a', 1), ('b', 2)]) # преобразование из списка
print (dct)
print(dct.keys()) # ключи
print(dct.values()) # значения
print(dct.items()) # пары (ключ, значение)
print (dct['a']) # обращение по ключу (если нет - исключение KeyError)
print (dct.get('c', 0)) # обращение по ключу со значением по умолчанию (когда ключ не найден)
print ('a' in dct) # есть ли ключ
del dct['a'] # удаление по ключу
print (dct)
{'a': 1, 'b': 2} {'a': 1, 'b': 2} {'a': 3, 'b': 2, 'd': 2} {'a': 1, 'b': 2} dict_keys(['a', 'b']) dict_values([1, 2]) dict_items([('a', 1), ('b', 2)]) 1 0 True {'b': 2}
d = dict(a=True, b="02", c=[1, 2, 3]) # можно так создавать
print(d)
d.setdefault('c', 100.0) # попытка добавить значение, если нет
d.setdefault('d', 100.0)
print(d)
d.update(e=1, f=2) # дабавить ещё значений
print(d)
d.update([('e', 3), ('f', 4)]) # дабавить ещё значений - старые значения заменятся на новые
print ('c = ', d.pop('c')) # возвращаем значение и удаляем его из словаря
print (d)
d.clear() # удалить из словаря все значения
{'a': True, 'b': '02', 'c': [1, 2, 3]} {'a': True, 'b': '02', 'c': [1, 2, 3], 'd': 100.0} {'a': True, 'b': '02', 'c': [1, 2, 3], 'd': 100.0, 'e': 1, 'f': 2} c = [1, 2, 3] {'a': True, 'b': '02', 'd': 100.0, 'e': 3, 'f': 4}
dict.fromkeys("abc", True) # словарь со значением по умолчанию
{'a': True, 'b': True, 'c': True}
dct = {'a': 1, 'b': 2}
dct[0] = 5
for key, val in dct.items(): # цикл по словарю
print (key, val)
for key in dct.keys(): # цикл по ключам словаря
print (key, dct[key])
for val in dct.values(): # цикл по значениям словаря
print (val)
print ('длина словаря = %i' % len(dct)) # количество пар в словаре
a 1 b 2 0 5 a 1 b 2 0 5 1 2 5 длина словаря = 3
dct = {'a':1, 'b':2}
dct2 = {'b':3, 'c':4}
dct.update(dct2) # пополнение словаря
dct
{'a': 1, 'b': 3, 'c': 4}
# но если нужно объединить 2 словаря не портя оба...
dct = {'a': 1, 'b': 2}
dct2 = {'b': 3, 'c': 4}
union = {**dct, **dct2} # Python3-способ
print(union, dct, dct2)
union = dct.copy() # Python2-способ
union.update(dct2)
print(union, dct, dct2)
union = dict(dct, **dct2)
print(union, dct, dct2)
{'c': 4, 'a': 1, 'b': 3} {'b': 2, 'a': 1} {'c': 4, 'b': 3} {'c': 4, 'a': 1, 'b': 3} {'b': 2, 'a': 1} {'c': 4, 'b': 3} {'c': 4, 'a': 1, 'b': 3} {'b': 2, 'a': 1} {'c': 4, 'b': 3}
# преобразование типов
a = ['a', 'b', 'c']
b = [1, 2, 3]
dict(zip(a, b))
{'a': 1, 'b': 2, 'c': 3}
# вывод словаря с упорядочиванием по значениям
import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))
sorted_x
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
d = {'a': 1, 'b': 2}
if 'c' not in d: # так проверям на не-вхождение
d['c'] = 3
d
{'a': 1, 'b': 2, 'c': 3}
# одно из применений словарей - имитация switch
def first():
print ('one')
def second():
print ('two')
def third():
print ('three')
x = 2
# плохой способ
if (x == 1):
first()
elif (x == 2):
second()
elif (x == 3):
third()
# Python-style способ
dct = {1: first, 2: second, 3: third}
dct[x]()
from collections import OrderedDict
# словарь, в котором ключи упорядочены по времени добавления
d = OrderedDict([("a", 1), ("b", 2)])
d["c"] = 3
print (d)
# словарь-счётчик
from collections import Counter
c = Counter(["a", "a", "b", "b", "c"])
c["a"] += 1
print (c, c.most_common(2))
# можно работать со счётчиками как с мультимножествами
c2 = Counter(["a", "a", "c"])
print (c + c2, c - c2, c & c2, c | c2)
OrderedDict([('a', 1), ('b', 2), ('c', 3)]) (Counter({'a': 3, 'b': 2, 'c': 1}), [('a', 3), ('b', 2)]) (Counter({'a': 5, 'c': 2, 'b': 2}), Counter({'b': 2, 'a': 1}), Counter({'a': 2, 'c': 1}), Counter({'a': 3, 'b': 2, 'c': 1}))
только хэшируемые объекты могут быть элементами множества (числа, строки)
есть ещё frozenset - неизменяемое множество
s = {'key1', 'key1', 'key2'}
print (s)
print ('key2' in s)
s = s.union({1,2})
print (s)
print (s.difference({1, 3, 4}))
s.add(121) # добавить 1 элемент
print (s)
s.update([122, 123, 121]) # добавляем несколько элементов
print (s)
s.remove('key1') # если нет - исключение, есть ещё discard (без исключений)
print (s)
{'key2', 'key1'} True {1, 2, 'key2', 'key1'} {2, 'key2', 'key1'} {1, 2, 'key2', 'key1', 121} {1, 2, 'key2', 'key1', 121, 122, 123} {1, 2, 'key2', 121, 122, 123}
# преобразование типов
x = [1, 2, 2]
set(x)
{1, 2}
a = {1, 2, 3}
b = {2, 3, 4}
# пересечение
print (a & b)
print (a.intersection(b)) # 2-й способ
# объединение
print (a | b)
print (a.union(b)) # 2-й способ
# разность
print (a - b)
print (a.difference(b)) # 2-й способ
# вложения
print (a <= b)
print (a < b)
print (a > b)
{2, 3} {2, 3} {1, 2, 3, 4} {1, 2, 3, 4} {1} {1} False False False
x, y, z = {1, 2}, {3}, {1, 3, 4}
print (set.union(x, y, z))
print (set.difference(x, y, z)) # x - y - z
{1, 2, 3, 4} {2}
f1 = open("file1.txt", "r")
f2 = open("file2.txt", "w", encoding="cp1251")
for line in f1.readlines():
f2.write(line)
f2.close()
f1.close()
f = open("file.txt", "r", 1)
for line in f:
# ...
f.close()
# чтобы не забывать закрывать файлы
with open('tmp.txt') as fin:
for line in fin:
# ...
# файлоподобные объекты
import urllib
f1 = urllib.urlopen("http://python.onego.ru")
модуль - один файл с расширением *.py (сейчас уже и zip-архив)
задаёт своё пространство имён
пакет - директория, в которой есть файл init.py (просто для организации кода)
Может содержать поддериктории. Пользователю не так важно, с чем работать
pak1 |-- init.py |--pak12 | |-- init.py | |-- f.py |--h.py
from pak1.pak12 import f
import datetime # импортируем модуль
d = datetime.date(2004, 11, 20) # появляется объект с соответствующим названием
print (d)
print (datetime.__name__) # имя
print (datetime.__doc__) # описание
print (datetime.__file__) # файл
import datetime as dt # сокращение имени модуля
print (dt.date(2004, 11, 20))
from datetime import date as dt # импортирование конкретной функции
print (dt(2004, 11, 20))
# from datetime import * # лучше не использовать
2004-11-20 datetime Fast implementation of the datetime type. C:\Anaconda3\lib\datetime.py 2004-11-20 2004-11-20
import sys
# здесь питон ищет модули
sys.path
# или
from sys import path
path
['', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\python35.zip', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\DLLs', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\lib', 'C:\\Users\\Александр Дьяконов\\Anaconda3', 'c:\\users\\александр дьяконов\\anaconda3\\lib\\site-packages\\setuptools-20.7.0-py3.5.egg', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\lib\\site-packages', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\lib\\site-packages\\Sphinx-1.3.1-py3.5.egg', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\lib\\site-packages\\cryptography-1.0.2-py3.5-win-amd64.egg', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\lib\\site-packages\\win32', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\lib\\site-packages\\Pythonwin', 'C:\\Users\\Александр Дьяконов\\Anaconda3\\lib\\site-packages\\IPython\\extensions', 'C:\\Users\\Александр Дьяконов\\.ipython']
print (sys.platform)
print (sys.version)
win32 3.5.1 |Anaconda 2.4.0 (64-bit)| (default, Feb 16 2016, 09:49:46) [MSC v.1900 64 bit (AMD64)]
# если модуль пытаются выполнить, то у переменной __name__ специальное значение
if __name__ =="__main__":
print ("...")
...
# при повторном импорте нет перезагруки модуля
# (это, в том числе, борьба с циклическими импортами)
reload(module) # перезегрузка модуля
# в 3м питоне по-другому! - importlib.reload
# import pre as re
# digits = re.compile("\d+")
# digits
#--
for i, c in enumerate("ABC"):
print (i, c, ord(c))
0 A 65 1 B 66 2 C 67
#--
def myf(a=1, b=2):
c = 3
print (vars()) # локальные имена
print (locals()) # локальные имена
d = 1
# print (globals()) # глобальные имена
myf()
{'c': 3, 'b': 2, 'a': 1} {'c': 3, 'b': 2, 'a': 1}
#--
a = 1
b = 2
c = eval('a + b') # вычисление выражений
# eval('c = a + b') # нельзя так
c
3
class A:
pass
a = A()
a.attr = 1 # setattr(a, 'attr', 1)
try:
# if hasattr(a, 'attr'):
print (a.attr) # getattr(a, 'attr')
except:
print (None)
del a.attr # delattr(a, 'attr')
# классы обычные объекты - их можно модифицировать
A.method = lambda x: "привет"
a.method()
1
'привет'
# как ещё можно задавать класс
# можно использовать для генерации во время выполнения программы
def pr(self, txt):
print('text:', txt)
MyList = type('MyList', (list,), dict(a=1,pr=pr))
ml = MyList()
ml.append('one')
print (ml)
ml.pr('two')
['one'] text: two
MyList.__class__.__class__
type
# УБРАТЬ???
# все имена - ссылки
a = 1000
b = a
a = 2000
print (a, b)
print (id(a), id(b))
2000 1000 74240048 63401840
# УБРАТЬ???
# но не во всех случаях об этом надо заботиться
s = [1, 2, 3]
a = s[1]
s[1] = 10
print (a, s)
a = 20
print(a, s)
2 [1, 10, 3] 20 [1, 10, 3]
from copy import copy
x = [copy([0]) for i in range(2)]
x[0][0] = 1
x
[[1], [0]]
# все имена - ссылки на объекты
a = [1, 2]
b = [a] * 3 # состоит из идентичных (!) объектов
print (b)
b[0][0] = 0
print (b)
print (id(b[0]), id(b[1]), id(b[2]))
from copy import copy
a = [1, 2]
b = [copy(a) for i in range(3)] # состоит из разных объектов
print (b)
b[0][0] = 0
print (b)
print (id(b[0]), id(b[1]), id(b[2]))
[[1, 2], [1, 2], [1, 2]] [[0, 2], [1, 2], [1, 2]] 74362568 74359240 74359880
# copy - не помогает...
a = 1
b = [a, a]
c = [b, b]
c2 = copy(c)
c2[0][0] = 0
print (c)
print (c2)
[[0, 1], [0, 1]] [[0, 1], [0, 1]]
from copy import deepcopy
# deepcopy - не помогает... (частично ;)
a = 1
b = [a, a]
c = [b, b]
c2 = deepcopy(c)
c2[0][0] = 0
print (c)
print (c2)
[[1, 1], [1, 1]] [[0, 1], [0, 1]]
x = [[0]]*2
id(x[0]), id(x[1])
(72882632, 72882632)
(принимают другие функции в качестве аргументов или возвращают другие функции, их можно присваивать и хранить)
(нет цикла – он реализован через рекурсию) • Обработка списков (например, print(len([1+1, 1/0])))
(чистые функции – зависят только от своих параметров и возвращают только свой результат)
(в идеале, программа - одно выражение с сопутствующими определениями)
from operator import add, mul
print (add(2, mul(3, 4))) # операции это тоже функции
14
# определение функции
def inc(n, delta=1): # необязательный аргумент со значением по умолчанию
return n+delta
myadd = inc # эта же функция (просто другте имя)
print (inc(20))
print (myadd(30))
21 31
# если функция ничего не возвращает, то она возвращает None
def f():
pass
def g():
"""
помощь
"""
def h():
# можно объявлять функцию внутри функции
print ('h')
10
print (f(), g())
print g.__doc__
help(g)
(None, None) помощь Help on function g in module __main__: g() помощь
# именованные аргументы
def f(x=1, y=2):
print ('x=%g, y=%g' % (x, y))
f(3, 4)
f(3)
f(y=10, x=20)
f(y=0)
x=3, y=4 x=3, y=2 x=20, y=10 x=1, y=0
# ???
def wrap(text, width=70, **kwargs):
from textwrap import TextWrapper
# kwargs - словарь с именами и значениями аргументов
w = TextWrapper(width=width, **kwargs)
return w.wrap(text)
print (wrap("my long text ...", width=4))
# wrap('abc', 70, 'def', 2)
['my', 'long', 'text', '...']
# сколько угодно аргументов - "упаковка аргументов"
def max_min(*args):
# args - список аргументов в порядке их указания при вызове
return max(args), min(args)
print (max_min(1, 2, 3, 4, 5))
print (max_min(*[4, 0, 3]))
print (max_min(*(1, 7, 3)))
print (max_min(*{6, 2, 4}))
# возвратить можно только одно значение, но оно м.б. кортежом
(5, 1) (4, 0) (7, 1) (6, 2)
# "бесполезная упаковка"
def f(**x):
print (x)
f(**{'a': 3, 'b': 7, 'c': 1})
def g(x):
print (x)
g({'a': 3, 'b': 7, 'c': 1})
{'c': 1, 'a': 3, 'b': 7} {'c': 1, 'a': 3, 'b': 7}
# ещё про распаковку
# этот код работает лишь в Python3!!!
first, *other = range(3)
print (first, other)
print ('for')
for a, *b in [range(3), range(2)]:
print (a,b)
[*range(5), 6]
0 [1, 2] for 0 [1, 2] 0 [1]
[0, 1, 2, 3, 4, 6]
# распаковка при инициализации контейнера
# в Python3
d = {'a':1, 'b':2}
d = {**d, 'a':3}
d
{'a': 3, 'b': 2}
# аргументы функции
# фиксированные (здесь - 1 обязательно)
# произвольные
# любые
def swiss_knife(arg1, *args, **kwargs):
print ('аргументы:')
print (arg1)
print (args)
print (kwargs)
print ('подробнее о **kwargs:')
for k, v in kwargs.items():
print (k,'=',v)
return None
swiss_knife(1, 2, [3, 4], b=-1, a=0)
# swiss_knife(1, 2, b=-1, a=0, [3, 4]) # так нельзя!
swiss_knife(1)
аргументы: 1 (2, [3, 4]) {'b': -1, 'a': 0} подробнее о **kwargs: b = -1 a = 0 аргументы: 1 () {} подробнее о **kwargs:
# передача нескольких аргументов
d = {'a':1, 'b':2}
s = [1, 2, 3]
swiss_knife(d)
swiss_knife(*d)
swiss_knife(s)
swiss_knife(*s) # такая передача аргументов!
аргументы: {'b': 2, 'a': 1} () {} аргументы: b ('a',) {} аргументы: [1, 2, 3] () {} аргументы: 1 (2, 3) {}
# лямбда-функции (анонимные)
func = lambda x, y: x + y
print (func(1, 2))
3
могут быть
# функции первого класса
def create_adder(x):
def adder(y): # определяем функцию внутри
return x + y
return adder # её же возвращаем
add_10 = create_adder(10)
print (add_10(3))
f = add_10 # та же функция
del add_10 # не удаляет саму функцию
print(f(0))
13 10
# интересное наблюдение
f.__name__
'adder'
# lst - хранится...
def mylist(val, lst=[]):
lst.append(val)
return lst
print (mylist(1))
print (mylist(2))
print (mylist(3))
[1] [1, 2] [1, 2, 3]
# lst не сохраняется!... часто очень полезно
def mylist(val, lst=None):
lst = lst or []
lst.append(val)
return lst
print (mylist(1))
print (mylist(2))
print (mylist(3))
[1] [2] [3]
# apply, reduce - не поддерживается больше
from functools import reduce
print (reduce(lambda x, y: x * y, [1, 2, 3, 4])) # ((1*2)*3)*4
print (reduce(lambda x, y: '(' + str(x) + '*' + str(y) + ')', [1, 2, 3, 4]))
# print (reduce(merge, [[1,2], range(2), 'abc'])) # Python 3?
24 (((1*2)*3)*4)
print (range(3)) # в 3м питоне - не список
print (list(range(3)))
for i in range(3):
print (i)
range(0, 3) [0, 1, 2] 0 1 2
# map
l1 = [1, 2, 3, 4]
l2 = [0, -1, +1, +2] # если разной длины - то по длине наименьшей
print (list(map(lambda x, y: x + y, l1, l2)))
print (list(map(max, l1, l2)))
[1, 1, 4, 6] [1, 2, 3, 4]
# map
l = [1, 2, 3]
print (list(map(lambda x: x * x, l)))
print (list(map(lambda x: x * x, range(3))))
[1, 4, 9] [0, 1, 4]
# filter
print (list(filter(lambda x: x.isalpha(), 'Привет, мир!'))) ### перезапустить;)
list(filter(lambda x: x % 2, range(10)))
['П', 'р', 'и', 'в', 'е', 'т', 'м', 'и', 'р']
[1, 3, 5, 7, 9]
# так надо было делать в Python 2.x - from types import IntType - ТАК ТОЖЕ РАБОТАЕТ
lst = [12, 1.2, '12', 1, 2]
list(filter(lambda x: type(x) is int, lst))
[12, 1, 2]
# zip
# - сюда пример
x = range(5)
y = 'abcde'
z = [0,1,0,1,0]
list(zip(x,y,z)) # list - python3
[(0, 'a', 0), (1, 'b', 1), (2, 'c', 0), (3, 'd', 1), (4, 'e', 0)]
# сформировать перечень пар соседних букв
x = 'Привет!'
# можно подавать разные по длине аргументы
list(zip(x, x[1:]))
[('П', 'р'), ('р', 'и'), ('и', 'в'), ('в', 'е'), ('е', 'т'), ('т', '!')]
# глобальные переменные
globvar = 0
def set_globvar_to_one():
global globvar # глобальная - без этого нельзя сделать, например, globvar+=1
globvar = 1 # если не объявить глобальной - тут будет локальная
def print_globvar():
print (globvar) # не надо объявлять
set_globvar_to_one()
print_globvar()
1
# области видимости
# nonlocal ??? - для охвата "объемлющей области"
a = 0
def f():
nonlocal a
#global a
a+=1
return (a)
print (f(), a)
File "<ipython-input-88-30351f0d325b>", line 5 nonlocal a ^ SyntaxError: no binding for nonlocal 'a' found
def f():
min = 1 # локальная переменная
max = 10
def g():
min = 2 # другая локальная переменная
# print (min, max) # max берём из f() - уберите комментарий;)
print ('locals = ' + str(locals()))
g()
# print (min)
print ('locals = ' + str(locals()))
g()
max = 0 # глобальная переменная
f()
min, max # встроенная функция
locals = {'min': 2} locals = {'max': 10, 'g': <function g at 0x0000000003C507B8>, 'min': 1} locals = {'min': 2}
(<function min>, 0)
# списковые включения
[(i, j) for i in range(3) for j in range (5) if i > j]
[(1, 0), (2, 0), (2, 1)]
[x**2 for x in range(5)]
[0, 1, 4, 9, 16]
# zip
print (list(zip(range(5), 'abcde')))
print (dict(zip(range(5), 'abcde')))
print (['%s=%s' % (x,y) for y, x in zip(range(5), 'abcde')])
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')] {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'} ['a=0', 'b=1', 'c=2', 'd=3', 'e=4']
# Set Comprehensions
lst = [10, 5, 100, 3, 20, 10, 3, 20]
{x for x in lst if 10*round(x / 10) == x}
{10, 20, 100}
# Dictionary Comprehensions
{x:y for y, x in zip(range(5), 'abcde') if y<3}
{'a': 0, 'b': 1, 'c': 2}
for работает с любой последовательностью (есть next до исключения StopIteration)
# что такое итератор
it = iter([1, 2, 3, 4, 5])
print (next(it))
print (next(it))
print ([x for x in it])
# print (next(it)) # исключение
1 2 [3, 4, 5]
# КАК ЕСТЬ
def forit(mystate=[]):
if len(mystate) < 3:
mystate.append(" ")
return " "
it2 = iter(forit, None) # если не возвращает значения явно, то None
print ([x for x in it2])
[' ', ' ', ' ']
print (list(x for x in enumerate("abcd")))
for i, j in enumerate("abcd"):
print (i, j)
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')] 0 a 1 b 2 c 3 d
dict(enumerate(['test', 'train', 'val']))
{0: 'test', 1: 'train', 2: 'val'}
for i in sorted('mamba'): # правда, это список
print (i)
a a b m m
# модуль itertools
from itertools import chain
it1 = iter([1, 2, 3])
it2 = iter([4, 5])
a = []
for i in chain(it1, it2): # соединение 2х итераторов
a.append(i)
print (a)
from itertools import repeat
b = []
for i in repeat(1, 4): # повторение итератора
b.append(i)
print (b)
from itertools import count
c = []
for i in count(1): # бесконечный итератор
c.append(i)
if i > 10:
break
print(c)
from itertools import cycle
d = []
for i, j in enumerate(cycle([1,2,3])):
d.append(j)
if i>10:
break
print (d)
from itertools import islice
e1 = islice(range(10), 3, 6) # срезы
e2 = islice(range(10), 3, 9, 2)
print ("e[3:6] " + str(list(e1)))
print ("e[3:9:2] " + str(list(e2)))
from itertools import dropwhile # ещё есть takewhile
f = dropwhile(lambda x: x < 5, range(10))
print (list(f))
from itertools import tee
it = range(3)
a, b, c = tee(it, 3) # три независимые копии итераторов
tmp = list(c) # этот итератор "уничтожится"
print (list(a), list(b), list(c))
from itertools import product
it = product("AB", repeat=2) # декартово произведение
print (list(it))
from itertools import permutations
it = permutations("YN") # перестановки
print (list(it))
from itertools import combinations
it = combinations("ABC", 2) # сочетания (без повторений)
print (list(it))
from itertools import combinations_with_replacement
it = combinations_with_replacement("AB", 2) # сочетания c повторениями
print (list(it))
[1, 2, 3, 4, 5] [1, 1, 1, 1] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] e[3:6] [3, 4, 5] e[3:9:2] [3, 5, 7] [5, 6, 7, 8, 9] [0, 1, 2] [0, 1, 2] [] [('A', 'A'), ('A', 'B'), ('B', 'A'), ('B', 'B')] [('Y', 'N'), ('N', 'Y')] [('A', 'B'), ('A', 'C'), ('B', 'C')] [('A', 'A'), ('A', 'B'), ('B', 'B')]
from itertools import groupby
it = groupby("ABBAAACBCC") # группировка
for i, j in it:
print (i, sum(1 for _ in j)) # list(j)
A 1 B 2 A 3 C 1 B 1 C 2
# не поддерживается!!!
from itertools import imap
# izip
--------------------------------------------------------------------------- ImportError Traceback (most recent call last) <ipython-input-111-2d92cb050d6d> in <module>() 1 # не поддерживается!!! ----> 2 from itertools import imap 3 # izip ImportError: cannot import name 'imap'
from itertools import takewhile
for i in takewhile(lambda x: x > 0, [1, -2, 3, -3]): # выдаёт пока истино
print ('takewhile', i)
from itertools import dropwhile
for i in dropwhile(lambda x: x > 0, [1, -2, 3, -3]): # не выдаёт пока истино, но потом - всё
print ('dropwhile', i)
takewhile 1 dropwhile -2 dropwhile 3 dropwhile -3
# НЕ РАБОТАЕТ
import itertools, math
lst = map(lambda x: math.sin(x*.4), range(30))
for k, i in itertools.groupby(lst, lambda x: x > 0):
print (k, lst(i))
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-301-23cdea7766c6> in <module>() 3 lst = map(lambda x: math.sin(x*.4), range(30)) 4 for k, i in itertools.groupby(lst, lambda x: x > 0): ----> 5 print (k, lst(i)) TypeError: 'map' object is not callable
itertools.tee(range(3), 2) # клонирование итераторов
(<itertools._tee at 0x46afe48>, <itertools._tee at 0x46837c8>)
from itertools import combinations
it = combinations(range(3), 2)
len(list(it))
3
# свой итератор
class Fibonacci:
"""Итератор последовательности Фибоначчи до N"""
def __init__(self, N):
self.n, self.a, self.b, self.max = 0, 0, 1, N
def __iter__(self):
return self
def __next__(self): # должна быть такая функция ( # Python 2: def next(self))
if self.n < self.max:
a, self.n, self.a, self.b = self.a, self.n+1, self.b, self.a+self.b
return a
else:
raise StopIteration
# for i in Fibonacci(10):
# print (i)
list(Fibonacci(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
# упрощённый итератор
class Identity:
def __getitem__(self, idx):
if idx > 5:
raise IndexError(idx)
return idx
list(Identity())
[0, 1, 2, 3, 4, 5]
-- помогают делать ленивые вычисления (lazy computations)
не вычисляет все значения сразу - делает это поитерациям
yield - похожа на return, но работа функции приостанавливается и выдаётся значение
def Fib(N):
a, b = 0, 1
for i in range(N):
yield a # вместо return для выдачи следующего значения
a, b = b, a + b
for i in Fib(10):
print (i)
0 1 1 2 3 5 8 13 21 34
def double_numbers(iterable):
for i in iterable:
yield i + i
list(double_numbers(range(5)))
[0, 2, 4, 6, 8]
# генераторное выражение
print ( [x * x for x in range(5)] ) # это список
print ( (x * x for x in range(5)) ) # а это - генераторное выражение
# не порождается коллекция;)
print ( sum(x * x for x in range(5)) ) # тут без скобок - тоже генераторое выражение
[0, 1, 4, 9, 16] <generator object <genexpr> at 0x7efe441ce678> 30
gen = (x*x for x in range(5))
print ('использование генераторного выражения:')
for y in gen:
print (y)
print ('переиспользование:') # ничего не будет!
for y in gen:
print (y)
использование генераторного выражения: 0 1 4 9 16 переиспользование:
# сопрограммы (coroutines)
# больше одной точки входа
# остановка исполнения, сохранение состояния и продолжение
def grep(pattern):
print("Ищем {!r}".format(pattern))
while True:
line = yield # точка входа в line засылает метод send
if pattern in line:
print('нашли в: ' + line)
gen = grep("Мир")
next(gen) # обязательно нужно - это инициализация (инициализацию можно спрятать в декораторе)
gen.send("Предложение")
gen.send("Предложение с Миром")
gen.send("Предложение с миром")
gen.send("Миру мир!")
Ищем 'Мир' нашли в: Предложение с Миром нашли в: Миру мир!
def f():
yield 1
yield 2
yield 3
# return 10 - нет эффекта
def g():
x = yield from f() # взять выход у f!
yield 4
yield 5
yield 6
# return 100 - нет эффекта
list(g())
[1, 2, 3, 4, 5, 6]
для модификации функции, сохраняя читабельность кода
# пример цепочки декораторов
def square(f): # на вход - функция
return lambda x: f(x * x) # выход - функция, которая будет реально выполняться
def add1(f): # на вход - функция
return lambda x: f(x + 1) # выход - функция, которая будет реально выполняться
# два декоратора у функции
@square
@add1
def time2(x):
return (x * 2)
time2(3) # (3*3 + 1)*2
20
class my_decorator(object):
def __init__(self, f):
print("внутри my_decorator.__init__()")
f() # это просто создание функции f
def __call__(self):
print("внутри my_decorator.__call__()")
@my_decorator
def aFunction():
print("внутри aFunction()")
print("окончание декорирования aFunction()")
aFunction() # вызов функции
# на самом деле вызывается my_decorator.__call__()
внутри my_decorator.__init__() внутри aFunction() окончание декорирования aFunction() внутри my_decorator.__call__()
# зачем нужны декораторы:
class entry_exit(object):
def __init__(self, f):
self.f = f
def __call__(self):
print("вызов - ", self.f.__name__)
self.f()
print("выход - ", self.f.__name__)
@entry_exit
def func1():
print("работа func1()")
@entry_exit
def func2():
print("работа func2()")
print ('Вызовы функций:')
func1()
func2()
Вызовы функций: вызов - func1 работа func1() выход - func1 вызов - func2 работа func2() выход - func2
# здесь декоратор - функция
# главное, чтобы декоратор можно было вызвать
def entry_exit(f):
def new_f():
print("Вызов: ", f.__name__)
f()
print("Выход: ", f.__name__)
new_f.__name__ = f.__name__ # меняем даже имя функции (попробуйте убрать)
return new_f
@entry_exit
def func1():
print("работа func1()")
@entry_exit
def func2():
print("работа func2()")
print ('Вызовы')
func1()
func2()
print(func1.__name__)
Вызовы Вызов: func1 работа func1() Выход: func1 Вызов: func2 работа func2() Выход: func2 func1
# декоратор без аргументов
class decorator_without_arguments(object):
def __init__(self, f):
"""
Если пишем декоратор без аргументов,
то передаём в конструкторе функцию
"""
print("Inside __init__()")
self.f = f
def __call__(self, *args):
"""
В __call__ method передаём аргументы.
"""
print("Inside __call__()")
self.f(*args)
print("After self.f(*args)")
@decorator_without_arguments
def sayHello(a1, a2, a3, a4):
print('Аргументы:', a1, a2, a3, a4)
print("После декорации...")
sayHello("say", "hello", "argument", "list")
print("Ещё раз...")
sayHello("a", "different", "set of", "arguments")
Inside __init__() После декорации... Inside __call__() Аргументы: say hello argument list After self.f(*args) Ещё раз... Inside __call__() Аргументы: a different set of arguments After self.f(*args)
# декоратор с аргументами
class decorator_with_arguments(object):
def __init__(self, arg1, arg2, arg3):
"""
Если пишем с аргументами, то их передаём в конструктор,
а функция не передаётся!
"""
print("работа __init__()")
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
def __call__(self, f):
"""
Если пишем с аргументами, то __call__() вызывается лишь раз,
как часть процесса декорации, ей можно передать только функцию!
"""
print("работа __call__()")
def wrapped_f(*args):
print("работа wrapped_f()")
print("Аргументы:", self.arg1, self.arg2, self.arg3)
f(*args)
print("выход из f(*args)")
return wrapped_f
@decorator_with_arguments("hello", "world", 42)
def sayHello(a1, a2, a3, a4):
print('Аргументы sayHello:', a1, a2, a3, a4)
print("После декорации...")
sayHello("say", "hello", "argument", "list")
print("Ещё раз...")
sayHello("a", "different", "set of", "arguments")
работа __init__() работа __call__() После декорации... работа wrapped_f() Аргументы: hello world 42 Аргументы sayHello: say hello argument list выход из f(*args) Ещё раз... работа wrapped_f() Аргументы: hello world 42 Аргументы sayHello: a different set of arguments выход из f(*args)
# декораторная функция с аргументами
def decorator_function_with_arguments(arg1, arg2, arg3):
def wrap(f):
print("Inside wrap()")
def wrapped_f(*args):
print("Inside wrapped_f()")
print("Decorator arguments:", arg1, arg2, arg3)
f(*args)
print("After f(*args)")
return wrapped_f
return wrap
@decorator_function_with_arguments("hello", "world", 42)
def sayHello(a1, a2, a3, a4):
print('sayHello arguments:', a1, a2, a3, a4)
print("After decoration")
print("Preparing to call sayHello()")
sayHello("say", "hello", "argument", "list")
print("after first sayHello() call")
sayHello("a", "different", "set of", "arguments")
Inside wrap() After decoration Preparing to call sayHello() Inside wrapped_f() Decorator arguments: hello world 42 sayHello arguments: say hello argument list After f(*args) after first sayHello() call Inside wrapped_f() Decorator arguments: hello world 42 sayHello arguments: a different set of arguments After f(*args)
их реализация м.б. специализирована для конкретного типа
print (len([1, 2, 3]))
print (len({1, 2, 3}))
print (len(range(4)))
3 3 [0, 1, 2, 3]
print (str([1, 2, 3]))
print (str({1, 2, 3}))
print (str(range(4)))
[1, 2, 3] set([1, 2, 3]) [0, 1, 2, 3]
print (sum([1, 2, 3]))
print (sum({1, 2, 3}))
print (sum(range(4)))
6 6 6
import pandas
import imp
imp.reload(pandas)
<module 'pandas' from '/home/dash/anaconda3/lib/python3.6/site-packages/pandas/__init__.py'>