Python Topics : Common Syntactic Snafus and Pitfalls in Python
Floating Point Arithmetic
floats carry imprecision
such imprecisioncan cause bugs
print(.1 + .2 == .3)  # False
use 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
SignatureDescription
math.isclose(a, b) check if a and b are close using the default relative tolerance
math.isclose(a, b, rel_tol=1e-9) a relative tolerance of 1e-9 is specified
makes the comparison stricter
math.isclose(a, b, abs_tol=1e-9) uses an absolute tolerance
the comparison uses the absolute difference between the values
floating point math can be a challenge
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 int
use float(), list() and dict() for other types
index