我是 Python 的新手,来自 Java,Java 在编译时一切都非常明确,所以我可能在这里遗漏了一些东西。我有一个这样定义的类:
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
然后我像这样使用它:
...
form = UploadFileForm(request.POST, request.FILES)
...
我正在向类中传递两个参数,那么为什么这在运行时没有向我抛出某种异常?当我尝试时它运行良好。我知道 Python 确实接受可变数量的参数,但在这种情况下我没有正确的语法。我想知道为什么可以这样做。
请您参考如下方法:
我认为您在这里混淆了类和函数。
这个:
class UploadFileForm(forms.Form):
…不是函数定义,而是类定义。它声明 UploadFileForm 的(唯一)父类(super class)是 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 框架父类(super class)用来代表您填充初始实例属性的类属性。
最后,reference documentation for Django's forms.Form class实际上并没有向您展示参数,因为有(至少)四种常见的不同方式来构造 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
其中一些接受额外的可选关键字参数。
实际源代码here显示真实原型(prototype):
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=':',
empty_permitted=False):
当然不是所有的关键字组合都有意义。
无论如何,您可以理解为什么他们没有尝试以解释其他类型的简单方式来解释 Form。
