Let's say we have a function do_something(item). The parameter item is a class that has an attribute called thing. When this function is called, it needs to perform an operation on item.thing so long as item is not None, and thing is a string. My first thoughts on how to do this were to check if item exists, then check if thing is an instance of a string, in that order. The first line of my code looked something like:
<the things needing done> if item.thing and isinstance(item.thing, str) else <don't do stuff>
My reasoning was something like: Well if item is not None, then it has a thing attribute, so if item.thing returns false then item must be None! Well...turns out this isn't the case, and this mistake cost me two whole marks on Test 2. If item is None, then trying to do anything with any attribute of item will throw an AttributeError, because NoneTypes have no attributes. In order for a bool(item.thing) call to return False, item.thing has to be explicitly initialized to None, or 0, or an empty string, etc. Looking back, this was such a stupid mistake, and it would've been fine if I had just had item instead of item.thing in the first check.
One thing I've noticed about the sample solutions for recursive functions is that they only ever check if the parameter itself exists, not any attributes of the parameter. For whatever reason I've been writing code that tries to avoid passing None as a parameter recursively, but also having to deal with the case that None is passed explicitly from outside the function. Had I noticed this earlier and incorporated it into my own code, the above mistake probably wouldn't have happened =\
<the things needing done> if item.thing and isinstance(item.thing, str) else <don't do stuff>
My reasoning was something like: Well if item is not None, then it has a thing attribute, so if item.thing returns false then item must be None! Well...turns out this isn't the case, and this mistake cost me two whole marks on Test 2. If item is None, then trying to do anything with any attribute of item will throw an AttributeError, because NoneTypes have no attributes. In order for a bool(item.thing) call to return False, item.thing has to be explicitly initialized to None, or 0, or an empty string, etc. Looking back, this was such a stupid mistake, and it would've been fine if I had just had item instead of item.thing in the first check.
One thing I've noticed about the sample solutions for recursive functions is that they only ever check if the parameter itself exists, not any attributes of the parameter. For whatever reason I've been writing code that tries to avoid passing None as a parameter recursively, but also having to deal with the case that None is passed explicitly from outside the function. Had I noticed this earlier and incorporated it into my own code, the above mistake probably wouldn't have happened =\