I’m confused about the differences of the following codes:
class car:
def __init__(self, weight):
self.weight = weight
class car:
def __init__(self, weight):
self.weight = 0
class car:
def __init__(self, weight=0):
self.weight = weight
class car:
def __init__(self, weight=0):
self.weight = 0
class car:
def __init__(self, weight=0):
self.weight = 1
class car:
def __init__(self):
self.weight = 0
My understanding it’s that if I specify weight=0
in def __init__(self, weight=0)
, then the default attributes is 0. But it seems that I can also do the similar if I don’t specify def __init__(self, weight)
but add self.weight = 0
afterwards. What’s the difference? What if we give two different values?
5
You get confused by concepts of function arg, default value for the arg, and member variable, you are mixing them so badly.
Function argument
For
def __init__(self,weight)
you are expecting a variable passed in when calling the constructor, which is given the name “weight”. It is a function argument.
Default value for function argument
For def __init__(self,weight=0)
, you are still expecting a variable passed in, but you are fine if it’s absent, in which case the default value 0 will be simply assigned to symbol “weight”. This is a default value for a function argument.
Member attribute
Now for the code below:
class car:
def __init__(self, weight=0):
self.weight = weight
It’s effectively saying, pass me a variable, I’ll assign it to a symbol “weight”, otherwise I’ll assign 0 to the symbol. And I’ll assign the value of symbol “weight” to “self.weight”, they locate at totally different scopes and hence are different symbols. It’s not like C++ when you do memberwise initialization. “self.weight” is an attribute of instances of the class.
weight vs self.weight
Hopefully that, now for the one last example, the logic will be clear enough:
class car:
def __init__(self, weight=0):
self.weight = 1
Here you are getting a symbol named “weight”, no matter by default or passed-in, it gets simply ignored, i.e., not referred anywhere, instead, you assign a 1 to member variable self.weight.
1
1
class car:
def __init__(self, weight):
self.weight = weight
- When initiating an object using this class, the
weight
argument is required (i.e.: can’t call justmy_car = car()
). And whatever the value ofweight
is passed when creating an object will be assigned to it’s attributeweight
:
>>> my_car = car()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: car.__init__() missing 1 required positional argument: 'weight'
>>> my_car = car(weight=69)
>>> print(my_car.weight)
69
2
class car:
def __init__(self, weight):
self.weight = 0
- When using this class to create an object, again, the
weight
argument is required. But no matter what the value ofweight
is passed when initializing an object, it’s going to be0
:
>>> my_car = car()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: car.__init__() missing 1 required positional argument: 'weight'
>>> my_car = car(weight=69)
>>> print(my_car.weight)
0
- However, later, it is possible to change/assign a new value to weight attribute:
>>> my_car.weight = 69
>>> print(my_car.weight)
69
3
class car:
def __init__(self, weight=0):
self.weight = weight
- When creating an object using this class, this time the
weight
is an optional argument (i.e.: no need to pass, but can be passed). Ifweight
is not passed as an argument, it will be assigned the default value, in this case0
:
>>> my_car = car()
>>> print(my_car.weight)
0
>>> my_car = car(weight=69)
>>> print(my_car.weight)
69
4
class car:
def __init__(self, weight=0):
self.weight = 0
- Okie, this one is interesting one (nvm).. When creating an object using this class, again, the
weight
argument is optional. But, what’s interesting about it is; no matter what is the value ofweight
that is passed as an argument or what is the default value of it, it will always going to be0
when creating an object:
>>> my_car = car() # No errors..
>>> print(my_car.weight)
0
>>> my_car = car(weight=69) # Useless argument..
>>> print(my_car.weight)
0
5
class car:
def __init__(self, weight=0):
self.weight = 1
- Just like the 4 just above,
weight
is optional and no matter what is the default value ofweight
is or what is being passed as an argument when creating an object, theweight
will be assigned the value1
:
>>> my_car = car()
>>> print(my_car.weight)
1
>>> my_car = car(weight=69)
>>> print(my_car.weight)
1
6
class car:
def __init__(self):
self.weight = 0
- This class doesn’t accept any arguments when creating an object and if you will try to pass an argument, you will get an error. And when creating an object, it’s
weight
attribute will be assigned value0
:
>>> my_car = car(69)
# That positional argument is `self`... 🙂
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: car.__init__() takes 1 positional argument but 2 were given
>>> my_car = car(weight=69)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: car.__init__() got an unexpected keyword argument 'weight'
>>> my_car = car()
>>> print(my_car.weight)
0
Okie, so which one is good or which one should you use? In my opinion (you can disagree), the 3rd one is good/better(?), but with slight modification:
class car:
def __init__(self, weight):
self.weight = weight
WHY?
- When creating an object, you are required to pass
weight
as an argument or it will give error. - I think, no car in this world will have “weight”
0
.. - All the cars must have weight, unless it’s made out of thin air. <3
Beside that, please follow “CapWords convention” for your class names. 🙂
🫡