Поля и типы данных¶
Типы данных¶
Прежде чем мы продолжим модифицировать наш класс 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)
Наше описание таблицы готово! Можем переходить к работе с ней!