1

我对 Python 比较陌生,并且来自 Java,在编译时一切都非常明确,所以也许我在这里遗漏了一些东西。我有一个这样定义的类:

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()

然后我像这样使用它:

...
form = UploadFileForm(request.POST, request.FILES)
...

我将两个参数传递给类,那么为什么在运行时不会向我抛出某种异常?当我尝试时它运行良好。我知道 Python 确实接受可变数量的参数,但在这种情况下我没有正确的语法。我想知道为什么可以这样做。

4

1 回答 1

8

我认为您在这里混淆了类和功能。

这个:

class UploadFileForm(forms.Form):

... 不是函数定义,而是类定义。它声明(唯一的)超类UploadFileFormis forms.Form

当你这样做时:

form = UploadFileForm(request.POST, request.FILES)

效果类似于这个伪代码:

form = make new UploadFileForm
form.__init__(request.POST, request.FILES)

如果你定义了一个__init__方法,你会得到form, request.POST, 和request.FILES作为你的参数。

由于您没有定义__init__方法,因此您从父类继承了该方法,因此获取了这三个参数。


这几乎与以下 Java 伪代码完全相同:

class UploadFileForm extends forms.Form {
    static forms.CharField title = forms.CharField(50);
    static forms.FileField file = forms.FileField();
};

UploadFileForm form = new UploadFileForm(request.POST, request.FILES);

就像在 Python 中一样,它之所以有效,是因为您从基类继承了构造函数。在某处Form,有这样的声明:

public Form(int verb, int obj) {
    // blah blah
}

而且,在 Python 中,同样的情况也是如此:

def __init__(self, verb, obj):
    # blah blah

换句话说,Python 几乎和 Java 一样显式(事实上,稍微多一点,因为self参数是显式的)。


另请注意,您的 Python 类属性等同于 Java 中的静态成员。如果你想要普通的实例成员,你通常会覆盖__init__它们并将它们设置为self.title,等等。(您不必那样——Python 允许您随时向对象添加新成员。但它显然是这样做的地方。)对于 Django,这实际上很常见——您创建类属性Django 框架超类用于代表您填写初始实例属性。


最后,Django 的 forms.Form 类的参考文档实际上并没有向您显示参数,因为(至少)有四种常见的不同方式来构造Form子类,所有这些方式都单独描述:

MyForm() # creates an unbound form
MyForm(data) # creates a bound form
MyForm(data, files) # creates a bound file or image form
MyForm(initial=initial_data) # creates an unbound form with initial data

其中一些接受额外的可选关键字参数。

这里的实际源代码显示了真正的原型:

def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
             initial=None, error_class=ErrorList, label_suffix=':',
             empty_permitted=False):

当然,并非所有关键字组合都有意义。

无论如何,您可以看到为什么他们没有尝试以Form他们做其他类型的简单方式来解释。

于 2013-05-30T01:01:20.493 回答