Поля и типы данных¶
Типы данных¶
Прежде чем мы продолжим модифицировать наш класс Points
,
углубимся в техническую часть и разберёмся,
как Sqlite3 API хранит данные.
Стандартные типы данных¶
К стандартным типам данных относятся str
и int
,
которые мы уже использовали при описании полей в таблице Points
.
Этих всем известных типов данных нет в синтаксисе Sqlite,
поэтому API переводит привычный для питонистов str
в привычный для Sqlite TEXT
, а int
в INTEGER
и обратно соответственно.
Пользовательские типы данных¶
Известно, что в Sqlite есть 4 основных типа данных,
это: INTEGER
, TEXT
, BLOB
и REAL
.
Поэтому, чтобы хранить например списки и словари,
были реализованы пользовательские типы данных
.
Они находятся в файле tupes.py
.
Пример использования пользовательских типов данных
from sqlite3_api.Table import Table
from sqlite3_api.field_types import List
class Students(Table):
first_name: str
last_name: str
age: int
marks: List
В данном случае поле marks
будет представлено в виде списка,
а так же будет иметь все свойства и
методы стандартного для питона типа данных list
Таблица типов данных¶
Тип данных | str | int | List | Dict |
---|---|---|---|---|
Расшифровка | TEXT | INTEGER | list | dict |
Создание пользовательских типов данных¶
Умение создавать пользовательские типы данных — полезное умение, так как пользовательские типы данных значительно облегчают хранение и использование данных, тип которых не поддерживает Sqlite.
Давайте научимся на примере.
Создадим тип данных, который будет хранить координаты на двумерной плоскости.
from sqlite3_api.field_types import CustomType
class Position(CustomType):
def __init__(self, x: float, y: float):
self.x = x
self.y = y
@staticmethod
def adapter(obj) -> bytes:
return ('%f;%f' % (obj.x, obj.y)).encode('ascii')
def converter(self, obj: bytes):
return Position(*map(float, obj.split(b";")))
Разберёмся как мы это сделали.
Импортируем инструмент для создания своих типов данных.
from sqlite3_api.field_types import CustomType
Создаем класс, родителем которого является CustomType
.
class Position(CustomType):
def __init__(self, x: float, y: float):
self.x = x
self.y = y
@staticmethod
def adapter(obj) -> bytes:
return ('%f;%f' % (obj.x, obj.y)).encode('ascii')
def converter(self, obj: bytes):
return Position(*map(float, obj.split(b";")))
Добавляем конструктор класса и определяем атрибуты x
и y
— координаты.
class Position(CustomType):
def __init__(self, x: float, y: float):
self.x = x
self.y = y
@staticmethod
def adapter(obj) -> bytes:
return ('%f;%f' % (obj.x, obj.y)).encode('ascii')
def converter(self, obj: bytes):
return Position(*map(float, obj.split(b";")))
Определяем метод adapter
, который будет переводить наш тип данных в понятый для Sqlite.
По умолчанию adapter
выглядит так.
@staticmethod
def adapter(obj) -> bytes:
return str(obj).encode('ascii')
Параметр obj
— объект нашего типа данных.
В нашем случае — объект класса Position
.
class Position(CustomType):
def __init__(self, x: float, y: float):
self.x = x
self.y = y
@staticmethod
def adapter(obj) -> bytes:
return ('%f;%f' % (obj.x, obj.y)).encode('ascii')
def converter(self, obj: bytes):
return Position(*map(float, obj.split(b";")))
Определяем метод converter
, который будет переводить то, что находилось в базе данных, в наш тип данных.
- По умолчанию
converter
не определён. Его необходимо определить самостоятельно. - Метод должен возвращать объект нашего класса.
Параметр obj
— то же самое, что возвращает метод adapter
.
class Position(CustomType):
def __init__(self, x: float, y: float):
self.x = x
self.y = y
@staticmethod
def adapter(obj) -> bytes:
return ('%f;%f' % (obj.x, obj.y)).encode('ascii')
def converter(self, obj: bytes):
return Position(*map(float, obj.split(b";")))
Ещё один пример
Создадим тип данных, который будет хранить
числа с плавающий точкой(float
),
который почему-то не был реализован в v2.0.0.
class Float(CustomType, float):
def converter(self, obj: bytes):
return Float(obj)
- Здесь мы не определяем метод
__init__
, так как наш тип данных наследуется отfloat
. - Метод
adapter
мы не определяем, так как его состояние по умолчанию подходит под наши цели.
Модификация класса Points
¶
Мы не зря писали новый тип данных Position
.
Он поможет нам хранить координаты точек в таблице Points
.
Теперь наш код выглядит так
from sqlite3_api.field_types import CustomType
from sqlite3_api import Table
class Position(CustomType):
def __init__(self, x: float, y: float):
self.x = x
self.y = y
@staticmethod
def adapter(obj) -> bytes:
return ('%f;%f' % (obj.x, obj.y)).encode('ascii')
def converter(self, obj: bytes):
return Position(*map(float, obj.split(b";")))
class Points(Table):
position: Position
color: str
size: int
Значения по умолчанию¶
Допустим мы пишем игру и нам необходимо хранить данные об игроках.
Опишем таблицу Players
, которая будет хранить их данные.
from sqlite3_api import Table
from sqlite3_api.field_types import List
class Players(Table):
nick: str
gender: str
lvl: int
hp: int
score: int
items: List
В таком случае, при регистрации новых игроков,
мы должны будем указывать значение каждого поля.
(ведь мы не можем оставить их пустыми)
(может быть расписать 6 значений не так сложно,
но представим что их намного больше).
Именно в таких случаях нам помогут значения по умолчанию.
Вот как будет выглядеть код
class Players(Table):
nick: str
gender: str
lvl: int = 1
hp: int = 100
score: int = 0
items: List = List([])
Теперь при регистрации игроков, нам нужно будет указать всего лишь nick
и gender
.
Предупреждение
При обозначении полей по умолчанию
необходимо указывать значения с тем же типом данных!
Обратимся к полю items
из таблицы Players
.
Значением по умолчанию для этого поля мы указали List([])
.
Модификация класса Points
№2¶
Укажем значения по умолчанию для некоторых полей нашей таблицы.
Тогда наш код станет таким
from sqlite3_api.field_types import CustomType
from sqlite3_api import Table
class Position(CustomType):
def __init__(self, x: float, y: float):
self.x = x
self.y = y
@staticmethod
def adapter(obj) -> bytes:
return ('%f;%f' % (obj.x, obj.y)).encode('ascii')
def converter(self, obj: bytes):
return Position(*map(float, obj.split(b";")))
class Points(Table):
position: Position
color: str = 'black'
size: int = 1
Примечание
Если бы мы хотели указать значение по умолчанию для поля position
.
Мы бы сделали так:
position: Position = Position(x=0, y=0)
Наше описание таблицы готово! Можем переходить к работе с ней!