То, что вы запрашиваете, не может быть выполнено в Python 2. независимо от по очень конкретной причине. Вы хотите написать:
class Task(model):
title = ''
isDone = False
В Python 2. что-нибудь , независимо от того, что model
может быть, это не может когда-либо позволить вам предсказать любой "порядок" для двух полей потому что семантика оператора class
:
- выполнить тело, таким образом готовя
dict
- найдите метакласс и запустите его специальные методы
Каким бы ни был метакласс, шаг 1 разрушил любую предсказуемость порядка полей.
Следовательно, желаемое использование позиционных параметров в фрагменте:
Task('Illustrate different syntax modes', True)
не может связать значения аргументов с различными полями модели. (Попытка угадать по типу ассоциации - надеясь, что никакие два поля никогда не будут иметь один и тот же тип - будет еще более ужасной, чем у вас выраженное желание использовать db.tasklist
и db['tasklist']
безразлично и взаимозаменяемо).
Одно из обратно несовместимых изменений в Python 3 было введено специально для решения подобных ситуаций. В Python 3 пользовательский метакласс может определять функцию __prepare__
, которая запускается за до «шага 1» в приведенном выше упрощенном списке, и это позволяет ему иметь больше контроля над телом класса. В частности, цитата PEP 3115 ...:
__prepare__
возвращает словарный объект, который используется для хранения
определения членов класса во время оценки тела класса.
Другими словами, тело класса оценивается как функциональный блок
(так же, как сейчас), за исключением того, что словарь локальных переменных
заменяется словарем, возвращаемым из __prepare__
. это
Объект словаря может быть обычным словарем или пользовательским отображением
тип.
...
Примером может служить метакласс, который
использует информацию о
упорядочение объявлений членов для создания структуры Си. Метакласс
будет предоставлять пользовательский словарь, который просто ведет запись
порядок вставок.
Вы не хотите «создавать структуру C», как в этом примере, но порядок полей имеет решающее значение (чтобы разрешить использование требуемых позиционных параметров), и поэтому пользовательский метакласс (полученный с помощью base * 1050) *) будет иметь метод класса __prepare__
, возвращающий упорядоченный словарь. Это устраняет конкретную проблему, но, конечно, только , если вы хотите переключить весь свой код с помощью этой «магической ORM» на Python 3. Вы бы хотели?
Как только это будет решено, вопрос в том, какие операции с базой данных вы хотите выполнить и как. Ваш пример, конечно, не проясняет это вообще. Является ли имя атрибута taskList
особенным или любой другой атрибут, назначенный объекту db
, должен быть "автоматически сохранен" (по имени и каким другим характеристикам [s]?) И "автоматически восстановлен" при использовании ? Есть ли способы удалить сущности, изменить их, найти их (иначе, чем когда-то в списке в том же атрибуте объекта db
)? Как ваш пример кода знает, какую службу БД использовать и как к ней аутентифицироваться (например, с помощью идентификатора пользователя и пароля), если она требует аутентификации?
Конкретные задачи, которые вы перечислите, не составит труда реализовать (например, в верхней части службы хранения Google App Engine, которая не требует аутентификации или указания «какую службу БД использовать»). Метакласс model
будет анализировать поля класса и генерировать GAE Model
для класса, объект db
будет использовать __setattr__
для установки триггера atexit
для хранения окончательного значения атрибута (как сущности в другом виде Model
, конечно) и __getattr__
для извлечения информации об этом атрибуте из хранилища. Конечно, без какой-либо дополнительной функциональности базы данных все это было бы довольно бесполезно; -).
Редактировать : поэтому я сделал небольшой прототип (Python 2.6 и на основе sqlite) и поставил его на http://www.aleax.it/lustdb.zip - это 3K-файл zipfile, включающий 225 строк lustdb.py
(слишком длинный, чтобы публиковать здесь) и два небольших тестовых файла, примерно эквивалентных оригиналам ОП: test0.py
is ...:
from lustdb import *
class Task(Model):
title = ''
done = False
db.taskList = []
db.taskList.append(Task(title='Beat old sql interfaces', done=False))
db.taskList.append(Task(title='Illustrate different syntax modes', done=True))
и test1.p1
- это ...:
from lustdb import *
print 'Done tasks:'
for task in db.taskList:
if task.done:
print task
Запуск test0.py
(на машине с доступным для записи каталогом /tmp
- т. Е. Любой ОС Unix-y или, в Windows, на которой mkdir \tmp
был запущен в любое предыдущее время ;-) не имеет выхода; после этого работает test1.py
выводит:
Done tasks:
Task(done=True, title=u'Illustrate different syntax modes')
Обратите внимание, что они гораздо менее "безумно волшебны", чем примеры ОП, во многих отношениях, например ...:
1. no (expletive delete) redundancy whereby `db.taskList` is a synonym of `db['taskList']`, only the sensible former syntax (attribute-access) is supported
2. no mysterious (and totally crazy) way whereby a `done` attribute magically becomes `isDone` instead midway through the code
3. no mysterious (and utterly batty) way whereby a `print task` arbitrarily (or magically?) picks and prints just one of the attributes of the task
4. no weird gyrations and incantations to allow positional-attributes in lieu of named ones (this one the OP agreed to)
Конечно, прототип (как и прототипы ;-) оставляет желать лучшего во многих отношениях (ясность, документация, модульные тесты, оптимизация, проверка ошибок и диагностика, переносимость между различными бэк-эндами и особенно функции БД за пределами возможностей те, которые подразумеваются в вопросе). Отсутствующие функции БД - легион (например, оригинальные примеры OP не дают возможности идентифицировать «первичный ключ» для модели или любые другие виды ограничений уникальности, поэтому дубликатов может быть достаточно, и от этого только ухудшается; - ). Тем не менее, для 225 строк (190 пустых строк, комментариев и строк документации ;-), по моему предвзятому мнению, это не так уж и плохо.
Надлежащим способом продолжения игры с этим проектом будет, конечно, инициирование нового lustdb
проекта с открытым исходным кодом на хостинговой части code.google.com (или на любом другом хорошем хостинг-сайте с открытым исходным кодом с трекером проблем, вики). , поддержка обзоров кода, онлайн-просмотр, поддержка DVCS и т. д., и т. д.) - Я бы сделал это сам, но я близок к ограничению по количеству проектов с открытым исходным кодом, которые я могу инициировать на code.google.com и не могу не хочу «сжечь» последние один или два таким образом; -).
Кстати, имя lustdb
для модуля - игра слов с инициалами ОП (первые две буквы - имена и фамилии), в традиции awk
и друзей - я думаю, это звучит красиво (и большинство других очевидных имен, таких как simpledb
и dumbdb
взяты; -).