1👍
This is more of a Python question than a Django question, as it looks at object inheritance and initialization more than anything else.
Here’s the short version:
__init__
is a method that gets called when initializing an instance. It’s not actually a constructor (that’s called __new__
), but when you do something like
booking_form = BookingForm(room_choices)
__init__
will be called after the constructor.
By calling super(BookingForm, self).__init__(*args, **kwargs)
you allow initializations to bubble up the inheritance chain. In this case, you allow forms.Form
to do all the initialization it needs to do, which includes defining the form and setting up the fields you defined.
After the fields are defined on the Form
instance, you override the choices on the room
field. If you’d try to switch those two lines so that the override takes place before the parent initialization, you’d get a KeyError
as self.fields
doesn’t exist at that point.
As for the params:
self
is a reference to the current instance, that has to be passed to every instance method. This is how Python deals with instance methods (it’s the equivalent ofthis
in Java)room_choices
is your param*args
and**kwargs
are Python’s way of dealing with arbitrary parameters.
For example, if you’d have something like
def foo(param1):
pass
and you called foo(1, 2, a=5)
you’d get an error about the number of arguments. However, if you defined your method like this:
def foo(param1, *args, **kwargs):
pass
and you called the same foo(1, 2, a=5)
, args would now be a list [1]
and kwargs will be a dictionary {'a': 5}
and you would obviously not get any errors.
*args
and **kwargs
are especially useful when you don’t want to care about all the parameters the parent method that you are overriding has – as it is in your case here, where forms.Form.__init__
has a whole bunch of parameters – which you don’t touch. You just add your parameter in front of them, and *args
and **kwargs
take any other potential parameter up the inheritance chain.