I'm learning how classes works and I got stuck on a thing which I can't explain, I also didn't find a solution on the Internet so here am I with my first question on StackOverflow.
class Swords:
damage = 5
Here is a class with only one line, with attribute damage. Let's make an instance of the class:
sharp_sword = Swords()
And here is the moment of truth.
My class doesn't have an init function, so right now my sharp_sword.__dict__
is empty - my object of the class has an empty namespace, it doesn't have any attributes or methods. Well, we can create an attribute since we already defined it in the class itself:
sharp_sword.damage = 10
Now if we print(sharp_sword.damage)
the return will be 10, if we print(Swords.damage)
, the return will be 5. That means that our instance of the class has its own attribute - and it is without any init inside my class.
I can create another object, set its damage to 15, and I will have two objects with different damage. Since we didn't change damage in class, if we print(Swords.damage), the return will be 5.
The question coming by itself - why then should I use __init__
inside my class to set properties for objects if I can do it without it with even fewer lines of code in my class?
class SwordsWithoutInit:
damage = 5
class SwordsWithInit:
def __init__(self):
self.damage = 5
big_sword = SwordsWithoutInit()
big_sword.damage = 10
sharp_sword = SwordsWithInit()
sharp_sword.damage = 20
print(f'big sword (class {type(big_sword)}) damage equals {big_sword.damage}')
print(f'sharp sword (class {type(sharp_sword)}) damage equals {sharp_sword.damage}')
# it both works the same way
# note that even if you create another object of class without init, it still will work the same as with init, there won't be any errors
another_sword = SwordsWithoutInit()
another_sword.damage = 33
print(f'big sword (class {type(big_sword)}) damage equals {big_sword.damage}')
print(f'another sword (class {type(another_sword)}) damage equals {another_sword.damage}')
print(f'Class without init still will have damage attribute equals to {SwordsWithoutInit.damage} in itself - we didnt change it')
'''
output:
big sword (class <class '__main__.SwordsWithoutInit'>) damage equals 10
#sharp sword (class <class '__main__.SwordsWithInit'>) damage equals 20
big sword (class <class '__main__.SwordsWithoutInit'>) damage equals 10
another sword (class <class '__main__.SwordsWithoutInit'>) damage equals 33
Class without init still will have damage attribute equals to 5 in itself - we didnt change it
'''