我对Python比较新,我来自Java,在编译时一切都非常明确,所以也许我在这里遗漏了一些东西。我有一个如此定义的类:
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
然后我就像这样使用它:
...
form = UploadFileForm(request.POST, request.FILES)
...
我将两个参数传递给了这个类,为什么在运行时这不会给我带来某种异常?我试用它时运行正常。我知道Python确实接受了可变数量的参数,但在这种情况下我没有正确的语法。我想知道为什么这样做可以。
答案 0 :(得分:8)
我认为你在这里混合了类和函数。
此:
class UploadFileForm(forms.Form):
...不是函数定义,它是类定义。它声明UploadFileForm
的(唯一)超类是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__
方法,因此您从父类继承了该方法,因此 it 获取这三个参数。
这几乎与以下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框架超类用于代表您填充初始实例属性的类属性。
最后,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显示了真实的原型:
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=':',
empty_permitted=False):
当然,并非所有关键字组合都有意义。
无论如何,你可以看到为什么他们没有尝试以简单的方式解释Form
。