[Конспект] Python 3

Основы
Python — интерпретируемый язык. Его можно встраивать в C/C++ программы. Официальное руководство говорит, чтобы исполняющиеся скрипты создавались посредством bash.
#!/usr/bin/env python3
print("Hello" "{}world".format(" "))
Затем задать права chmod a+x hello.py и добавить в PATH (PATH=$PATH:DIRNAME)
Для получения справки используется встроенная функция help.
help('print')
Комментарии со знака решетки
# this is help function
help('print')
Числа
Числа бывают целые, с плавающей точкой и комплексные с помощью j
(1-1j)
Дробные литералы MEp, где M - мантисса, E - E, p - порядок
print(1.2E-4)
Двоичные объявляются через 0b. Восьмиричные объявляются с нуля и латинской буквы «o», 0o. Шестнадцатеричные объявляются через 0x. Для операций с действительной дочностью используются объекты Decimal и модуля decimal.
from decimal import *
print(1.0 - 0.1 - 0.3) # 0.6000000000000001
print(Decimal('1.0') - Decimal('0.1') - Decimal('0.3')) # 0.6
Для дробей используется тип Fraction из модуля fractions.
from fractions import *
print(Fraction(1, 2)) # 1/2
Функции преобразования int (с системой счисления), float, bin, oct, hex, round (с количеством точек после запятой), abs, pow, max, min, sum (последовательность), div (возвращает кортеж x// y, x%y).
print(12)
print(1.4E-2)
print(1-1j)
/usr/bin/python /test.py
12
0.014
У типа float усть методы методы is_integer, as_integer_ration — возвращает кортеж числителя и знаменателя дроби.
Строки
Строки указываются в одинарных и двойных кавычках, они никак не отличаются.
print("test")
print('test')
Тройные двойные или одинарные кавычки действуют как HEREDOC.
print(""" First line"" And second """)
Объединить строки можно поставив их одну за одной. print(“Hello” “ “ “World”) Вывод с помощью print. Ввод с помощью input.
input = input("Enter some string") print(input)
Точка с запятой нежелательна
print("Hello" " " "World"); # Bad print(2)
Метод format позволяет составить строку на основе каких-либо данных.
print("Say {}".format("Hi"))
print("My name is {0}. And the second is {1}".format("Pavel", "Murtazin"))
print("Your name is {name}".format(name="Vasya"))
А так же с уточнениями. (см. http://www.python.org/dev/peps/ pep-3101) Все строки в UTF-8. Для объявления кодировки применяется специальный комментарий
# -*- coding: utf-8 -*-
Строки позволяют работать с ними, как с коллекциями, то есть выбирать символ и брать срезы.
print("A very long message"[0:6]) # A very Конкатенация через плюс. Причем строка всегда является строкой.
print("1" + "2") # 12
bytes
и bytearray
являются строковыми типами данных. Чтобы использовать несколько строк в одной, необходимо использовать слэш.
Для использования слэша в конце строки, его необходимо экранировать.
# print("Hello\") # SyntaxError: EOL while scanning string literal
print("Hello\\") # Hello\
Что отлючить спецсимволы в строке, нужно перед строкой разместить модификатор r.
print(r"Hello\n") # Hello\n
Если строку не передать в аргумент, то она автоматически попадет в переменную doc текущего объекта. Строка — неизменяемая последовательность, можно получить символ по индексу, но нельзя изменить. Узнать длину строки можно с помощью функции len.
print(len("Hello")) # 5
Операция умножения повторяет строку, а in и not in осуществляет проверку на вхождение.
print("A" * 3) # AAA
Оператор форматирования - это процент. Специальная строка имеет формат %[key][flag][width][.accuracy]<type>
.
key
— ключ словаря, тогда правым операндом должен быть передан словарь.flag
— флаг преобразования#
— восьмиричное значение0x
— количество ведущих нулей-
— выравнивание по левой границепробел
— вставляет пробел перед положительным числом+
— обязательный ввод знака для положительных и отрицательных чисел
width
— минимальная ширина поляaccuracy
— количество знаков после точки для вещественных чисел. Можно указать как * и передать значения внутри кортежа.type
- тип преобразованияs
— строкаr
— строка с помощью repra
— строка с помощью asciic
— символd
,i
— целое числоo
- восьмиричноеx
,X
- шестнадцатиричное в нижнем и верхнем регистреf
иF
— вещественное числоe
иE
— вещественное число в экспоненциальной формеg
иG
— вещественное чсило в наиболее короткой форме
print("""
My name is %(name)s.
I am %(age)i age old.
I live in %(city)-10s.
My body's temperature is %(temp)010.5G """ % {
"name": "Alex", "age": 10,
"city": "London", "temp": 36.63145123412
})
# My name is Alex.
# I am 10 age old.
# I live in London .
# My body's temperature is 000036.631
В качестве альтернативы используется метод format. Для этого метода символы {} являются специальными, вместо них подставляются соответствующие аргументы.
print("My name is {1}. I am {0} age old".format(10, "Paul"))
Аргументы могут быть именованными или же являться словарем.
print("My name is {name}. I am {age} age old".format(age=10, name="Paul"))
print("My name is {name}. I am {age} age old".format(**{"age": 10, "name": "Paul"}))
Внутри специальной строки можно получить доступ к элементам массива.
print("My name is {data[name]}. I am {data[age]} age old".format(data={'age': 10, 'name': "Paul"}))
Через восклицательный знак можно указать функцию-обработчик.
- s
- str
- r
- repr
- a
- ascii
print("My name is {data[name]!a}. I am {data[age]} age old".format(data={'age': 10, 'name': "Павел"}))
В конце через двоеточие можно указать форматирование в формате. - Заполнитель с выравниванием по левому (<) и правому (>) краю, или по-центру (^).
print(
"My name is {name:!>10}." \
.format(
**{"age": 10, "name": "Paul"}
) # My name is !!!!!!Paul.
)
-
Минимальную ширину строки.
- Указать знак для чисел.
+
— с выводом всех знаков,-
— только отрицательных,пробел
— пробел для положительных. - Указать преобразование.
b
— двоичное число. print(““.format(100)) # 1100100c
— целое число в символ print(““.format(47)) # /d
— десятичное числоn
— как d, но учитывает настройки локалиo
— восьмиричное числоx
— шестнадцатеричное значение в нижнем регистреX
— шестнадцатеричное значение в верхнем регистреf
иF
— вещественное число в десятичном представленииe
иE
— вещественное число в экспоненциальном представленииg
иG
— f или e, что будет короче%
— преобразует в процент Строки имеют следующие методы.
expandtabs
— заменяет символы табуляции на пробелы (можно указать количество пробелов).center
- выравнивает строку по центру внутри поля указанной длины.ljust/rjust
— выравнивает строку по левому/правому краю внутри поля указанной длины.zfill
— выравнивает строку по правому краю внутри поля указанной длины, дополняя 0.strip
— удаляет символы с начала и конца строки (если аргумент не передан, то пробельные символы).lstrip
, rstrip — удаление символов слева/справа.split
— разбивает строку по указанному разделителю.rsplit
— тоже, но поиск разделителя справа-налево.splitlines
— разбивает строку на подстроки. Если передать False, то в результате будет только первая строка.partition
— находит первое вхождение символа-разделителя и возвращает кортеж из фрагмента перед разделителем, разделитель и фрагмент после.rpartition
— тоже, но поиск справа-налево.join
— преобразует последовательность в строку.upper
— в верхний регистр.lower
— в нижний регистр.swapcase
— меняет регистр местами.capitalize
— первая буква в верхний регистр.title
— первая буква каждого слова в верхний регистр.casefold
— как и lower, но преобразует диактрические знаки в латиницу.find
— ищет подстроку в строке.index
— тоже, что и find, но с исключением.rfind
— find справа-налево.rindex
— тоже для index.count
— количество вхождений подстроки в строку.startswith
— начинается ли строка с подстроки.endswith
— заканчивается ли строка с подстроки.replace
— заменяет все подстроки, входящие в строку.translate
— заменяет все символы в соответствии с таблицей символов. В качестве ключей код символа.maketrans
— статический метод, помогающий создать таблицу символов.isalnum
— проверяет, что строка собержит только буквы и цифры.isalpha
— только буквы.isdigit
— только цифры.isdecimal
— только десятичные цифры.
- Указать знак для чисел.
print("Hello".rjust(20, '0'))
print("Hello".zfill(20))
print("ß".casefold()) # ss
print("Hello".translate({ord("H"): "M" })) # Mello
print("Hello".translate( str.maketrans({"H": "M"}))) # Mello
Определить кодировку можно с помощью метода detect модуля chardet
.
print(chardet.detect(result.read())) # {'confidence': 0.99, 'encoding': 'utf-8'}
Bytes и bytearray
Эти типы данных подходят для обработки изображений. Можно создать с помощью одноименных функций, передав последовательность или челое число для инициализации последовательности переданной длины. Bytes можно создать, начав строку с b.
b"Foo-bar"
Есть методы append, extend, insert, pop, remove, reverse, decode. Метод decode преобразует в указанную кодировку. С помошью модуля pickle (методы dumps и loads) можно сериализовать и десериализовать объекты в последовательность байтов.
import pickle
fb = pickle.dumps("Foo-bar") print(pickle.loads(fb))
Взаимодействие с файловой системой
Открыть файл можно с помощью функции open.
for line in open(__file__):
num += 1
print(str(num) + " " + line)
Метод readline возвращает текущую строку. Метод close закрывает файл. Чтобы записать в файл используется функция print с аргументом file. Но для этого необходимо открыть файл в режиме записи (аргумент mode).
file = open('./sources/index.txt', 'w')
for i in range(0, 20):
print("Line N" + str(i), file=file)
file.close()
Также для записи существует метод write.
file = open('./sources/index.txt', 'w')
for i in range(0, 20):
print("Line N" + str(i), file=file)
file.write("Last %s" % "Line")
file.close()
Для записи/чтения из стандартного потока используются объекты sys.stdout и sys.stdin
import sys
line = sys.stdin.readline()
sys.stdout.write("{}\r...\nOk".format(line))
Типы данных
bool
- логический.NoneType
- отсутствие значение. Объявляется как None.int
- целое число. Ограничено оперативной памятью.float
- число с плавающей точкой.complex
- комплексное число.str
- строка.bytes
- неизменяемая последовательность байтов.bytearray
- изменяемая последовательность байтов.list
- список. Последовательность.tuple
- кортежи.range
- диапазон. От и до для чисел.dict
- словарь. Ассоциативный массив.set
- множество. Набор уникальных значений.frozenset
- неизменяемое множество. Набор уникальных значений. ellipsis - обозначается тремы точками.function
- функция.module
- модуль.type
- сами типы являются этим типом.
Определить тип можно с помощью функции type.
print(type(...)) # <class 'ellipsis'>
Приведение типов производится с помощью одноименной с типов функции. Чтобы проверить тип данных, нужно сравнить результат функции type и имени типа.
print(type(1) == int) # True
Преобразование типов
Преобразования к строке производится с помощью функций str
, repl
, ascii
и format
.
class Person:
pass
print(str(23))
print(repr(Person()))
Преобразования с помощью методов str
, int
.
print(str(1)) # "1"
print(int("12")) # 12
Остальное
Переменные объявляются с определения.
eggSize = 10
При присваивании в переменной хранится ссылка на объект, а не сам объект. Это необходимо учитывать при групповом присваивании.
x = y = {
"one": 1,
"two": 2
}
y["one"] = 3
print(x, y, sep="\n")
# {'two': 2, 'one': 3}
# {'two': 2, 'one': 3}
Python кэширует малые числа и строки, так что они ссылаются на одну облать в памаяти. Чтобы узнать, что переменные ссылаются на один и тот же объект используется оператор is.
a = 2 b = 1 + 1
print(a is b) # True
Обратной операцией является is not.
print(2 is not 3) # True
Количество ссылок можно узнать с помощью функции getrefcount модуля sys.
print(sys.getrefcount(2)) # 116
Как только количество ссылок равно нулю, область памяти очищается. Список ключевых слов можно найти в модуле keyword.kwlist. Встроенные идентификаторы можно переопределить. Все типы являются объектами. Логическая строка в Python — одна инструкция. По-умолчанию одна строка — одна инструкция. Чтобы разместить на одной физической строке несколькое логических используется точка с запятой. Чтобы разбить логическйю строку на физические используется обратный слэш.
eggSize = \
10
print(eggSize)
Логическими типами являются True и False. В Python крайне важны отступы. Набор предложений, идущих одно за одним, с одинаковыми отступами называется блоком. Блоки высокого уровня указывают на вложенные с помощью двоеточия. Для использования пустого блока используется оператор pass.
if True:
pass
Удаление происходит с помощью оператора del.
a = 50
del a
# print(a) NameError: name 'a' is not defined
Регулярные выражения
Регулярные выражения лежат в модуле re. Создать регулярное выражение можно с помощью функции compile
.
Первым аргументом является регулярное выражение, а вторым флаги.
L
— учитывать настройки локали.I
— ignorecaseM
— поиск в строке, состоящей из нескольких строк.S
— включить, что точка — любой символ, ^ — начало строки, $ — конец строки.X
— пробельные символы и переноса строки будут проигнорированы. Добавляет возможность комментариев.A
— символы \w \W \d и прочие теряют свое предназначение.
re.compile("""
^ # Start of line
.* # Any symbol
$ # End of line
""", re.X)
Методы.
match
— проверяет соответствие с началом строки.search
— проверка на соответствие.fullmatch
— соответствие строки целиком.findall
- ищет все совпадения.findinter
— возвращает итератор.sub
— осуществляет замену.split
— разбивает по шаблону.
Эти методы возвращают объект типа Match. Он имеет полезные методы и свойства.
re
— ссылка на регулярное выражение. У регулярного выражения имеются свойства.groups
— количество групп в шаблоне.groupindex
— словарь с именами и номерами групп.pattern
— строка регулярки.flags
— флаги.
string
— переданная строка, в которой происходит поиск.pos
и endpos — значения одноименных аргументов в функциях, которые были использованы (match или search).lastindex
— номер последней совпавшей группы или None.lastgroup
— для именованных групп.group(index)
— фрагмент совпавшей группы.groupdict
— словарь с группами и их значениями.groups
— все группы.expand
— производит замену в строку.
Всем методам есть одноименные функции. Также есть функция escape
, которая экранирует переданную строку.
Операторы и выражения
Стандартные + - / * % и дополнительные ** (возведение в степень) и // (целая часть от деления)
print(1 + 1) # 2
print("one" + "one") # oneone print(1 - 1) # 0
print(4 / 2) # 2
print(2 * 2) # 4
print("one" * 2) # oneone print(4 % 3) # 1
print(2 ** 3) # 8
print(5 // 3 ) # 1
Побитовые « » & (and) | (or) ^ (xor) ~ (not)
print(0b1001 << 2) # 0b0100100 == 36 <=> n << x (n * (2 ** x))
print(0b1001 >> 2) # 0b0010 == 2
print(0b110 & 0b011) # 0b010 == 2
print(0b110 | 0b001) # 0b111 == 7
print(0b110 ^ 0b011) # 0b101 == 5
print(~ 0b011) # -0b100 == -4
Логические not
or
and
print(0 and 1) # 0
print(0 or 1) # 1
print(not 0) # True
Математические операции присваивания могут быть в краткой форме.
a = 10
a += 10
print(a) # 20
Все операторы левоассоциативны. Оператор in проверяет на вхождение в последовательность.
print("a" in "abc") # True
Оператор not in проверяет на НЕ вхождение в последовательность.
print("d" not in "abc") # True
Условные операторы
Булевое значение возвращают операторы <, >, ==, != или <>, <=, =>, is, is not, in, not in Оператор if называется if-{block}.
if 1:
print('Block' ' 1')
Используется вместе с необязательными elif-{block} и else-{block}
age = int(input("Enter your age\n"))
if age < 18:
print("Учись")
elif age < 60:
print("Работай")
else:
print("Отдыхай")
exit("Ok")
Есть цикл while-{block} для обхода последовательностей.
while True:
age = int(input("Enter your age\n"))
if age < 18:
print("Учись")
elif age < 60:
print("Работай")
else:
print("Отдыхай")
exit("Ok")
Может использоваться с else-{block}. Он выполнится, если не было операции break.
a = True
while a:
a = bool(raw_input("Press Enter"))
else:
exit("Enter pressed")
Цикл for-in-{block} также может использовать else-{block}. Цикл позволяет обходить коллекции.
for i in range(1, 12): # [1, 11]
print(i)
else:
print("Bye-bye")
Для прерывания цикла используется break, а для перехода к следующей итерации continue
for i in range(1, 100):
if i > 10:
break
if i < 5:
continue
print i
Функции
Именные функции
Объявляется с помощью ключевого слова def
.
def say_hi_to(person_name):
print("Hi, " + person_name)
say_hi_to("Mike") # Hi, Mike
Область видимости локальна. Глобальныю переменную можно указать с помощью global
.
Функции можно вкладывать друг в друга. Чтобы указать переменную как переменную из внешней фукнции используется ключевое слово nonlocal
.
x = 1
def glob_test():
global x
print(x)
def outer():
y = 10
def inner():
nonlocal y
y = 30
print(y) # 10
inner()
print(y) # 30
glob_test() # 1
outer()
Функция globals
возвращает словарь глобальных переменных, а locals
— локальных.
Значения аргументов по-умолчанию через знак равенства.
def egg(count = 10):
print("You have {} eggs".format(count))
egg() # You have 10 eggs
Параметры могут быть ключевыми. То есть при вызове можно указать имя параметра.
egg(count=20) # You have 20 eggs
Можно определить функции с переменным числом параметров с помощью одинарной и двойной звездочки.
def echo(*argv, **named):
for arg in argv:
print(arg)
for name in named:
print("{name}:{value}".format(name=name, value=named[name]))
echo("Arg1", PI=3.14, e=2.7) # Arg1 PI:3.14 e:2.7
При этом из переменной, объявленной с одной звездочкой, будет образован кортеж, а с двумя — словарь. Чтобы объявить параметр, доступный только по ключу, его необходимо объявить после параметра со звездочкой.
def foo(normal, *any, required_name):
pass
foo(1, required_name=12)
Можно комбинировать все эти типы параметров. Для возвращения значения используется return
.
def sum(a, b):
return a + b
Функция модет возвращать кортеж для дальнейшей распаковки. Указать тип аргумента можно через двоеточие, а возвращаемый тип с помощью стрелочки после объявления функции.
def sum(left: float, right: float) -> float:
return left + right
Если начать функцию со строки, то она поместиться в свойство __doc__
и будет доступна при вызове help.
def sum(left: float, right: float) -> float:
"""
Args:
left: Float
right: Float
Returns: sum of arguments
"""
return left + right
sum(1, 2)
help(sum)
print(sum.__doc__)
/usr/bin/python /test.py
Help on function sum in module __main__:
sum(left:float, right:float) -> float
Args:
left: Float
right: Float
Returns: sum of arguments
Args:
left: Float
right: Float
Returns: sum of arguments
Функции тоже являются объектом, поэтому их можно передать.
def sum(a, b):
return a + b
def funcWith(f, a, b):
return f(a, b)
print(funcWith(sum, 20 ,30)) # 50
Для того, чтобы распаковать кортеж или список в аргументы, используется звездочка.
print(funcWith(sum, *[20, 30])) # 50
Для того, чтобы распаковать словарь как имя аргумента и изначение используются двойные звездочки.
print(funcWith(sum, **{"a": 20, "b": 30})) # 50
Анонимные функции
Анонимные функции называются лямбда-функциями. Объявляются как lambda param1..paramN: returnvalue
print((lambda: 10 + 10)()) # 20
print((lambda a, b, *c: a - b + sum(c))(1, 2)) # -1
Как и в обычных функциях, параметры могут быть необязательными. Подобно обычным функциям могут буть многострочными.
Функции-генераторы
Функция-генератор возвращает новое вычисляемое значение для каждой итерации. Они поддерживают метод next.
Значение, которое возвращается для новой итерации стоит после ключевого слова yield
.
def gen(a):
for i in range(1, a):
yield i
for i in gen(10):
print(i)
Из одной функции генератора можно вернуть результат другой функции-генератора с помощью yield from
.
def gen(a):
for i in range(1, a):
yield i
def gen2(a):
for i in range(1, a):
yield from gen(i)
for i in gen2(10):
print(i)
Тогда сначала выполнится первая итерация верхней функции, а так для результата каждый из вложенной.
Декораторы функций
Python имеет встроенную поддрежку декорирования функций. Для этого необходимо объявить функцию, которая будет выступать декоратором (она принимает и возвращает декорируемую в качестве аргумента), а затем имя этой функции использовать в качестве аннотации к декорируемой.
def log(f):
print(str(f) + " was called")
return f
@log
def sum(a, b):
return a + b
sum(2, 2) # <function sum at 0x10715d158> was called
Может быть более одной функции-декоратора. Вызов идет снизу вверх по объявленным декораторам.
Чтобы перехватить аргументы, функция декоратор должна возвращать третью функцию, которая ожидает аргументы.
def checktype(func):
"""
Check types in annotation, if annotion is None, then skipped
:param func: function
:return: function
"""
def inner(*args, **kwargs):
if not kwargs:
"Nothing to check. Use named arguments"
for name, argtype in func.__annotations__.items():
if name in kwargs:
checkarg(kwargs[name],argtype)
return func(*args, **kwargs)
def checkarg(arg, argtype):
assert type(arg) == argtype
return inner
@checktype
def sqlen(l: str, r: str):
if len(l) > len(r):
return -1
elif len(r) > len(l):
return 1
return 0
sqlen(l="String 1", r="String2")
# sqlen(l="String 1", r=10) # AssertionError
Вложенные функции
Функции можно вкладывать одну в другую. Внутренняя функция имеет доступ ко всем переменным внешней, но при этом не может их изменять.
def outer():
x = 1
def inner():
print("x=" + str(x))
inner()
outer() # x=1
Чтобы изменять функцию, нужно указать её как nonlocal
.
def outer():
x = 1
def inner():
nonlocal x
print("x=" + str(x))
x = 3
inner()
print("x=" + str(x))
outer() # x=1 # x=3
Аннотации функций
Функции могут содержать аннотации. С помощью них можно указать данные какого типа принимает функция, предназначение параметров и тип возвращаемого значения.
Аннотации к аргументу ставятся через двоеточие после имени аргумента (если есть значение по-умолчанию, то оно ставится после аннотации).
Аннотации к аргументу вызываются перед вызовом функции и сохраняются в свойство __annotation__
(словарь) по ключу, который является именем функции.
def sum(a: [int, str, "An integer"], b: 1 + 2):
return a + b
print(sum.__annotations__) # {'a': [<class 'int'>, <class 'str'>, 'An integer'], 'b': 3}
Аннотация к возвращаемому значению ставится через ->
, вызываeтся перед вызовом функции и хранится по ключу return.
def sum(a: [int, str, "An integer"], b: 1 + 2) -> 2 + 4:
print(sum.__annotations__)
return a + b
print(sum(1,2)) # {'return': 6, 'b': 3, 'a': [<class 'int'>, <class 'str'>, 'An integer']}
Модули
Модулем называется файл с функциями, который можно импортировать с помощью команды import
.
Это могут быть файлы с расширением .py
, написанные на C модули или же один из встроенных модулей Python.
import sys
for path in sys.path:
print(path)
Импорт модулей — дорогостоящая операция, чтобы быстро импортировать модули, то необходимо перевести их в байт-код. Такие файлы имеют расширение .pyc
.
Можно импортировать только определенные переменные, а также сразу задать им псевдонимы с помощью команды from-import-as
.
from sys import argv as args
from datetime import timedelta, time
print(args[0])
Каждый модуль имеет имя в переменной __name__
.
__name__ = "MyModule"
По-умолчанию модуль называется __name__
.
Чтобы определить собственный модуль необходимо создать файл с расширением .py
.
Модуль должен лежать в том же каталоге, где он импортируется, либо в одном из каталого sys.path
.
import Modulo
Modulo.echo(Modulo.__version)
> ls -1
Modulo.py
__pycache__
script.py
Чтобы импортировать все публичные методы и свойства модуля используется звездочка.
from Modulo import *
echo(10)
# echo(__version__)
Функция dir
возвращает список всех идентификаторов для аргумента.
import Modulo
echo(dir(Modulo))
# ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', 'echo']
Без аргументов возьмется текущий модуль.
print(dir())
# ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
a = 1
print(dir())
# ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a']
Пакетом называется каталог с модулями и специальным файлом __init__.py
, который сообщает Python, что каталог является пакетом.
Доступ к модулям пакета осуществляются с помощью точек package1.package2.module
.
from Step1.Module.yes import *
Чтобы импортировать модуль, который расположен в том же каталоге, необходимо имя модуля начать с точки.
from .Timer import *
Чтобы обратиться к родительсткому пакету используется две точки.
Файл __init__.py
должен быть либо пустым, либо иметь код, который будет выполнятся при первом импорте из пакета.
Он может содержать.
- Переменную __all__
, которая является списком имен модулей, которые можно загрузить с помощью from package import *
.
- Можно использовать импорты, которые будут доступны как from package import *
.
Чтобы повторно загрузить модуль необходимо воспользоваться функцией reload
из модуля imp
.
Структуры данных
Последовательности
К последовательностям относятся str
, list
, tuple
, range
, bytes
и bytearray
.
Python поддерживает позиционное присваивание.
one, two, three = 1, 2, 3
С его помощью можно поменять значения местами.
На самом деле правая часть позиционного присваивания неявно приводится к кортежу. По обе стороны могут находится любые последовательности. Чтобы передать в переменную несколько значений сразу используется звездочка, чтобы проигнорировать значение — нижнее подчеркивание.
a, _, *lst = 1, 2, 3, 4
print(a, lst) # 1, [3, 4]
Все указанные последовательности и строки обладают дополнительными свойствами сабскрипта. Отрицательный индекс берет значения с конца.
list = ["One", "Two", "Three"]
print(list[-1]) # Three
Брать срезы слева-направо, справа-налево с помощью двоеточия. Указать можно от начала или до конца.
При этом правое значение является не включительным.
listing = ["One", "Two", "Three", "Four"]
print(listing[:1]) # ['One']
print(listing[1:]) # ['Two', 'Three', 'Four']
print(listing[1:3]) # ['Two', 'Three']
print(listing[-1:]) # ['Four']
Можно указать шаг через еще одно двоеточие.
print(listing[::2]) # ['One', 'Three']
print(listing[1::2]) # ['Two', 'Four']
При полной вырезке создается копия, а не ссылка. При присваивании же создается ссылка.
# l = [1, 2, 3]
# l2 = l <=> l2 === l
# l3 = l[:] <=> l2 !== l
При итерировании последовательностей используется метод __next__
или функция next
. Для всех последовательностей возвращается значение. А для словаря — значение ключа, так как словарь является отображением, а не последовательностью. Функция enumerate
возвращает итератор, который на каждый вызов next возвращает кортеж ключ/значение.
for k, v in enumerate(range(1, 10)):
print("{}: {}".format(k, v))
Для объединения последовательностей одного типа используется оператор +
.
Функция map
принимает функцию и последовательность, потом применяет функцию к каждому элементу.
Функция zip
на каждой итерации возвращает кортеж элементов переданных последовательностей, которые находятся на одинаковом смещении.
Функция filter
принимает функцию и последовательность, потом фильтрует последовательность с учетом переданной функции. Функция reduce принимает функцию и последовательность и/или начальное значение, потом сводит последовательность к единому значению с помощью переданной функции.
Существуют методы append
, extend
, insert
, pop
, remove
, clear
, index
, count
, reverse
, reversed
, shuffle
, sort
, join
.
Функции min
, max
, any
.
Список
Список — содержит упорядоченный набор элементов. Задается с помощью квадратных скобок.
toBuy = ["Cheese", "Vine", "Bread", "Tomato", "Olive oil", "Salad"]
for product in toBuy:
print(product)
Метод append
добавляет элемент в конец списка.
toBuy.append("Gum")
Метод insert
добавляет элемент на указанную позицию.
list = [1, 2, 3, 4, 5]
list.insert(2, 7)
print(list) # [1, 2, 7, 3, 4, 5]
Метод sort
сортирует список.
toBuy.sort()
print(toBuy) # ['Bread', 'Cheese', 'Gum', 'Olive oil', 'Salad', 'Tomato', 'Vine']
Получить элемент можно с помощью сабскрипта из квадратных скобок.
print(toBuy[4]) # Salad
Чтобы создать пустой список используются пустые скобки или фукнция list
.
print(list() == []) # True
Создать список можно также из генератора списков.
listOfInt = (int(elem) for elem in ["1", "2", "3", "4", "5"])
for unit in listOfInt:
print(unit)
Кортеж
Кортежи похожи на списки, но при этом они неизменяемы. Отличие так же в том, что объявляется в круглых скобках.
toBuy = ("Cheese", "Vine", "Bread", "Tomato", "Olive oil", "Salad")
print(toBuy) # ('Cheese', 'Vine', 'Bread', 'Tomato', 'Olive oil', 'Salad')
print(toBuy[4]) # Olive oil
print(().count(toBuy)) # 0
Python распознает кортежи, даже если они не залючены в скобки.
tuple1 = 1, "Эби", True
print(tuple1)
Кортеж можно распаковать в несколько переменных.
age, name, is_a_girl = tuple1
print(name) # Эби
Чтобы получить кортеж с одним элементом нужно поставить после него запятую, иначе Python распознает просто скобки.
print(("Salad",)) # ('Salad',)
Range
Для цикла используется тип range
. Но он создает все элементы сразу, так что для тонких мест следует использовать xrange
, который создает поток.
for i in range(0, 1000000):
pass
Диапазон имеет методы index
, который возвращает индекс указанного элемента или возбуждает исключение ValueError, а также count
, который возвращает количество элементов с переданным значением.
rng = range(2, 20, 4)
try:
print(rng.index(1))
except ValueError:
print("Единицы нет")
print(rng.count(1)) # 0
Множество
Чтобы использовать математические операции над множествами используется класс set
.
Значения в множестве неупорядочены, но они не могут повторяться.
Для таких множеств определены операции & | и ^ -.
listing1 = [1, 2, 4, 6, 7]
listing2 = [3, 6, 9, 12]
print(set(listing1) & set(listing2)) # {6}
print(set(listing1) | set(listing2)) # {1, 2, 3, 4, 6, 7, 9, 12}
print(set(listing1) ^ set(listing2)) # {1, 2, 3, 4, 7, 9, 12}
Проверить вхождение ключа можно с помощью оператора in
.
print(2 in listing1) # True
print(3 in listing1) # False
Для добавления одного элемента используется метод add
, а для добавления списка метод update
.
Можно применять функции сравнения ==
равенство, <=
левое подмножество правого, < > >=.
Метод isdisjoint
проверяет, что пересечение множеств пусто.
Неизменяемое множество — frozenset
.
Словарь
Словарь — ассоциативный массив, указывается в фигурных скобках, ключ и значение через двоеточие.
dictionary = \
{
"Ключ 1": "Значение 1",
"Ключ 2": "Значение 2"
}
print(dictionary) # {'Ключ 1': 'Значение 1', 'Ключ 2': 'Значение 2'}
print(dictionary['Ключ 1']) # Значение 1
Для обхода в цикле с использованием ключей, необходимо указать ключи и значение через запятую с вызовом метода .items()
.
for key, value in dictionary.items():
print("{}: {}".format(key, value))
Чтобы создать пустой словарь используются пустые скобки или фукнция dict
.
print({} == dict()) # True
Наличие элемента проверяется с помощью оператора in.
print("Vasya" in {}) # False
Для получения списка ключей используется преобразование в список.
dst = {
"Key1": "Value1",
"Key2": "Value2",
}
print(list(dst)) # ['Key1', 'Key2']
Функия dict создает словарь из кортежа двух элементов. Статический метод dict.fromkeys
создаст словарь с ключами и значениями None.
Метод copy
копирует словарь, а не копирует ссылку при присвоении.
Метод get
поддерживает значение по-умолчанию.
Метод keys
возвращает все ключи.
Метод values
возвращает все значения.
Метод items
возвращает все ключи и значения в виде массива кортежей.
Метод popitem
удаляет и возвращает произвольный кортеж из ключа и значения.
Генераторы списков
Для создания списков, заполненных по более сложным формулам можно использовать генераторы — выражения, позволяющие заполнить список по формуле.
Создать список с одинаковыми элементами можно умножив последовательность с одним элементом на желаемую длину.
print([1] * 3) # [1, 1, 1]
Генератор списков имеет вид [выражение for переменная in последовательность]
.
Здесь обходится последовательность, к каждой переменной применяется значение и записывается в результирующую последовательность.
print([i ** 2 for i in range(1, 4)]) # [1, 4, 9]
После последовательности можно добавить ограничитель if
, который позволит добавить элемент только в случае выполнения условия.
print([ i ** 2 for i in range(1, 4) if i != 3]) # [ 1, 4]
Если разместить генератор списков внутри круглых скобок, то вернется итератор.
gen = (i ** 2 for i in range(1, 4) if i != 3)
for elem in gen:
print(elem)
В фигурных скобках будет создано множество.
print({i for i in [1, 2, 2, 3]}) # {1, 2, 3}
В фигурных скобках, когда выражение через двоеточие будет создан словарь.
print({ ord(str(i * 2)): i for i in [1, 2, 2, 3]}) # {50: 1, 52: 2, 54: 3}
ООП
Основы
Класс создается с помощью ключевого слова class
.
class Person:
pass
Класс тоже может иметь описание.
class Person:
"""Person template"""
pass
print(Person.__doc__) # Person template
Методы класса обязаны иметь в качестве первого аргумента слово self
. При этом передавать его не нужно, это автоматически сделает Python.
class Person:
def say(self, message):
print(message)
Person().say("Hi") # Hi
Создается новый экземпляр через вызов имени класса.
Self является указателем на экземпляр внутри класса.
Подобно функциям, классы можно задекорировать с помощью функций декораторов.
def echo_class_name(C):
print("Initialize class " + str(C))
return C
@echo_class_name
class A:
pass
A() # Initialize class <class '__main__.A'>
Конструктор и деструктор
За инициализацию отвечает метод __init__
. В нем мы можем присваивать значения необъявленным свойствам, таким образом объявляя их.
class Person:
def __init__(self, name):
self.name = name
mike = Person("Mike")
print(mike.name) # Mike
Деструктором является метод __del__
.
class Person:
population = 0
def __init__(self, name):
self.name = name
Person.population += 1
def __del__(self):
Person.population -= 1
Person("Mike")
jane = Person("Jane")
print(Person.population) # 2
del jane
print(Person.population) # 1
Методы класса и объекта
Статический метод можно создать с помощью декоратора @staticmethod или вызова одноименной функции в теле класса.
class Person:
"""Person template"""
population = 0
def __init__(self, name):
self.name = name
Person.population += 1
def __del__(self):
Person.population -= 1
def make_more():
Person.population += 1
make_more = staticmethod(make_more)
@staticmethod
def more_more():
Person.population += 2
Person.make_more()
print(Person.population) # 1
Person.more_more()
print(Person.population) # 3
Существует две области видимости для методов и свойств. Публичные — по-умолчанию и приватные — начинаются с двойного знака подчеркивания.
class Person:
"""Person template"""
def __init__(self, name, phone_number):
self.name = name
self.__phone = phone_number
def get_phone(self):
return self.__append7()
def __append7(self):
return "7" + self.__phone
mike = Person("Mike", "9114445566")
# print(mike.__phone) AttributeError: 'Person' object has no attribute '__phone'
# print(mike.__append7()) AttributeError: 'Person' object has no attribute '__append7'
Наследование
Для наследования указывается родительский класс в скобках после имени текущего класса.
class Human:
def __init__(self, age):
self.age = age
class Person(Human):
def __init__(self, name):
self.name = name
Human.__init__(self, 0)
mike = Person("Mike")
print(mike.age)
Поддерживается множественное наследование.
class Human:
def __init__(self, age):
self.age = age
class Man:
def __init__(self):
self.voice = "Min"
class Person(Human, Man):
def __init__(self, name):
self.name = name
Human.__init__(self, 0)
Man.__init__(self)
Поиск методов начинается с базового класса, переходя к родительским в порядке их объявления.
class Human:
def voice(self):
print("Human")
class Man:
def voice(self):
print("Man")
class Person(Human, Man):
pass
mike = Person()
mike.voice() # Human
Обратиться к родительскому классу можно с помощью метода super
, по имени родительского класса.
class ParentCls:
def run(self):
print("Parent")
class AnotherParentCls:
def run(self):
print("AnotherParent")
class Cls(ParentCls, AnotherParentCls):
def run(self):
super().run()
AnotherParentCls.run(self)
cls = Cls()
cls.run()
# Parent
# AnotherParent
Базовые классы хранятся в статическом свойстве __bases__
.
class Cls(ParentCls, AnotherParentCls):
def run(self):
print(Cls.__bases__) # (<class '__main__.ParentCls'>, <class '__main__.AnotherParentCls'>)
Цепочка наследования хранятся в статическом свойстве __mro__
. На основании множественного наследования используется механизм примесей mixin. Используется как трейты.
Специальные методы
__call__
— вызов объекта как вызов функции.__getattribute__
— аналог одноименной функции. Перехватывает обращение к атрибутам.__setattr__
— аналог одноименной функции. Перехватывает обращение к атрибутам.__delattr__
— аналог одноименной функции. Перехватывает обращение к атрибутам.__len__
— вызывается при вызове функции len на объекте или вместо bool, если она не определена.__bool__
— вызывается при вызове функции bool.__int__
— вызывается при вызове функции int.__float__
— вызывается при вызове функции float.__complex__
— вызывается при вызове функции complex.__round__
— вызывается при вызове функции round.__index__
— вызывается при вызове функций bin, hex, oct.__repr__
и__str__
— вызывается при вызове функций repr и str.__hash__
— используется, если класс участвует в качестве ключа словаря.__add__
— вызывается при сложении.__radd__
— вызывается при сложении, когда экземпляр справа.__iadd__
— вызывается при присваивании +=.__sub__
,__rsub__
,__isub__
— вызывается при операциях вычитания.__mul__
,__rmul__
,__imul__
— вызывается при операциях умножения.__truediv__
,__rtruediv__
,__itruediv__
— вызывается при операциях деления.__floordiv__
,__rfloordiv__
,__ifloordiv__
— вызывается при операциях деления с округлением.__mod__
,__rmod__
,__imod__
— вызывается при операции нахождения остатка от деления.__pow__
,__rpow__
,__ipow__
— вызывается при операции возведения в степень.__neg__
— унарный минус.__pos__
— унарный плюс.__abs__
— вызывается при вызове функции abs.__invert__
— двоичная инверсия ~.__and__
,__rand__
,__iand__
— двоичное И &.__or__
,__ror__
,__ior__
— двоичное ИЛИ &.__xor__
,__rxor__
,__ixor__
— двоичное исключающее ИЛИ ^.__lshift__
,__rlshift__
,__ilshift__
— сдвиг влево «.__rshift__
,__rrshift__
,__irshift__
— сдвиг вправо ».__eq__
— сравнение на равенство ==.__ne__
— сравнение на неравенство !=.__lt__
— сравнение на меньше <.__gt__
— сравнение на больше >.__le__
— сравнение на меньше или равно <=.__ge__
— сравнение на больше или равно >=.__contains__
— проверка на вхождение in.
Абстрактные методы
Единственный способ сделать метод абстрактным — это бросать в нем исключение.
Можно задекорировать метод и использовать аннотацию.
Это уже сделано в модуле abc
с помощью функции-декоратора abstractmethod
.
Доступ к свойствам
В конструкторе объявляются свойства экземпляра. А в классе переменные принадлежат всему классу (статические свойства).
class Person:
population = 0
def __init__(self, name):
self.name = name
Person.population += 1
print(Person.population) # 0
Person("Mike")
Person("Jane")
print(Person.population) # 2
Для доступа к атрибутам (свойствам) могут использоваться функции.
getattr
- получить атрибут объекта или значение по-умолчанию.
setattr
- установить значение для атрибута объекта, возможно несуществующего.
delattr
- удалить значение для атрибута объекта.
hasattr
- проверить атрибут объекта на существование.
class Cls:
def __init__(self):
self.prop = 1
obj = Cls()
print(getattr(obj, 'prop')) # 1
print(getattr(obj, 'prop2', 0)) # 0
setattr(obj, 'prop2', 1)
print(getattr(obj, 'prop2')) # 1
delattr(obj, 'prop')
print(getattr(obj, 'prop', 0)) # 0
print(hasattr(obj, 'prop')) # False
Можно объявить сеттер, геттер и удалитель одной функцией property
.
class Cls:
def __init__(self):
self.__secret_var = 0
def get_secret_var(self):
print("Getter")
return self.__secret_var
def set_secret_var(self, v):
print("Setter")
self.__secret_var = v
def del_secret_var(self):
print("Delete")
del self.__secret_var
var = property(get_secret_var, set_secret_var, del_secret_var, "Documentation")
cls = Cls()
cls.var = 10 # Setter
cls.var # Getter
del cls.var # Delete
Или заменить это все функциями-декораторами var_name.getter, var_name.setter и var_name.deleter.
class Cls:
def __init__(self):
self.__secret_var = 0
@property
def var(self):
print("Getter")
return self.__secret_var
@var.setter
def var(self, v):
print("Setter")
self.__secret_var = v
@var.deleter
def var(self):
print("Delete")
del self.__secret_var
cls = Cls()
cls.var = 10 # Setter
cls.var # Getter
del cls.var # Delete
Данные свойства можно объявить абстрактными.
Исключения
Обработка исключений производится с помощью оператора try-except-else
. Можно обработать любую ошибку, кроме синтаксической.
try:
pass
except EOFError:
print("EOF???")
else:
print("Исключения не произошло")
Блок else выполняется если ошибки не происходит.
Можно обработать несколько типов исключений сразу, перечислив их в скобках.
try:
pass
except (ValueError, NameError):
pass
Можно определить исключение в переменную с помощью оператора as
.
try:
pass
except (ValueError, NameError) as e:
print(e)
Чтобы создать собственный тип исключения, нужно отнаследоваться от класса Exception.
class MyException(Exception):
pass
Чтобы бросить исключение используется оператор raise
.
try:
raise MyException
except MyException:
print("MyException gotcha”)
Блок finally выполняется всегда.
try:
raise MyException
except MyException:
print("MyException gotcha")
finally:
print("Finally block")
Получить информацию об исключении можно с помощью функции exc_info
модуля sys
.
Для удобного чтения полученного кортежа можно воспользоваться модулем traceback
.
print(traceback.print_exception(sys.exc_info()))
Если в блоке except не указать тип исключения, то блок перехватывает все исключения.
Менеджеры контекста
Python поддерживает протокол менеджеров контекста. Протокол гарантирует выполнение завершающих действий.
Для работы с протоколом следует использовать инструкцию with-as
.
Формат:
with <Выражение> as <Переменная>, <Выражение> as <Переменная>:
{block}
В начале вычисляется выражение, которое должно возвращать объект с методами __enter__
и __exit__
.
__enter__
вызывается после создания объекта, возвращает значение, которое присваивается в переменную.- Потом вызывается блок внутри with.
- При возникновении исключения, вызывается
__exit__
с теми же аргументами, что возвращает функцияexc_info
модуля sys. Если исключение обработано, то возвращает True, иначе False и исключение передается вышестоящему обработчику. __exit__
вызывается в любом случае, только в случае успеха все аргументы равны None.
class Cls:
def __init__(self, value):
self.value = value
def __enter__(self):
return self.value
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exception")
self.value = None
return True
def run(self):
raise BaseException
def createCls(value):
return Cls(value)
with createCls(10) as value:
createCls(value).run() # Exception
Инструкция assert
бросает AssertionError
, если выражение справа не равно True.
try:
assert False
except AssertionError:
print("Error")
Итераторы, контейнеры и перечисления
Итераторы
Это классы, которые могут выступать как последовательности. Для того, чтобы определить итератор, необходимо определить в классе два метода.
__iter__
— говорит о том, что класс является итератором, должен вовращать сам экземпляр класса и выполнять все необходимые предустановки.__next__
— вызывается при каждой итерации, должен возвращать очередное значение из последовательности, пока не возникнет исключение StopIteration.
class Iter:
def __init__(self, max: int):
self.__current = 0
self.max = max
def __iter__(self):
return self
def __next__(self):
if (self.__current >= self.max):
raise StopIteration
self.__current += 1
return self.__current
for cur in Iter(10):
print(cur) # print from 1 to 10
Контейнеры
Классы, которые могут выступать как последовательности или отображения (словари).
__getitem__
— получение элемента по индексу или ключу (для отображений).__setitem__
— присваивание элемента по индексу или ключу (для отображений).__delitem__
— удаление элемента по индексу или ключу (для отображений).__contains__
— вызывается при проверке на существование значения или ключа (для отображений) с помощью in и not in.
class Container:
def __init__(self, content):
self.content = content
def __getitem__(self, index):
return self.content[index]
def __setitem__(self, key, value):
self.content.extend(value)
def __contains__(self, item):
return self.content.__contains__(item)
cont = Container(["A", "B", "C"])
print(cont[1]) # B
cont[4] = "D"
print(cont[3]) # D
print("E" in cont) # False
print("E" not in cont) # True
Перечисление
Чтобы создать перечисление (enumeration) с целыми величинами необходимо наследовать класс от IntEnum
из модуля enum
.
Чтобы создать перечисление (enumeration) со скалярными величинами необходимо наследовать класс от Enum
из модуля enum
.
Перечисления обязаны хранить атрибуты, названные по разному, но значения могут быть неуникальными.
Чтобы утвердить, что значения уникальны используется декоратор класса @unique
.
class PaymentType(enum.IntEnum):
VISA = 1
MASTER = 2
MAESTRO = 3
DINNERS = 4
AMERICAN_EXPRESS = 5
Для того, чтобы создать экземпляр необходимо либо передать идентификатор в конструктор, либо использовать одно из значений.
print(PaymentType(1))
print(PaymentType.VISA)
Это делается благодаря базовому классу EnumMeta, в котором объявлена логика.
Кроме того, можно создать экземпляр с помощью синтаксиса словарей.
print(PaymentType['VISA'])
Из типа перечисления можно создать список его значение, обернув в list.
print(list(PaymentType)) #[<PaymentType.VISA: 1>, <PaymentType.MASTER: 2>, <PaymentType.MAESTRO: 3>, <PaymentType.DINNERS: 4>, <PaymentType.AMERICAN_EXPRESS: 5>]
IntEnum можно использовать как число.
Получить имя можно с помощью свойства name. Оно совпадает с именем переменной.
print(PaymentType.VISA.name) # VISA
Получить значение с помощью value.
print(PaymentType.VISA.value) # 1
Некоторые модули
Модуль Math
pi
— возвращает число Пи.e
- значение числа Эйлера.- Есть функции
sin
,cos
,tan
,asin
,acos
,atan
.degress
— преобразует радианы в градусы.radians
— преобразует градусы в радианы. exp
- экспонента (e ** x).log
— логарифм числа по основанию.log10
— логарифм числа по основанию 10.log2
— логарифм числа по основанию 2.sqrt
— квадратный корень.ceil
— округление до большего.floor
— округление до меньшего.fmod
— остатотк от деления.fabs
— модуль.factorial
— факториал числа.fsum
- точная сумма переданных чисел.
Модуль random
random
— случайное число от 0 до 1.seed
— настройка генератора случайных чисел. Если первый параметр одинаковый, то при random число будет тоже.uniform
— число в диапазоне от и до.randint
— целое число в диапазоне от и до.randrange
— случайное число из последовательности. Аргументы как у range.choice
— случайное число из переданной последовательности. shuffle - перемешивает последовательность.sample
— возвращает список из указанного количества элементов переданной последовательности.
Модуль locale
Модуль используется для настройки локализации.
Функция setlocale
устанавливает локализацию для категории.
import locale
locale.setlocale(locale.LC_ALL, "ru_RU")
В качестве категории выступают константы.
- locale.LC_ALL
— все режимы.
- locale.LC_COLLATE
— сравнение строк.
- locale.LC_CTYPE
— перевод символов в нижний/верхний регистр.
- locale.LC_MONETARY
— отображение денежных единиц.
- locale.LC_NUMERIC
— форматирование чисел.
- locale.LC_TIME
— форматирование вывода даты и времени
Функция getlocale
получает текущую локализацию для режима.
print(locale.getlocale()) # ('ru_RU', 'UTF-8')
Настройки локали можно получить с помощью функции localeconv
.
Модуль hashlib
Модуль используется для хеширования строк.
Есть функции md5
, sha1
, sha224
, sha256
, sha384
и sha512
. Все они принимают последовательность байт.
print(hashlib.md5(b"password"))
Чтобы получить зашифрованную последовательность байт используются методы digest
и hexdigest
.
print(hashlib.md5(b"password").digest())
Передать последовательность можно с помощью метода update
.
hash = hashlib.sha256()
hash.update(b"password")
print(hash.hexdigest())
Для создания устойчивого к взлому пароля используется функция pbkdf2_hmac
.
Модуль itertools
Модуль содержит функции для работы с последовательностями.
count
— создает бесконечную, монотонно-изменяющуюся последовательность.
for elem in itertools.count(1, 2):
if elem > 1000:
break print(elem)
cycle
- бесконечно по кругу перебирает последовательность.repeat
— возвращает объект заданое количество раз.
for elem in itertools.repeat(1, 10):
print(elem)
combinations
— возвращает итератор с различными комбинациями элементов коллекции (как кортежи).
for comb in itertools.combinations("abcd", 3):
print(comb)
combinations_with_replacement
— возвращает итератор с различными комбинациями элементов коллекции (как кортежи), но здесь элемент может быть в кортеже с собой.
for comb in itertools.combinations_with_replacement("abcd", 3):
print(comb)
permutations
— аналог combinations.product
— кортеж из комбинации элементов одной или несколькоих последовательностей.filterfalse
— как функция filter, но ожидает значения false.dropwhile
— возвращает элементы, начиная с элемента, для которого функция вернет false.takewhile
— возвращает элементы, включая до элемента, для которого функция вернет false.compress
— фильтрует последовательность в соответствии с булевым значением из второй последовательности.islice
— возвращает итератор, для которого можно задать границы и шаг.startmap
— аналог map, но каждый элемент должен быть последовательностью.zip_longest
— аналог zip, но обходит все элементы, добавляя значение по-умолчанию.accumulate
— аналог reduce.chain
— принимает несколько последовательностей, при итерации поочередно возвращает их элементы.chain.from_iterable
— возвращает итератор последовательности, все элементы которой тоже являются последовательностью.
Модули для работы с датой и временем
Модуль time
time
— timestamp с 1.01.1970г.gmtime
— возвращает struct_time объект переданного timestamp или текущего времени, если параметр не передан.localtime
— возвращает struct_time в локальном времени.strftime
— принимает формат и struct_time и возвращает строковое представление.strptime
— разбирает строку в указанном формате и возвращает объект struct_time.asctime
— возвращает сроку в формате ascii, принимает struct_time.ctime
— возвращает сроку в формате ascii, принимает timestamp.sleep
— используется для задержки скрипта (использует секунды).mktime
— принимает struct_time, а возвращает timestamp.
print(time.time()) # 1472475009.691453
print(time.gmtime()) # time.struct_time(tm_year=2016, tm_mon=8, tm_mday=29, tm_hour=12, tm_min=30, tm_sec=10, tm_wday=0, tm_yday=242, tm_isdst=0)
print(time.localtime()) # time.struct_time(tm_year=2016, tm_mon=8, tm_mday=29, tm_hour=12, tm_min=30, tm_sec=10, tm_wday=0, tm_yday=242, tm_isdst=0)
print(time.mktime(time.localtime())) # 1472475009.0
Объект struct_time
имеет свойства.
tm_year
— годtm_mon
— месяцtm_mday
— день месяцаtm_hour
— часtm_min
— минутыtm_sec
— секундыtm_wday
— день недели (число)tm_yday
— день годаtm_isdst
— флаг коррекции летнего времени
Модуль datetime
Модуль позволяет оперировать датой и временем.
timedelta
— класс, дата в виде количества дней, секунд и микросекунд. Экземпляр можно складывать с date и datetime.
print(timedelta(0, 10)) # 0:00:10
tenSeconds = timedelta(0, 10)
print(tenSeconds.days) # 0
print(tenSeconds.seconds) # 10
print(tenSeconds.microseconds) # 0
Над классом можно проводить арифметические операции + - / // : * и получать абсолютное значение с помощью abs
.
Можно использовать операторы сравнения.
tenSeconds = timedelta(0, 10)
minTenSeconds = timedelta(0, -10)
print(tenSeconds - minTenSeconds) # 20 sec
date
— класс, представление даты.
Конструктор принимает год, месяц и день. Статический метод today
возвращает текущую дату.
print(date.today()) # 2016-08-29
Статический метод fromtimestamp
возвращает дату для timestamp.
print(date.fromtimestamp(sum(i for i in range(1, 50000)))) # 2009-08-11
Статический метод fromordinal
возвращает дату, соответствующую количеству дней с первого года.
print(date.fromordinal(736150)) # 2016-07-05
print(date.today() + timedelta(1)) # Yesterday
Есть методы replace
, strftime
, isotime
, ctime
, timetuple
, toordinal
, weekday
, isoweekday
, isocalendar
.
time
— класс, представление времени.
Коструктор принимает час, минута, секунда, микросекунда, tzinfo.
datetime
— класс, представление даты и времени.
print(time(12, 23, 2, 189, timezone(timedelta(0, 3600)))) # 12:23:02.000189+01:00
Есть методы now, utcnow, fromtimestamp, utcfromtimestamp, fromordinal, combine, strptime, date, time, timetz, timestamp, replace, timetuple, utctimetuple, toordinal, weekday, isoweekday, isoformat, ctime, strftime.
tzinfo
— абстрактный класс, отвечает за временную зону.
Модуль calendar
Модуль формирует календарь в определенном виде.
Calendar
— базовый класс, который принимает в качестве аргумента номер первого дня недели.
(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)
TextCalendar
— выводит календать в виде текста.
LocaleTextCalendar
— выводит календать в виде текста с учетом локали.
Имеют методы:
formatmonth
— возвращает указанный месяц.
import calendar
cal = calendar.TextCalendar(calendar.MONDAY) print(cal.formatmonth(2016, 9))
# September 2016
# Mo Tu We Th Fr Sa Su # 1234 # 5 6 7 8 9 10 11 # 12 13 14 15 16 17 18 # 19 20 21 22 23 24 25 # 26 27 28 29 30
prmonth
— выводит указанный месяц.formatyear
— возвращает указанный год.pryear
— выводит указанный год.HTMLCalendar
— выводит календать в виде HTML.LocaleHTMLCalendar
— выводит календать в виде HTML с учетом локали.
Дополнительно имеют метод formatyearpage
.
Модуль timeit
Модуль используется для измерения времени выполнения программы или кода.
Измерения проводятся с помощью класса Timer.
В конструктор он принимает код, который будет исполнятся в качестве строки, код, который будт выполнен перед запуском таймера и необязательную функцию-таймер.
Получить время выполнения можно с помощью метода timeit, который принимает количество повторений.
from timeit import *
timer = Timer("""
[i for i in range(1, 9999999)]
""")
print(timer.timeit(5)) # 3.3326380960061215
Метод repeat
запускает метод timeit указанное количество раз и возвращает результат.
Работа с файловой системой
Работа с файлами
open
— открывает файл.- Первый аргумент принимает путь к файлу. Поддерживаются относительные и абсолютные пути. Слэши обрабатываются в соответствие с os.path.sep.
- Второй параметр необязателен — mode. Он задает режим открытия.
r
— только чтение (по-умолчанию). После открытия указатель в начале файла. Если файл не существует, возбуждается FileNotFoundError.r+
— чтение и запись. Указатель в начале файла. FileNotFoundError.w
— только запись. Указатель в начале файла. Если файла нет, то он создается, иначе перезаписывается.w+
— чтение и запись. Указатель в начале файла. Если файла нет, то он создается, иначе перезаписывается.a
— только запись. Указатель в конце файла. Если файла нет, то он создается.a+
— чтение и запись. Указатель в конце файла. Если файла нет, то он создается.x
— создание файла для записи. Если есть, то FileExistsError.x+
— создание файла для записи и чтения. Если есть, то FileExistsError.b
— файл будет открыт в бинарном режиме. Методы будут принимать и возвращать объекты типа bytes.t
— файл будет открыт в бинарном режиме. Методы будут принимать и возвращать объекты типа str. По-умолчанию.
- При записи данных, информация записывается в буфер. Из буфера в файл данные будут записаны только после вызова метода
flush
или после закрытия файла. Третьим аргументомbuffering
можно указать размер буфера. Если будет 0, то данные в файл будут записаны сразу (только для бинарного режима).- Если будет 1, то данные в файл будут записаны построчно (только для тесктового режима).
- Четвертым аргументом encoding можно указать кодировку.
- Пятым аргументом error можно указать уровень обработки ошибок.
strict
— при ошибке возбуждается исключение (по-умолчанию).replace
— неизвестный символ заменяется символом вопроса или символом с кодом \ufffd.ignore
— неизвестный символ будет проигнорирован.xmlcharrefreplace
— неизвестный символ заменяется последовательностью &#xxxx;.backslashreplace
— неизвестный символ заменяется последовательностью \uxxxx;.
- Шестым аргументом
newline
задается режим обработки конца строк.None
— выполняется стандартная обрабока (для Windows при чтении \r\n преобразуется в \n, при записи наоборот).“”
— пустая строка. Обработка не осуществляется.“<symbol>”
— указанный символ считается концом строки.
После открытия файла функция open возвращает объект-дескриптор файла.
- Метод
close
— закрывает файл. - Метод
write
— записывает переданную последовательность (str или bytes) в файл. - Метод
writelines
— записывает переданную последовательность (str или bytes) в файл. - Метод
writable
— проверка возможности записи. - Метод
read
— чтение данных. Можно передать количество считываемых данных. - Метод
readline
— считывает из файла одну строку при каждом вызове. - Метод
readlines
— считывает из файла все строки в список. - Метод
__next__
— считывает из файла одну строку при каждом вызове. - Метод
flush
— принудительно записывает данные в файл. - Метод
fileno
— возвращает целочисленный дескриптор файла. 0 — stdin, 1 — stdout, 2 — stderr. - Метод
truncate
— обрезает файл до указанного количества символов или байт (для бинарного режима). - Метод
tell
— возвращает позицию указателя относительно начала файла. - Метод
seek
— устанавливает позицию, имеющую смещение (первый аргумент) относительно позиции (второй). Из модуля io доступны позиции:SEEK_SET
— начало файлаSEEK_CUR
— текущая позицияSEEK_END
— конец файла.
- Метод
seekable
— проверка на возможность перемещения указателя.
Помимо методов есть некоторые атрибуты.
name
— имя файлаmode
— режим открытияclosed
— True, есть файл закрытencoding
— кодировкаbuffer
— доступ к буферу. Можно, например, записать в буфер
sources_dir = 'sources'
file = open(sources_dir + "/test", "w+"); file.write("Hello")
file.close()
Модуль os
Модуль содержит низкоуровневые операции для работы с файлами.
Функциональность зависит от операционной системы.
Получить название можно из атрибута name.
import os
print(os.name)
Функция open
открывает файл:
- Путь к файлу.
- Режим открытия, можно комбинировать несколько через бинарное ИЛИ.
os.O_RDONLY
— чтение.os.O_WRONLY
— запись.os.O_RDWR
— чтение и запись.os.O_APPEND
— добавление в конец.os.O_CREAT
— создать файл, если он не существует.os.O_EXCL
— говорит, что изначально файл не должен существовать.os.O_TEMPORARY
— файл будет удален после закрытия.os.O_SHORT_LIVED
— что и os.O_TEMPORARY, но будет храниться в оперативной памяти.os.O_TRUNC
— очистить содержимое.os.O_BINARY
— бинарный режим.os.O_TEXT
— текстовый режим.
mode
— восьмиричное число от 0o000 до 0o777.
- Режим открытия, можно комбинировать несколько через бинарное ИЛИ.
Функция read
читает из файла указанное число байт.
Функция write
пишет из файл последовательность байт.
Функция close
закрывает файл.
Функция lseek
устанавливает указатель в позицию, возвращает новую позицию.
Функция dup
возвращает дубликат файлового дескриптора.
Функция fdopen
возвращает файл по дескриптору.
Класс StringIO
позволяет работать со строкой как с файловым объектом. Все операции хранятся в оперативной памяти.
Методы подобны методам файла, имеется метод getvalue
, который возвращает значение.
Для аналогичной работы с байтами используется класс BytesIO
.
Функция getcwd
возвращает текущий каталог (каталог, где находится файл).
print(os.getcwd()) # /Users/pavel/personal/python/Steps
Функция chdir
— переходит в каталог.
os.chdir('/tmp')
print(os.getcwd()) # /private/tmp
Функция mkdir
— создает каталог с правами доступа, указанными во втором аргументе с помощью восьмиричного значения.
Функция rmdir
— удаляет пустой каталог.
Функция listdir
— возвращает список файлов в каталоге.
Чтобы использовать специальные символы *, ? и [] используется функция glob из модуля glob.
Функция walk
— возвращает итератор файлов в каталоге (может рекурсивно).
Чтобы удалить непустую папку используется функция rmtree
из модуля shutil
.
Функция normcase
— преобразует переданный путь в тот вид, в котором используется в системе.
Для определения прав используется функция access
, на принимает путь и режим. Возвращает True, если проверка успешна, иначе False.
- os.F_OK
— проверка наличия.
- os.R_OK
— проверка на права чтения.
- os.W_OK
— проверка на права записи.
- os.X_OK
— проверка на исполняемость.
Права можно изменить с помощью функции chmod
. Она принимает путь и восьмиричные права.
Модуль shutil
имеет методы для манипулирования файлами.
Функция copyfile
— копирует файл.
Функция copy
— копирует файл вместе с правами доступа. Функция copy2 — копирует файл вместе с метаданными. Функция move — перемещает файл.
Функция rename
— переименовывает файл.
Функции remove
и unlink
— удаляет файл.
Модуль os.path также имеет методы для манипулирования файлами.
Функция exists
— проверка на существование.
Функция getsize
— размер в байт.
Функция getatime
— время последнего доступа, возвращает timestamp в секундах.
Функция getctime
— время создания, возвращает timestamp в секундах.
Функция getmtime
— время последнего изменения, возвращает timestamp в секундах.
Функция utime
— обновить время последнего доступа и изменения, возвращает timestamp в секундах.
Функция abspath
— вернет абсолютный путь.
Функция isabs
— проверка, что путь — абсолютный.
Функция basename
— вернет имя файла без пути до него.
Функция dirname
— вернет путь до файла.
Функция split
— вернет кортеж из пути и имени файла.
Функция splitdrive
— вернет кортеж из пути до файла с именем и диска, на котором он лежит.
Функция splittext
— вернет кортеж из имени файла и его расширения.
Функция join
— объединяет в путь.
Функция isdir
— проверяет, что строка ведет на каталог.
Функция isfile
— проверяет, что строка ведет на файл.
Функция islink
— проверяет, что строка ведет на ссылку.
Ввод и вывод
Функция print
напрямую поддерживает перенаправление вывода с помощью аргумента f.
Чтобы перенаправить ввод и вывод используются атрибуты модуля sys stdout, stdin, stderr.
import sys
logfile = './sources/log'
file = open(logfile, "a+");
sys.stderr = file
raise AssertionError
Чтобы проверить, ссылается ли на стандартный ввод на терминал, применяется метод stdin.isatty
.
Сохранение объектов
Сохранить объекты в файл могут модули pickle
и shelve
.
pickle.dump
— сохраняет объект (предустановленные в Python) в файл, открытый в бинарном режиме.
file = open('./sources/dump', "w+b")
pickle.dump([1, 2, 3], file)
pickle.load
— загружает объект (предустановленные в Python) из файла, открытого в бинарном режиме.
pickle.dumps
— преобразует объект строку.
pickle.loads
— преобразует строку, созданную с помощью pickle.dumps в объект.
class Cls:
def __init__(self):
self.name = "Вася"
file = open('./sources/dump', "w+b")
pickle.dump(pickle.dumps(Cls()), file)
file.flush()
print(pickle.loads(pickle.load(open('./sources/dump', "r+b"))))
Тоже самое делает объект типа Pickler
методами dump
, load
, dumps
, loads
.
shelve.open
— открывает файл для хранения объектов. Возвращается отображение с объектами DbfilenameShelf
. Можно указать режим открытия.
r
- чтение.w
- чтение и запись.c
- если файл не существует, то будет создан (по- умолчанию).n
- если файл существует, то будет перезаписан.
shelve.DbfilenameShelf.close
— закрывает файл.
shelve.DbfilenameShelf.keys
— получить ключи.
shelve.DbfilenameShelf.values
— получить значения.
shelve.DbfilenameShelf.items
— возвращает итератор с кортежем из ключа и значения.
shelve.DbfilenameShelf.get
— получить значение по ключу или по-умолчанию.
shelve.DbfilenameShelf.setdefault
— получить значение по ключу или установить.
shelve.DbfilenameShelf.pop
— удаляет элемент и возвращает его.
shelve.DbfilenameShelf.popitem
— удаляет произвольный элемент и возвращает кортеж из ключа и значения.
shelve.DbfilenameShelf.clear
— удаляет все элементы.
shelve.DbfilenameShelf.update
— обновляет файл.
import shelve
db = shelve.open("./sources/shelve")
db["first"] = ["one", "two", "three"]
db["second"] = {
"Key1": "Value1"
}
db.update()
for key, value in db.items():
print(str(key) + ": " + str(value))
# second: {'Key1': 'Value1'}
# first: ['one', 'two', 'three']
Работа с SQLite
DB-API
Работать с базой данных SQLite можно с помощью модуля sqlite3
. Чтобы писать модули для взаимодействия с БД необходимо придерживаться DB-API.
Модуль sqlite имеет полезныем атрибуты apilevel (версия DB- API), sqlite_version или sqlite_version_info (версия модуля).
Последовательность работы с базой данных согласно DB-API 2.0:
- Подлючение производится с помощью функции
connect
. Она должна возвращать объект соединения. - Создается объект-курсор.
- Выполняются запросы, обрабатываются результаты.
- Перед первым запросом запускается транзакция.
- Завершается транзакция.
- Закрывается объект-курсор.
- Закрывается соединение.
С помощью функции set_trace_callback
можно выполнить трассировку. Она принимает ссылку на функцию, которая принимать строку с SQL командой.
connection.set_trace_callback(lambda req: print(req))
Создание и открытие БД
Для создания и открытия служит функция connect, первым аргументом будет путь до базы данных.
import sqlite3
sources_dir = "./sources/"
connection = sqlite3.connect(sources_dir + 'python.db')
Можно указать значение memory:
, тогда база будет создана в оперативной памяти.
Чтобы передать параметры при открытии используется синтаксис, как в GET запросе.
- С помощью аргумента
mode
можно указать режим доступа.ro
— только чтениеrw
— чтение и записьrwc
— чтение, запись и создание БД.memory
— аналог :memory:.
- С помощью аргумента
immutable
отключаются все механизм транзакций, остается исключительно чтение.
Если база не существует, то она будет создана. Базу всегда нужно закрывать командой close.
connection.close()
Выполнение запросов
Согласно DB-API необходимо создать объект курсор, а все запросы пускать через него.
Создать объект курсор можно с помощью метода cursor объекта-соединения.
cursor = connection.cursor()
Чтобы выполнить несколько запросов, применяется метод executescript
объекта-курсора.
По окончанию автоматически делает commit.
cursor.executescript("""
create table if not exists product (
id integer primary key autoincrement,
name varchar(128) not null,
price real default 0
);
insert into product(name, price)
values ("Raspberry", 306.0), ("Watermelon", 11.2); """)
Чтобы выполнить один запрос, но при этом использовать биндинг применяется метод execute
объекта-курсора.
Автоматически commit не делает.
Первым параметром передается запрос.
Все значения, которые нужно забиндить указываются как ?
, если второй аргумент будет кортежем.
Указываются каr :<key>
, если это будет словарь.
import sqlite3
sources_dir = "./sources/"
connection = sqlite3.connect(sources_dir + 'python.db')
cursor = connection.cursor()
cursor.execute("""
insert into product(name, price) values (?, ?); """, ("Apple", 5.89))
cursor.execute("""
insert into product(name, price) values (:name, :price); """, {"name": "Orange", "price": 7.66})
connection.commit()
cursor.close()
connection.close()
Чтобы завершить транзакцию нужно вызвать commit
у объекта соединения.
Чтобы забиндить множественные параметры используется метод executemany
объекта-курсора.
Автоматически commit не делает.
connection = sqlite3.connect(sources_dir + 'python.db')
cursor = connection.cursor()
cursor.executemany("insert into product (name, price) values (?, ?);", [
("Lemon", 5.67),
("Grapefruit", 4.44)
])
connection.commit()
cursor.close()
connection.close()
Объект соединения также имеет методы executescript
, execute
и executemany
, но эти методы не входят в DB-API.
Объект-курсор имеет атрибуты lastrowid
(индекс вставленной последней записи), rowcount (количество добавленных или удаленных методов), description (содержит кортеж кортежей с именем поля).
Обработка результата запроса
Метод fetchone
при каждом вызове возвращает одну запись из результат запроса в виде кортежа и передвигает указатель на следующую запись.
cursor.execute("select * from product;")
print(cursor.fetchone()) # (35, 'Raspberry', 306.0)
Сам курсор является итератором, так что результаты можно обойти с помощью цикла.
for product in cursor:
print(product)
Метод fetchmany
возвращает переданное количество записей (по-умолчанию равно cursor.arraysize
).
print(cursor.fetchmany(3)) # [(35, 'Raspberry', 306.0), (36, 'Watermelon', 11.2), (37, 'Apple', 5.89)]
Метод fetchall
возвращает список всех полученных записей.
Объект-курсор имеет свойство row_factory
. Этому свойству можно задать функцию обработчик, которая принимает объект-курсор первым аргументом и запись вторым.
import sqlite3
class Connection:
def __init__(self, dbname):
self.__connection = sqlite3.connect(dbname)
self.cursor = self.__connection.cursor()
self.cursor.row_factory = lambda cursor, line: Product(line[0], line[1], line[2])
def execute(self, sql, params=()):
self.cursor.execute(sql, params)
self.__connection.commit()
return self.cursor.fetchall()
class Product:
def __init__(self, id, name, price):
self.id = id
self.name = name
self.price = price
def calculate(self, count):
return self.price * int(count)
product = orm.product.Connection(sources_dir + 'python.db')
for product in product.execute("select * from product;"):
print(product.calculate(10))
Атрибуту row_factory также можно присвоить ссылку на объект типа Row
.
Объект типа Row поддерживает итерации, доступ по индексу и метод keys, который возвращает список с названиями полей.
sources_dir = "./sources/"
connection = sqlite3.connect(sources_dir + 'python.db')
cursor = connection.cursor()
cursor.row_factory = sqlite3.Row
cursor.execute("select * from product")
rows = cursor.fetchall()
print(len(rows)) # 20 (elements)
for row in rows:
print(row[0]) # first db field
print(row['naMe']) # 'name' db field (ignore case)
print(row.keys()) # ['id', 'name', 'price'] field names
cursor.close()
connection.close()
Управление транзакциями
Управлять транзакциями можно с помощью параметра isolation_level
функции connect. DEFERRED, IMMEDIATE, EXCLUSIVE — запустит транзакцию с соответствующим урованем.
None — транзакция запущена не будет.
Откатить изменения транзакции можно с помощью метода rollback
объекта-соединения.
Свойство класса-соединения in_transaction
передает информацию о том, осуществляется ли сейчас транзакция.
Пользовательские функции
С помощью метода create_collation
объекта-соединения можно создать пользовательскую функцию сортировки.
Функция должна принимать две строки, возвращать -1, если первая больше, 0 при равенстве и 1, если больше правая.
Метод create_collation принимает первым аргументом название в SQL, вторым ссылку на функцию.
import sqlite3 sources_dir = "./sources/"
connection = sqlite3.connect(sources_dir + 'python.db')
cursor = connection.cursor()
def checktype(func):
"""
Check types in annotation, if annotion is None, then skipped
:param func: function :return: function
"""
def inner(*args, **kwargs):
if not kwargs:
"Nothing to check. Use named arguments"
for name, argtype in func.__annotations__.items():
if name in kwargs:
checkarg(kwargs[name],argtype)
return func(*args, **kwargs)
def checkarg(arg, argtype):
assert type(arg) == argtype
return inner
@checktype
def sqlen(l: str, r: str):
if len(l) > len(r):
return -1
elif len(r) > len(l):
return 1
return 0
connection.create_collation("sqlen", sqlen)
cursor.execute("select * from product order by name collate sqlen")
rows = cursor.fetchall()
for row in rows:
print(row)
"""
(36, 'Watermelon', 11.2)
(40, 'Grapefruit', 4.44)
(42, 'Grapefruit', 4.44)
(44, 'Grapefruit', 4.44)
(46, 'Grapefruit', 4.44)
(48, 'Grapefruit', 4.44)
(50, 'Grapefruit', 4.44)
(52, 'Grapefruit', 4.44)
(54, 'Grapefruit', 4.44)
(35, 'Raspberry', 306.0)
(55, 'Помидор', 14.55)
(38, 'Orange', 7.66)
(37, 'Apple', 5.89)
(39, 'Lemon', 5.67)
(41, 'Lemon', 5.67)
(43, 'Lemon', 5.67)
(45, 'Lemon', 5.67)
(47, 'Lemon', 5.67)
(49, 'Lemon', 5.67)
(51, 'Lemon', 5.67)
(53, 'Lemon', 5.67)
"""
cursor.close()
connection.close()
С помощью метода create_function
объекта-соединения можно создать пользовательскую функцию.
Она принимает название функции, количество параметров и ссылку на функцию.
connection = sqlite3.connect(sources_dir + 'python.db')
cursor = connection.cursor()
def ten(a, b):
if a > b:
return 10
return -10
connection.create_function('tens', 2, ten)
cursor.execute("SELECT tens(1, 2);")
print(cursor.fetchone()) # -10
cursor.close()
connection.close()
С помощью метода create_aggregate
объекта-соединения можно создать пользовательскую агрегатную функцию.
Она принимает имя функции, количество параметров и сслыку на класс.
Класс должен реализовывать два метода step
и finalize
.
step
— вызывается для каждой обрабатываемой записи, ему передаются параметры, колическтво которых задано.finalize
— возвращает результат выполнения
class SQLSum:
def __init__(self):
self.result = None
def step(self, arg):
if self.result is None:
self.result = arg
return
self.result += arg
def finalize(self):
return self.result
connection.create_aggregate('mysum', 1, SQLSum)
cursor.execute("select mysum(name) from product;")
Преобразование типов
Каждому типу SQLite соответствует тип Python.
NULL
- NoneINTEGER
— intREAL
— floatTEXT
— str-
BLOB
— bytesЕсли необходимо сохранить в таблице данные, которые не поддеживаются SQLite, следует преобразовать тип самостоятельно.
Для этого с помощью функции register_adapter
необходимо зарегистрировать пользовательскую функцию, которая будет вызываться при попытке вставке объекта в SQL.
Эта функция принимает в качестве аргументов тип данных и ссылку на функцию.
class Product:
def __init__(self, name):
self.name = name
sqlite3.register_adapter(Product, lambda p: p.name)
cursor.execute("insert into product (name, price) VALUES (?, ?);", (Product("Тыква"), 12.33))
Чтобы восстановить объект из записи, используется функция register_converter
.
Первым аргументом является тип, используемый в SQLite, а вторым функция преобразования.
По умолчанию тип данных определяется при создании таблицы в параметре тип.
cursor.execute("""
create table if not exists new_product(
id integer primary key autoincrement,
product product not null
);
""")
Определение типа данных задается при создании подключения с помощью аргумента detect_types
.
PARSE_COLNAMES
— смотри на имена полей, если указано как <real_field> as ‘<alias> [<required_type>]'
.
connection = sqlite3.connect(sources_dir + 'python.db', detect_types=sqlite3.PARSE_COLNAMES)
cursor.execute("select name as 'c [product]' from product;")
PARSE_DECLTYPES
— по-умолчанию, с помощью имени типа при создании таблицы.
Для даты и времени из модуля datetime уже предусмотрены преобразователи данных.
cursor.execute("""
create table product(
id integer primary key autoincrement,
name varying character (32) not null,
created_at datetime not null
);
""")
cursor.execute("insert into product(name, created_at) values (?, ?)", ("Watermelon", datetime.datetime.now()))
print(product) # (1, 'Watermelon', '2016-09-02 18:58:33.569139')
Разработка с серверными БД
Основные отличия
- Используются специальные модули, которые реализуют DB-API.
- При подключении указываются специальные параметры.
Взаимодействие с интернетом
URL
Манипулировать URL адресом можно с помощью модуля urllib.parse
.
- URL —
:// : / ; ? # . - FTP —
:// : @
Разобрать URL можно с помощью функции urlparse
.
print(urllib.parse.urlparse("http://ya.ru?a=1&b=4")) # ParseResult(scheme='http', netloc='ya.ru', path='', params='', query='a=1&b=4', fragment='')
Вторым указывается протокол, который дут использован, есть в URL его нет.
Метод geturl
объекта ParseResult
возвращает строку с исходным URL.
print(urllib.parse.urlparse("http://ya.ru?a=1&b=4").geturl()) # http://ya.ru?a=1&b=4
Собрать URL из кортежа можно с помощью функции urlunoparse
.
Вместо urlparse
можно воспользоваться функцией urlsplit
. Помимо всего прочего, она не выделяет параметры.
print(urllib.parse.urlsplit("http://ya.ru?a=1&b=4")) # SplitResult(scheme='http', netloc='ya.ru', path='', query='a=1&b=4', fragment='')
Чтобы декодировать строку запроса нужно воспользоваться функцией parse_qs
.
Она принимает строку запроса, параметр keep_blank_values указать, что пустые значения тоже возвращать.
url = "param2=¶m1=%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%801"
print(parse_qs(url)) # {'param1': ['Параметр1']}
print(parse_qs(url, keep_blank_values=1)) # {'param1': ['Параметр1'], 'param2': ['']}
Функция parse_qsl делает тоже самое, но возвращает не словарь, список кортежей пар.
print(parse_qsl(url, keep_blank_values=1)) # [('param2', ''), ('param1', 'Параметр1')]
Функция urlencode делает обратную операцию.
print(urlencode({"param1": "Параметр1", "param2": ""})) # param1=%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%801¶m 2=
Если поставить параметр doseq
в True, то для одного параметра можно будет добавить несколько значений.
print(
urlencode(
[("param1", ["Знач1", "Знач1"])],
doseq=1
)
) # param1=%D0%97%D0%BD%D0%B0%D1%871¶m1=%D0%97%D0%BD%D0%B0%D1% 871
Функция quote
кодирует строку.
Функция quote_pluse
кодирует строку, но ставит + для пробела.
print(quote("Строка 1")) # %D0%A1%D1%82%D1%80%D0%BE%D0%BA%D0%B0%201
print(quote_plus("Строка 1")) # %D0%A1%D1%82%D1%80%D0%BE%D0%BA%D0%B0+1
Функция quote_from_bytes
кодирует последовательность байт. Функция unquote
, unquote_plus
, unquote_to_bytes
декодирует строку.
Преобразовать относительную ссылку в абсолютную можно с помощью функции urljoin
.
Она преобразует ссылку относительно текущего контекста подобно файловой системе, если бы хост был бы корневым каталогом.
url = "http://yandex.ru/news/bad.html"
print(urljoin(url, "good.html")) # http://yandex.ru/news/good.html
print(urljoin(url, "/good.html")) # http://yandex.ru/good.html
print(urljoin(url, "../search/good.html")) # http://yandex.ru/search/good.html
print(urljoin(url, "very/bad.html")) # http://yandex.ru/news/very/bad.html
HTML
Чтобы экранировать специальные символы HTML используется функция escape
из модуля xml.sax.saxutils
. Дополнительно ей можно передать словарь, по которому будут производится замены.
print(escape("<&>")) # <&>
Обратная ей функция — unescape
.
Обмен данными
Модуль http.client
позволяет взаимодействовать по HTTP(s) методами GET, HEAD и POST.
За создание соединения ответственен класс HTTPConnection
. Его конструктор принимает хост, порт и таймаут.
connection = HTTPConnection("http://suggest-maps.yandex.ru/")
Закрыть соединение можно с помощью метода close
.
Метод request
отправляет запрос. Он принимает метод, путь, тело запроса и заголовки,
connection.request(
'GET',
'/suggest-geo?' + urlencode(
{
'lang': 'ru-RU',
'search_type': 'all', 'fullpath': 1,
'v': 5,
'part': 'Россия, Москва, улица Солженицына',
}
)
)
Метод getresponse
возвращет результат в виде объекта типа HTTPResponse.
Метод read
возвращает тело ответа.
Метод getheader
возвращает запрошенный заголовок ответа или значение по-умолчанию.
Метод getheaders
возвращает все заголовки ответа. Свойство status статус в виде числа.
Свойство reason
статус в виде текста.
Свойство version
содержит версию протокола HTTP.
connection = HTTPConnection("suggest-maps.yandex.ru", 80)
connection.request(
'GET',
'/suggest-geo?' + urlencode(
{
'lang': 'ru-RU',
'search_type': 'all',
'fullpath': "1",
'v': "5",
'_': 2315123,
'part': 'Россия, Москва, улица Солженицына',
}
)
)
response = connection.getresponse()
print(response.read())
Свойство msg
содержит объект сообщение.
Модуль urllib.request также предоставляет методы для работы с интернет.
Для выполнения запроса используется функция urlopen
. Она принимает Url, данные, таймаут. В качестве URL может выступать объект Request. Если данные переданы, то это будет POST, иначе GET. Функция возвращает объект типа HTTPRequest.
from urllib.request import *
result = urlopen(
Request(
"http://suggest-maps.yandex.ru/suggest-geo?" + urlencode(
{
'lang': 'ru-RU',
'search_type': 'all',
'fullpath': "1",
'v': "5",
'_': 2315123,
'part': 'Калинин',
}
)
)
)
print(result) # <http.client.HTTPResponse object at 0x1031569e8>
HTTPResponse
имеет метод read
, который возвращает ответ.
print(result.read().decode("utf-8"))
Метод readline
считывает одну строку на каждый вызов.
Метод readlines
возвращает список.
HTTPResponse является итератором.
Метод info
возвращает список заголовков.
Свойство code
содержит код ответа.
Свойство msg
содержит текстовый код ответа.