Floating Point Arithmetic | ||||||||
floats carry imprecision such imprecisioncan cause bugs print(.1 + .2 == .3) # Falseuse the math.isclose function can specify relative or absolute tolerance to use in comparison helps account for small inaccuracies when comparing floats import math print(math.isclose(.1 + .2, .3)) # True print(math.isclose(.1 + .2, .3, rel_tol=1e-9)) # True print(math.isclose(.1 + .2, .3, abs_tol=1e-9)) # True import decimal print(decimal.Decimal('.1') + decimal.Decimal('.2') == decimal.Decimal('.3')) # True
use the decimal.Decimal('value') convert floats to decimals print(decimal.Decimal(.1) + decimal.Decimal(.2) == decimal.Decimal(.3)) # True |
||||||||
Mutable Variables as Arguments | ||||||||
using mutable default arguments in functions can lead to unexpected behavior default argument is only evaluated once when the function is defined, not each time the function is called mutable value is shared among instances the list my_list is shared across all calls to add_to_list def add_to_list(value, my_list=[]): my_list.append(value) return my_list print(add_to_list(1)) # [1] print(add_to_list(2)) # [1, 2], not [2]to avoid unwanted accumulation of values use None as the default value def add_to_list(value, my_list=None): if my_list is None: my_list = [] my_list.append(value) return my_list print(add_to_list(1)) # [1] print(add_to_list(2)) # [2]each call to add_to_list gets a new list if one is not provided |
||||||||
Structural Pattern Matching | ||||||||
a common error is trying to match values and types below an instance is compared with a type match 10: # value case int: # type print("It's an int") case _: print("It's something else!") # It's something else!using int() correctly identifies the value as being of the int type match 10: case int(): print("It's an int") case _: print("It's something else!") # It's an intuse float(), list() and dict() for other types |