!!! abstract "Usage Documentation" [Discriminated Unions with `Callable` `Discriminator`](../concepts/unions.md#discriminated-unions-with-callable-discriminator) Provides a way to use a custom callable as the way to extract the value of a union discriminator. This allows you to get
| 2977 | |
| 2978 | @_dataclasses.dataclass(**_internal_dataclass.slots_true, frozen=True) |
| 2979 | class Discriminator: |
| 2980 | """!!! abstract "Usage Documentation" |
| 2981 | [Discriminated Unions with `Callable` `Discriminator`](../concepts/unions.md#discriminated-unions-with-callable-discriminator) |
| 2982 | |
| 2983 | Provides a way to use a custom callable as the way to extract the value of a union discriminator. |
| 2984 | |
| 2985 | This allows you to get validation behavior like you'd get from `Field(discriminator=<field_name>)`, |
| 2986 | but without needing to have a single shared field across all the union choices. This also makes it |
| 2987 | possible to handle unions of models and primitive types with discriminated-union-style validation errors. |
| 2988 | Finally, this allows you to use a custom callable as the way to identify which member of a union a value |
| 2989 | belongs to, while still seeing all the performance benefits of a discriminated union. |
| 2990 | |
| 2991 | Consider this example, which is much more performant with the use of `Discriminator` and thus a `TaggedUnion` |
| 2992 | than it would be as a normal `Union`. |
| 2993 | |
| 2994 | ```python |
| 2995 | from typing import Annotated, Any, Literal, Union |
| 2996 | |
| 2997 | from pydantic import BaseModel, Discriminator, Tag |
| 2998 | |
| 2999 | class Pie(BaseModel): |
| 3000 | time_to_cook: int |
| 3001 | num_ingredients: int |
| 3002 | |
| 3003 | class ApplePie(Pie): |
| 3004 | fruit: Literal['apple'] = 'apple' |
| 3005 | |
| 3006 | class PumpkinPie(Pie): |
| 3007 | filling: Literal['pumpkin'] = 'pumpkin' |
| 3008 | |
| 3009 | def get_discriminator_value(v: Any) -> str: |
| 3010 | if isinstance(v, dict): |
| 3011 | return v.get('fruit', v.get('filling')) |
| 3012 | return getattr(v, 'fruit', getattr(v, 'filling', None)) |
| 3013 | |
| 3014 | class ThanksgivingDinner(BaseModel): |
| 3015 | dessert: Annotated[ |
| 3016 | Union[ |
| 3017 | Annotated[ApplePie, Tag('apple')], |
| 3018 | Annotated[PumpkinPie, Tag('pumpkin')], |
| 3019 | ], |
| 3020 | Discriminator(get_discriminator_value), |
| 3021 | ] |
| 3022 | |
| 3023 | apple_variation = ThanksgivingDinner.model_validate( |
| 3024 | {'dessert': {'fruit': 'apple', 'time_to_cook': 60, 'num_ingredients': 8}} |
| 3025 | ) |
| 3026 | print(repr(apple_variation)) |
| 3027 | ''' |
| 3028 | ThanksgivingDinner(dessert=ApplePie(time_to_cook=60, num_ingredients=8, fruit='apple')) |
| 3029 | ''' |
| 3030 | |
| 3031 | pumpkin_variation = ThanksgivingDinner.model_validate( |
| 3032 | { |
| 3033 | 'dessert': { |
| 3034 | 'filling': 'pumpkin', |
| 3035 | 'time_to_cook': 40, |
| 3036 | 'num_ingredients': 6, |
no outgoing calls