CitrusBoy
CitrusBoy

Reputation: 179

How can I activate Setter of property whenever the __init__ function is called?

I'm making a program where I want to verify if the induced value is the right one. Imagine I want to create an object with a property called name. That name must be a string, right? Well, I would like to verify this by running this piece of code:

    def SetName(self, name):
        if not isinstance(name, str):
            raise ValueError("It must be a string")
        self._name = name

This is my __init__ :

    def __init__(self, name:str, price:int, note = None) -> None:
        self._name = name
        self._price = price
        self.note = note
        Product.listOfProducts.append(self)

This code works when I input a string, like this:

    Margerita = P.Pizza("Margerita", 15, ["Cheese", "Basil"], 10)

However, if I run:

    Margerita = P.Pizza(5, 15, ["Cheese", "Basil"], 10)

It raises no error.

What can I do to make the property:

    name = property(fget = GetName, fset = SetName)

Work as I described it?

Thank you for your time.

Upvotes: 0

Views: 51

Answers (1)

Christian Karcher
Christian Karcher

Reputation: 3711

Instead of your approach with a dedicated setter function for each argument, you could use dataclasses in combination with a __post_init__ check for a generalized type check:

from dataclasses import dataclass

list_of_products = []

@dataclass
class Pizza:
    name: str
    price: int
    condiments: list

    def __post_init__(self):
        for (name, arg_type) in self.__annotations__.items():
            if not isinstance(self.__dict__[name], arg_type):
                raise TypeError(
                    f"`{name}` must be `{arg_type.__name__}` "
                    f"(was `{self.__dict__[name].__class__.__name__}`)"
                )
        # various other manipulations previously done in your __init__
        list_of_products.append(self)
        # [...]


margerita = Pizza("foo", 15, ["spam"])  # valid
m4rg3rita = Pizza(42, 15, ["spam"])  # <= raises TypeError: `name` must be `str` (was `int`)

Upvotes: 1

Related Questions