Понимание использования псевдонимов типов и ParamSpec в PythonPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Понимание использования псевдонимов типов и ParamSpec в Python

Сообщение Anonymous »

В настоящее время я работаю над проектом Python версии 3.12.2, который я недавно опубликовал в PyPi, под названием ormlambda, где я широко использую TypeAlias для управления сложными аннотациями типов в функциях. и занятия. Однако по мере роста проекта я обнаружил, что псевдонимами типов сложно управлять и рефакторить, что приводит к избыточности и снижению читабельности.
Для иллюстрации я прикрепил фрагмент из моего текущего кода. настройку.
Мой главный вопрос:
Существуют ли альтернативные способы обработки аннотаций сложных типов, которые могут быть более эффективными или простыми в управлении, чем использование TypeAlias в этом сценарии?
Контекст:
В моем проекте я использую класс . методы join и .select для обработки сложных запросов, включающих несколько классов. Вот описание каждого метода и конкретная роль, которую он играет:

[*].join Метод: этот метод позволяет мне объединить несколько классов (таблиц) в один запрос. Указав классы в .join, я могу получать данные из различных связанных источников, структурируя свой запрос для более эффективного получения данных без выполнения нескольких отдельных запросов к базе данных.

.select Метод: после использования .join для объединения нескольких таблиц метод .select позволяет мне указать, какие поля я хочу получить. Здесь я использую лямбда-функцию для динамического выбора полей из каждого класса, который объединяет .join.
Однако важным моментом является то, что сложность лямбда-функции возрастает с увеличением количества классы, указанные в .join. Каждый дополнительный класс добавляет больше переменных, которые должна обрабатывать лямбда-функция для правильного сопоставления полей в .select. По мере роста количества классов в .join лямбда-функции в .select приходится управлять растущим количеством входных данных.

< /ol>
Основная задача: Моя основная цель — найти способ передать ввод из метода .join непосредственно в .select метод с использованием TypeVarTuple -> [*Ts] (В настоящее время подход работает правильно). В нынешнем виде сложность лямбда-функции .select увеличивается с каждым дополнительным классом, добавляемым в .join, поскольку для точной обработки полей требуется больше переменных.
Я чувствую, что могу использовать что-то вроде TypeVarTuple но, похоже, у меня не получается.
Любые рекомендации по эффективному связыванию этих наборов между .join и .select буду очень признателен!
Код, который я использую, приведен ниже.
from __future__ import annotations

import unittest
import typing as tp
from datetime import datetime

from ormlambda import Table, Column # pip install ormlambda

class Custom(Table):
__table_name__ = "custom"
pk_custom: int = Column[int](is_primary_key=True)
data: str
floats: float

class Client(Table):
__table_name__ = "client"
pk_client: int = Column[int](is_primary_key=True)
age: int
name: str
surname: str

class Order(Table):
__table_name__ = "order"
pk_order: int = Column[int](is_primary_key=True)
code: str
date_from_order: datetime

class A(Table):
__table_name__ = "a"
pk_a: int = Column[int](is_primary_key=True)
data_a: str

class B(Table):
__table_name__ = "b"
pk_b: int = Column[int](is_primary_key=True)
data_b: str

class C(Table):
__table_name__ = "c"
pk_c: int = Column[int](is_primary_key=True)
data_c: str

class D(Table):
__table_name__ = "d"
pk_d: int = Column[int](is_primary_key=True)
data_d: str

type JoinCondition[T, T1] = tuple[T1, tp.Callable[[T, T1], bool]]

type TupleJoins1[T, T1] = tuple[JoinCondition[T, T1]]
type TupleJoins2[T, T1, T2] = tuple[*TupleJoins1[T, T1], JoinCondition[T, T2]]
type TupleJoins3[T, T1, T2, T3] = tuple[*TupleJoins2[T, T1, T2], JoinCondition[T, T3]]
type TupleJoins4[T, T1, T2, T3, T4] = tuple[*TupleJoins3[T, T1, T2, T3], JoinCondition[T, T4]]
type TupleJoins5[T, T1, T2, T3, T4, T5] = tuple[*TupleJoins4[T, T1, T2, T3, T4], JoinCondition[T, T5]]
type TupleJoins6[T, T1, T2, T3, T4, T5, T6] = tuple[*TupleJoins5[T, T1, T2, T3, T4, T5], JoinCondition[T, T6]]

