1

在python中保证类中属性的顺序保持不变?这是如何保证的?手册在哪里指定?

这以声明方式将字段定义为类属性:

class MyForm(Form):
    first_name = TextField(u'First Name', validators=[validators.required()])
    last_name  = TextField(u'Last Name', validators=[validators.optional()])
    ...


def get(self):
    form = MyForm(self.request.arguments)
    form=form
    self.render('forms.html', form=form)

即使我有n 个项目,名字总是第一个项目,姓氏第二个项目?

4

2 回答 2

7

不,通常不能保证属性的顺序,因为 Python 将属性存储在字典中。

相反,wtforms使用特殊技巧来检测定义字段的顺序,以解决此问题。每次创建Field对象时,都会增加一个计数器,并为字段实例分配一个唯一编号。这使得对象可排序:

class UnboundField(object):
    _formfield = True
    creation_counter = 0

    def __init__(self, field_class, *args, **kwargs):
        UnboundField.creation_counter += 1
        # [...]
        self.creation_counter = UnboundField.creation_counter

因此,每次将新字段添加到表单时,Field实例都会增加一个值。creation_counter

然后FormMeta该类在字段上使用该值以正确的顺序对它们进行排序:

fields.sort(key=lambda x: (x[1].creation_counter, x[0]))
于 2013-11-11T17:25:39.743 回答
1

一个新的类是通过实例化一个元类来创建的,就像你通过实例化一个类来创建一个新的实例对象一样。类声明,如:

class MyForm(Form):
    first_name = TextField(u'First Name', validators=[validators.required()])
    last_name  = TextField(u'Last Name', validators=[validators.optional()])    

相当于下面的调用,type默认的python元类在哪里:

MyForm = type('MyForm', (Form,), {'first_name': TextField(u'First Name', validators=[validators.required()]), 
                                  'last_name': TextField(u'Last Name', validators=[validators.optional()])}

由于类命名空间作为 dict 向前传递,并且 dicts 具有任意顺序,因此不会保留顺序。

将顺序记录在某处的一种方法是让TextField类本身为每组参数注册调用它的顺序。然后您可以恢复声明字段的顺序。这可能是 Django 在幕后所做的。

于 2013-11-11T17:32:36.753 回答