您所请求的内容无法在 Python 2 中完成。whatever,出于非常具体的原因。你想写:
class Task(model):
title = ''
isDone = False
在Python 2中。anything, whatever model
可能是,这不可能ever允许您预测两个字段的任何“顺序”,因为 a 的语义class
声明是:
- 执行主体,从而准备一个
dict
- 找到元类并运行其特殊方法
无论元类是什么,步骤 1 都破坏了字段顺序的任何可预测性。
因此,您希望在代码片段中使用位置参数:
Task('Illustrate different syntax modes', True)
无法将参数的值与模型的各个字段关联起来。 (尝试通过类型关联来猜测 - 希望没有两个字段具有相同的类型 - 比你表达的使用愿望更可怕db.tasklist
and db['tasklist']
无关紧要和可互换)。
Python 3 中的一项向后不兼容的更改是专门为了处理此类情况而引入的。在Python 3中,自定义元类可以定义__prepare__
运行的函数before上面简化列表中的“步骤 1”,这让它可以更好地控制类的主体。具体来说,引用PEP 3115 http://www.python.org/dev/peps/pep-3115/...:
__prepare__
返回一个类似字典的对象,用于存储
评估类主体期间的类成员定义。
换句话说,类体被评估为一个功能块
(就像现在一样),除了局部变量字典
被替换为返回的字典__prepare__
。这
字典对象可以是常规字典或自定义映射
类型。
...
一个例子是元类
使用有关的信息
创建 C 结构体的成员声明的顺序。元类
将提供一个自定义字典,仅记录
插入顺序。
您不想像本示例中那样“创建 C 结构”,但字段的顺序至关重要(以允许使用您想要的位置参数),因此自定义元类(通过基类获得)model
)会有一个__prepare__
返回有序字典的类方法。这消除了具体问题,但是,当然,only如果您愿意将使用此“神奇 ORM”的所有代码切换到 Python 3。您愿意吗?
一旦解决了,问题就是您想要执行哪些数据库操作以及如何执行。当然,你的例子根本没有澄清这一点。是个taskList
属性名称特殊,或者应该any分配给的其他属性db
对象在使用时“自动保存”(通过名称和其他什么特征?)和“自动检索”?是否有办法删除实体、改变它们、定位它们(除了曾经被列在实体的相同属性中之外)db
目的)?如果需要身份验证,您的示例代码如何知道要使用什么数据库服务以及如何对其进行身份验证(例如通过用户 ID 和密码)?
您列出的具体任务并不难实现(例如,在 Google App Engine 的存储服务之上,它不需要身份验证,也不需要指定“使用什么数据库服务”)。model
的元类会内省该类的字段并生成一个 GAEModel
对于班级来说,db
对象将使用__setattr__
设置一个atexit
用于存储属性的最终值的触发器(作为不同类型的实体)Model
当然),并且__getattr__
从存储中取回该属性的信息。当然,如果没有一些额外的数据库功能,这一切都将毫无用处;-)。
Edit:所以我做了一个小原型(Python 2.6,基于 sqlite)并将其放在http://www.aleax.it/lustdb.zip http://www.aleax.it/lustdb.zip-- 这是一个 3K zip 文件,包含 225 行lustdb.py
(太长了,无法在这里发布)和两个小测试文件,大致相当于OP的原始文件: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))
and test1.p1
is...:
from lustdb import *
print 'Done tasks:'
for task in db.taskList:
if task.done:
print task
Running test0.py
(在具有可写的机器上/tmp
目录——即任何 Unix-y 操作系统,或者在 Windows 上,一个mkdir \tmp
之前已运行过;-) 没有输出;之后,运行test1.py
输出:
Done tasks:
Task(done=True, title=u'Illustrate different syntax modes')
请注意,这些在很多方面都远不如OP的例子那么“疯狂神奇”,例如......:
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 托管部分的开源项目(或任何其他具有问题跟踪器、wiki、代码审查支持、在线浏览、DVCS 支持等的良好开源托管网站) - 我会自己做,但是我在 code.google.com 上可以启动的开源项目数量已接近极限,并且不想以这种方式“烧掉”最后一两个项目;-)。
顺便说一句,lustdb
该模块的名称是一个带有 OP 首字母缩写的文字游戏(名字和姓氏各前两个字母),遵循以下传统:awk
和朋友们——我认为这听起来不错(以及大多数其他明显的名字,例如simpledb
and dumbdb
被采取;-)。