Python3 - 替换动态选择的namedtuple字段

问题描述:

我使用collections.namedtuple为数据库记录建模。有时,我希望用户能够替换任意字段的内容。只要我们可以指定其名称作为参数的一部分,_replace()方法允许替换特定字段的内容:somenamedtuple._replace(somefield=newcontent)。但是,如果名称本身是由用户动态提供的,我无法找到一种方法来实现它。Python3 - 替换动态选择的namedtuple字段

这里是一个最小的工作示例:

from collections import namedtuple 

fields = ['one', 'two', 'three'] 
Record = namedtuple('Record', fields) 
# Populate fields. 
record = Record(*tuple(['empty' for i in fields])) 
while True: 
    # Show what we have already. 
    print('0: quit') 
    for i in range(len(fields)): 
    print('{}: {}: {}'.format(i+1, fields[i], record[i])) 
    to_change = int(input('Field to change: ')) 
    if not to_change: 
     break 
    else: 
     new_content = input('New content: ') 
     field_to_change = {fields[to_change-1]:new_content} 
     print('Setting', field_to_change) 
     record._replace(**field_to_change) 
print('Finished.') 
print(record) 

输出(IPython的1.0.0,Python的3.3.1)如下。

In [1]: run test_setattr_namedtuple 
0: quit 
1: one: empty 
2: two: empty 
3: three: empty 
Field to set: 2 
New content: asdf 
Setting {'two': 'asdf'} 
0: quit 
1: one: empty 
2: two: empty 
3: three: empty 
Field to set: 0 
Finished. 
Record(one='empty', two='empty', three='empty') 

In [2]: 

record._replace()线尝试设置“两化”到“ASDF”,而不是two等失败默默。我曾想过在_replace()内部使用eval,但_replace()不接受表达式作为参数。

我也尝试了内置函数setattr,但它不适用于namedtuples,大概是因为它们是不可变的。

._replace()方法返回改变的命名元组实例。您将丢弃返回的值。

与元组类似,名为派生类的实例是不可变的,并且._replace()确实是而不是就地更改了值。

用新的替换原来的值:

record = record._replace(**field_to_change)           
+0

Aaarrrgh ...谢谢你。 – brannerchinese