Pydantic Model Field Of Type Union[int, float] : How To Prevent Field From Rounding To int When Initialised With float Value?
Asked Answered
H

3

8

I have the following pydantic model which contains a result typed as Union[int,float] as listed below.

from typing import Union

from pydantic import BaseModel


class Calculation(BaseModel):
    arg1: int 
    arg2: int 


class CalculationResult(Calculation):
    op: str 
    result: Union[int, float]


if __name__ == "__main__":

    arg1 = 1 
    arg2 = 2 
    result = arg1 / arg2

    # this displays type of result := <class 'float'> when program is run
    print(f"type of result := {type(result)}")

    x = CalculationResult(**{"arg1": arg1, "arg2": arg2, "op": "divide", "result": result}) 

    print(f"result := {x.result}")

When the result property of CalculationResult has a value of 0.5 it is rounded to 0.

How do I get pydantic to recognise that 0.5 is a float for the typing hint Union[int, float]?

Hebrews answered 17/12, 2021 at 22:45 Comment(0)
C
7

Modifying the order as mention in @anon_dcs3spp's answer may not be ideal as Union[float, int] would lead to all integers being coerced to floats.

Pydantic added support for smart_union recently which prevents the type-coercion and preserves original types.

So something like below, should work!

class CalculationResult(Calculation): op: str result: Union[int, float]

class CalculationResult(Calculation):
    op: str 
    result: Union[int, float]

    class Config:
       smart_union = True
Cahoot answered 27/3, 2023 at 23:53 Comment(2)
+1 Nice! Thanks for posting this. Have just seen your answer and will accept it as the answer to my original question. Thanks again :)Hebrews
smart_union has been removed in pydantic v2. It is now default github.com/pydantic/pydantic/discussions/7264Phi
H
5

Solved after looking at Pydantic documentation!

The solution is to specify the most specific type first, followed by less general types. In this case, I swapped the order of float and int in the union type declaration.

class CalculationResult(Calculation):
    op: str 
    result: Union[float, int]
Hebrews answered 18/12, 2021 at 9:45 Comment(1)
This doesn't work for float | bool, but Harshith's answer below doesTimeout
P
0

Pydantic v2 allows this by default, therefore this question is irrelevant in 2024. https://github.com/pydantic/pydantic/discussions/7264

Phi answered 8/8 at 13:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.