Sometimes, (but only sometimes) we think that writing too much code is useless and writing less code in python is more readable and performs faster. While in the general case this is true, this article is simply going to show a strange and unwanted error (or feature, if you can sell it this well), that will happen if you use default list as a property in a python class, without setting the property to None.
Imagine that you have the following class:
1 2 3 4 5 6 7 8 9 10 11 12 |
class FootballClub: def __init__(self, players): if players is None: self.players = [] else: self.players = players def add(self, player): self.players.append(player) def remove(self, player): self.players.remove(player) |
Somehow, you might decide to rewrite the __init__ with default empty list in it, in order to remove the if players is None check and to save 3 rows. It will look like this:
1 2 3 |
class StrangeFootballClub: def __init__(self, players=[]): self.players = players |
What can go wrong? Well, if you pass a non empty list every time, when you use the class everything will be ok. But if you create two instances of the StrangeFootballClub class with the default empty list, then strange things will happen – the two instances will refer to the same list. Definitely a bug (unless you really manage to convince someone it is a feature) and black python magic…
Take a look here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
teamA = ['Player1', 'Player2', 'Player3'] teamB = ['Player10', 'Player20', 'Player30'] new_club = FootballClub(teamA) new_club.add('Player4') new_club.remove('Player2') print(new_club.players) #['Player1', 'Player3', 'Player4'] new_club2 = StrangeFootballClub(teamB) print(new_club2.players) #['Player10', 'Player20', 'Player30'] new_club3 = StrangeFootballClub() new_club3.add('Hello') new_club3.add('how') new_club3.add('are') new_club3.add('you') print(new_club3.players) #['Hello', 'how', 'are', 'you'] new_club4 = StrangeFootballClub() print(new_club4.players) #['Hello', 'how', 'are', 'you'] #new_club4.players is obviously the same list as new_club3.players? |
Take home message – do not oversimplify everything, some standard checks are there for a reason!
Enjoy it:)