класс данных: как получить вычисленные значения родительского экземпляра в дочерних экземплярах - PullRequest
0 голосов
/ 29 февраля 2020

Я не уверен, что вопрос точно отражает мою дилемму. Экземпляры Film на самом деле не связаны в цепочке родительского MRO Director, поскольку они не наследуются от этого класса.

С этим связано множество проблем, не в последнюю очередь из которых, как я исследую, как рефакторинг это для использования с SQLAlchemy. Простую стандартную библиотеку (3.7) dataclass declarative легко построить, и она хорошо работает, даже с миксинами и в виде смешанных, но причудливые кусочки ассоциативных отношений в классах Python, представленные здесь, остаются для меня в значительной степени загадка с чем-то вроде едва достижимого горизонта.

На пути к этому рассвету самая большая проблема здесь, помимо размещения классов для рефакторинга для использования с SQLAlchemy, - это присвоение Director instance id к каждому из фильмов.

Если у вас есть понимание порядка вывода, это было бы здорово. Таким образом, порядок сохраняется в соответствии с порядком объявления в классе, но он уничтожается тем фактом, что любой атрибут со значением по умолчанию не должен предшествовать любому, который инициализируется автоматически, то есть порядок в объявлении учитывается в зависимости от того, как получено значение .

Извините, если это немного грязно. Это бесплатно sh из заметок, и не было предпринято никаких усилий, чтобы уменьшить его.

Любые другие вопросы / ответы, которые вы можете задать в отношении автономной оптимизации рефакторинга, и в теоретическом контексте SQLAlchemy, все очень очень признателен. Я сделаю все, что в моих силах, чтобы отредактировать это, если есть интерес к рассылке лучших практик здесь.

На дополнительном примечании у меня возникли проблемы с импортом InitVar. Поскольку я использую Python 3.6.9, а dataclasses устанавливается через pip install dataclasses, мне интересно, решена ли это известная проблема, связанная со стандартным внедрением библиотеки в Python 3.7, или, вероятно, что-то уникальное для меня?

Поскольку я продолжаю работать над этим, я ищу указатели о том, как обращаться с датами. Обратите внимание на дату рождения директоров здесь, висят как комментарии. Для date нет типа класса данных, и, если я не ошибаюсь, Any из библиотеки typing, тот же самый List, с заглавной буквы 'L', будет способствовать автоматической инициализации, требуется запись на создание экземпляра класса. Для этого также необходимо рассчитать возраст по введенной дате рождения.

Импорт

from dataclasses import dataclass, field, asdict, astuple
from typing import ClassVar, List, Any
import pprint
from pprint import PrettyPrinter
pp = pprint.PrettyPrinter(indent=4)


@dataclass
class Film:
    _films_count: ClassVar = 0
    _films_list: ClassVar = []

    name: str
    year: str
    director_id: int = field(default_factory = int, init=False)
    # film_list: list = field(default_factory = list)
    film_tuple: tuple = field(default_factory = tuple)
    id: int = field(init=False)

    def __post_init__(self):
        # director_id = Director.id
        Film._films_count += 1
        self.id = Film._films_count

# d_films = Films()
# d_films = Film("Lucy", 2016)
# print(d_films)
# print(asdict(d_films))

@dataclass
class Director:

    _director_count: ClassVar = 0
    _director_names: ClassVar = []

    firstname: str
    lastname: str
    age: int
    fullname: str = field(init=False)
    film_list: List[Film] # = field(default_factory=list)
    id: int = field(init=False)

    def __post_init__(self):
        # pass
        Director._director_count += 1
        self.id = Director._director_count
        self.fullname = f"{self.firstname} {self.lastname}"
        Director._director_names.append(self.getfullname())
        Director._director_names.append(self.fullname)

    def getfullname(self):
        return self.fullname

    @classmethod
    def assign_id(cls):
        print("Class ", cls)
        return Director._director_count + 1 

d_assign_id = Director.assign_id()
print("D_ID ",d_assign_id)


films = (Film("Lucy", 2014, d_assign_id), Film("5th Element", 1997, d_assign_id), Film("Anna", 2019, d_assign_id))
d = Director("Luc", "Besson", 60, films)
# March 18, 1959

d_assign_id = Director.assign_id()
films = (Film("Star Trek: Into Darkness", 2013, d_assign_id), Film("Mission Impossible III", 2006, d_assign_id), Film("Star Wars: The Force Awakens", 2015, d_assign_id))
e = Director("JJ", "Abrams", 53, films)
# June 27, 1966

print(d.getfullname())
print(d.__repr__())
print(Director._director_count)
dashed()
print(Director._director_names)
dashed()
for _ in Director._director_names:
    print(_)
dashed()
pp.pprint(asdict(d))
dashed()
# pp.pprint(astuple(d))
# dashed()
# pp.print(Film._film_names[:])
pp.pprint(asdict(e))


Вывод

d_assign_id не работает. В film_list.director_id для каждой записи значение остается 0. Как бы вы подошли к рефакторингу, чтобы он работал? Как бы вы описали отношения между классами на языке OO и, надеюсь, с метаданными таблицы lin go?

☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂

{   'age': 60,
    'film_list': (   {   'director_id': 0,
                         'film_tuple': 1,
                         'id': 1,
                         'name': 'Lucy',
                         'year': 2014},
                     {   'director_id': 0,
                         'film_tuple': 1,
                         'id': 2,
                         'name': '5th Element',
                         'year': 1997},
                     {   'director_id': 0,
                         'film_tuple': 1,
                         'id': 3,
                         'name': 'Anna',
                         'year': 2019}),
    'firstname': 'Luc',
    'fullname': 'Luc Besson',
    'id': 1,
    'lastname': 'Besson'}

☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂

{   'age': 53,
    'film_list': (   {   'director_id': 0,
                         'film_tuple': 2,
                         'id': 4,
                         'name': 'Star Trek: Into Darkness',
                         'year': 2013},
                     {   'director_id': 0,
                         'film_tuple': 2,
                         'id': 5,
                         'name': 'Mission Impossible III',
                         'year': 2006},
                     {   'director_id': 0,
                         'film_tuple': 2,
                         'id': 6,
                         'name': 'Star Wars: The Force Awakens',
                         'year': 2015}),
    'firstname': 'JJ',
    'fullname': 'JJ Abrams',
    'id': 2,
    'lastname': 'Abrams'}

☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂ # ☂

New Horizons

Итак, Ответ был опубликован в комментариях, и он содержит правильный, последовательно получаемый director_id для каждого экземпляра класса Film в пределах сгенерированного default_factory List. И это немного низкоуровневых магов c, которые должны быть зачтены умельцам PEP.

Продвигаясь, в Film, этот метод экземпляра:

def getdirector_id(self):
    return self.director_id

. .. с желанием получить доступ к Film экземплярам, ​​созданным в массовом порядке при вызове Director, в соответствии с этим нерабочим примером:

print(Film.id[5].getdirector_id())

Имеется ли возможность уже и вызов Я делаю просто показывает недостаток знаний? Или метод экземпляра не является правильным подходом, или путь данных к элементу плохо понят / понят?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...