仅向一个已定义的类发送多个参数

tre*_*r-e 1 python django

我是Python的新手,我来自Java,在编译时一切都非常明确,所以也许我在这里遗漏了一些东西.我有一个类定义如下:

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()
Run Code Online (Sandbox Code Playgroud)

然后我就像这样使用它:

...
form = UploadFileForm(request.POST, request.FILES)
...
Run Code Online (Sandbox Code Playgroud)

我将两个参数传递给了这个类,为什么在运行时这不会给我带来某种异常?我试用它时运行正常.我知道Python确实接受了可变数量的参数,但在这种情况下我没有正确的语法.我想知道为什么这样做是可以的.

aba*_*ert 8

我认为你在这里混淆了课程和功能.

这个:

class UploadFileForm(forms.Form):
Run Code Online (Sandbox Code Playgroud)

...不是函数定义,它是类定义.它声明了(唯一的)超类UploadFileFormforms.Form.

当你这样做:

form = UploadFileForm(request.POST, request.FILES)
Run Code Online (Sandbox Code Playgroud)

效果类似于这个伪代码:

form = make new UploadFileForm
form.__init__(request.POST, request.FILES)
Run Code Online (Sandbox Code Playgroud)

如果你定义一个__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);
Run Code Online (Sandbox Code Playgroud)

就像在Python中一样,它可以工作,因为你从基类继承了构造函数.在某处Form,有一个这样的声明:

public Form(int verb, int obj) {
    // blah blah
}
Run Code Online (Sandbox Code Playgroud)

并且,在Python中,同样的事情是真的:

def __init__(self, verb, obj):
    # blah blah
Run Code Online (Sandbox Code Playgroud)

换句话说,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
Run Code Online (Sandbox Code Playgroud)

其中一些接受其他可选关键字参数.

实际的源代码在这里展示真实的原型:

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

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

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