Raymond's answer is very fancy and ergonomic, but seems like a lot of magic for something that could be much simpler. A more minimal version would just be to capture the calculated value and just explicitly check whether the things are "close", e.g.:
import math match 1.1 + 2.2: case x if math.isclose(x, 3.3): print(f"{x} is close to 3.3") case x: print(f"{x} wasn't close)
I'd also suggest only using cmath.isclose()
where/when you actually need it, using appropriate types lets you ensure your code is doing what you expect.
The above example is just the minimum code used to demonstrate the matching and, as pointed out in the comments, could be more easily implemented using a traditional if
statement. At the risk of derailing the original question, this is a somewhat more complete example:
from dataclasses import dataclass @dataclass class Square: size: float @dataclass class Rectangle: width: float height: float def classify(obj: Square | Rectangle) -> str: match obj: case Square(size=x) if math.isclose(x, 1): return "~unit square" case Square(size=x): return f"square, size={x}" case Rectangle(width=w, height=h) if math.isclose(w, h): return "~square rectangle" case Rectangle(width=w, height=h): return f"rectangle, width={w}, height={h}" almost_one = 1 + 1e-10 print(classify(Square(almost_one))) print(classify(Rectangle(1, almost_one))) print(classify(Rectangle(1, 2)))
Not sure if I'd actually use a match
statement here, but is hopefully more representative!
*.isclose
are heuristics, and can themselves fail in unexpected ways.math.isclose(a, b)
andmath.isclose(b, c)
but notmath.isclose(a, c)
. (E.g. with default settings,a,b,c = 1, 1.0000000005, 1.0000000015
)