<p>Namedtuples有一系列的行为使得它们不适合使用sqlalchemy进行映射:最重要的是,Namedtuples在创建之后不能被更改。这意味着您不能在insert操作之后使用namedtuple来跟踪数据库中一行的状态。您通常希望执行以下操作:</p>
<pre><code>class MyDataHolder(namedtuple('MyDataHolder', ('id', 'my_value')):
pass
mapper(MyDataHolder, MyDataMeta)
...
newRow = MyDataHolder(None, 'AAA')
...
session.add(newRow)
</code></pre>
<p>当会话代码执行SQL以将新数据添加到数据库时,它需要更新<em>newRow</em>,以便<em>新行.id</em>对应于数据库分配给行的id。但是由于newRow</em>是一个不可变的元组,因此不能更改id来保存从数据库返回的主键。这使得namedtuples在很大程度上不适合映射器。在</p>
<p>发生此问题是因为namedtuple在\uu new\uu中初始化,然后不希望更改。__在对象被创建之后,init_uUi()会被调用,因此没有任何效果。因此,namedtuples的qinit_uu只定义了一个参数:self。我猜映射器假设优init_uUu()正在处理类初始化,而不知道新的和不可变的类型。看起来他们在用创建时传递的参数调用<em>类名</em>。您可以通过指定自己的初始值设定项来“修复”这个问题,但最终会出现weakref问题。在</p>
<p>weakref错误的发生是因为namedtuples使用u slot_uuu存储它们的值,而不是可变的u dict_uus。我知道使用uu slots_uuu是一种内存优化,因此可以高效地存储大量的namedtuples。我假设一个namedtuple在创建之后不会改变。这包括添加属性,因此使用插槽是一个值得优化的内存。但是,我并不理解为什么namedtuple类的作者不支持弱引用。这不会是特别困难的,但可能有一个很好的原因,我失踪。在</p>
<p>今天早上我遇到了这个问题,并通过定义自己的类来解决这个问题,该类是用一个_fieldset属性初始化的。这指定了我感兴趣的(子)字段集。然后,我花了一些时间阅读了namedtuples是如何与其他一些python内部构件一起实现的文档。我想我已经了解了为什么这不起作用了,但是我相信有一些python专家比我更了解这一点。在</p>
<p>克里斯</p>