class CustomTable[T, *Ts]:
def __init__(self, model: T) -> None:
self.tables: tuple[T, *Ts] = (model,)

@tp.overload
def join[T1](self, joins: TupleJoins1[T, T1]) -> CustomTable[T, T1]: ...
@tp.overload
def join[T1, T2](self, joins: TupleJoins2[T, T1, T2]) -> CustomTable[T, T1, T2]: ...
@tp.overload
def join[T1, T2, T3](self, joins: TupleJoins3[T, T1, T2, T3]) -> CustomTable[T, T1, T2, T3]: ...
@tp.overload
def join[T1, T2, T3, T4](self, joins: TupleJoins4[T, T1, T2, T3, T4]) -> CustomTable[T, T1, T2, T3, T4]: ...
@tp.overload
def join[T1, T2, T3, T4, T5](self, joins: TupleJoins5[T, T1, T2, T3, T4, T5]) -> CustomTable[T, T1, T2, T3, T4, T5]: ...
@tp.overload
def join[T1, T2, T3, T4, T5, T6](self, joins: TupleJoins6[T, T1, T2, T3, T4, T5, T6]) -> CustomTable[T, T1, T2, T3, T4, T5, T6]: ...

def join[*Tables](self, joins) -> CustomTable[T, *Tables]:
tables = tuple(table for table, _ in joins)
self.tables = (*self.tables, *tables)
return self

def select[*TRes](self, query: tp.Callable[[T, *Ts], tuple[*TRes]]) -> tuple[*TRes]:
return query(*self.tables)

class TypeCheckerTest(unittest.TestCase):
def test_type_checker(self) -> None:
table = CustomTable[Custom](Custom(data="custom_data"))

# region instantiate model classes
client = Client(1, 25, "pp", "pp's surname")
order = Order(1, "000-111-222", datetime(2000, 1, 1))
a = A(None, "data_A")
b = B(None, "data_B")
c = C(None, "data_C")
# endregion

result = table.join(
(
(client, lambda cu, cl: cu.pk_custom == cl.pk_client),
(order, lambda cu, order: cu.pk_custom == order.pk_order),
(a, lambda cu, a: cu.pk_custom == a.data_a),
(b, lambda cu, b: cu.pk_custom == b.data_b),
(c, lambda cu, c: cu.pk_custom == c.pk_c),
)
).select(
lambda custom, client, order, a, b, c: (
custom.data,
client.age,
order.date_from_order,
order.code,
a.data_a,
b.data_b,
c.data_c,
)
)

tu1 = ("custom_data", 25, datetime(2000, 1, 1), "000-111-222", "data_A", "data_B", "data_C")
self.assertTupleEqual(tu1, result)

if __name__ == "__main__":
unittest.main()


Подробнее здесь: https://stackoverflow.com/questions/791 ... -in-python
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Понимание использования псевдонимов типов и ParamSpec в Python
    Anonymous » » в форуме Python
    0 Ответы
    36 Просмотры
    Последнее сообщение Anonymous
  • Понимание псевдонимов шаблонов в C++
    Anonymous » » в форуме C++
    0 Ответы
    35 Просмотры
    Последнее сообщение Anonymous
  • Предоставление функций, структур и псевдонимов типов в Godot 4 с помощью GDExtension?
    Anonymous » » в форуме C++
    0 Ответы
    53 Просмотры
    Последнее сообщение Anonymous
  • Недопустимое преобразование из «const T*» в «T*» с использованием псевдонимов типов
    Anonymous » » в форуме C++
    0 Ответы
    42 Просмотры
    Последнее сообщение Anonymous
  • MyPy не игнорирует код ошибки `valid-type` для псевдонимов типов
    Anonymous » » в форуме Python
    0 Ответы
    40 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»