Then this is more of an issue with type hints rather than dataclasses. Interesting.
On Mon, Jan 4, 2021, at 16:01, Josue Balandrano Coronel wrote: > Ah, very interesting. > > Just tried this and it worked. That's awesome, thanks! > > On Mon, Jan 4, 2021, at 15:45, Joao S. O. Bueno wrote: > > I think you are complicating things just because there is no easy way > > to tell mypy > > that although you are assigning a descriptor to a class variable > > in the class body, it will be used as a normal instance attribute > > afterwards - and > > it is the type used in the instance attribute that mypy should care for, > > > > And then > > maybe, the specs of static type checking could get a feature to allow > > assigning one thing at class declaration and another thing at instance > > working > > (otherwise, not only dataclasses, but anything using custom descriptors > > would not work with static type checking). > > > > As a workaround, you could just "cast" our descriptor instance to the > > type the attribute will actually hold - mypy should not complain: > > ``` > > @dataclass > > class Item: > > price: Decimal = typing.cast(Decimal, MyDescriptor()) > > > > ``` > > > > On Sun, 3 Jan 2021 at 22:48, Josue Balandrano Coronel > > <j...@rmcomplexity.com> wrote: > > > I've been exploring dataclasses for a few months now and they've proven > > > to be very useful. > > > > > > The only downside is that there's not a simple way to use descriptors. > > > > > > Descriptors only work on class attributes (as per the docs: > > > https://docs.python.org/3/howto/descriptor.html#closing-thoughts). This > > > means that to use a descriptor in a data class we have to use > > > typing.ClassVar like this > > > > > > @dataclass > > > class Item: > > > name: str > > > price: typing.ClassVar[Decimal] = PriceValidator() > > > > > > Which is totally fine because of how descriptors work the previous syntax > > > is a feature in dataclasses, IMHO. > > > > > > But, there's not a straight forward way to pass a value to the descriptor > > > on init. Because ClassVars are not used by @dataclass to do its thing (as > > > per the docs: > > > https://docs.python.org/3/library/dataclasses.html#class-variables) > > > > > > This means that in the example above `price` is not going to be a > > > parameter of the class Item's __init__ method. So the only way to do this > > > is to either create an InitVar field or a regular field and then pass the > > > value to the descriptor in __post_init__ > > > > > > @dataclass > > > class Item: > > > name: str > > > price_val: InitVar[Decimal] > > > price: typing.ClassVar[Decimal] = PriceValidator() > > > > > > def __post_init__(self, price_val: Decimal) -> None: > > > self.price = price_val > > > > > > When using a regular field we can double the field's purpose by making it > > > the field the descriptor is going to use: > > > > > > @dataclass > > > class Item: > > > name: str > > > _price: Decimal > > > price: typing.ClassVar[Decimal] = PriceValidator() > > > > > > def __post_init__(self) -> None: > > > self.price = self._price > > > > > > And then in the descriptor implement __set_name__ like so: > > > > > > def __set_name(self, owner, name): > > > self.name = f"_{name}" > > > > > > > > > Personally, I don't like either option because it adds noice to the data > > > class definition. Using an InitVar is the better option because that > > > variable is clearly defined as init only and it's not present in an > > > instance. Using a regular field adds unnecessary noice to the data class. > > > > > > Also, I think it clashes with the intent of descriptors since they're > > > supposed to manage their data in any way they want. > > > > > > My questions are: > > > > > > - Are my assumptions correct? > > > - Is this the intended behavior? Or what's the preferred way of using a > > > descriptor in a dataclass field? > > > - If this is not intended, could it be possible to add a `descriptor` > > > parameter to the `field` method and treat the field accordingly? > > > > > > I couldn't find any information on the docs or the PEP. I could"ve missed > > > something, sorry if this is the case :) > > > > > > Thanks! > > > > > > -- > > > Josue > > > https://www.rmcomplexity.com > > > _______________________________________________ > > > Python-Dev mailing list -- python-dev@python.org > > > To unsubscribe send an email to python-dev-le...@python.org > > > https://mail.python.org/mailman3/lists/python-dev.python.org/ > > > Message archived at > > > https://mail.python.org/archives/list/python-dev@python.org/message/UOMBDIVNRG3DS6UHWSOF4JTLIPXEENCT/ > > > Code of Conduct: http://python.org/psf/codeofconduct/ > > _______________________________________________ > > Python-Dev mailing list -- python-dev@python.org > > To unsubscribe send an email to python-dev-le...@python.org > > https://mail.python.org/mailman3/lists/python-dev.python.org/ > > Message archived at > > https://mail.python.org/archives/list/python-dev@python.org/message/HRIDJO4VX4F4MNOHODMZJNAOV7NP2VL7/ > > Code of Conduct: http://python.org/psf/codeofconduct/ > > > > -- > https://www.rmcomplexity.com > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/7CFKKYMVEUQV545R4DWXQOPC2F6UJMCY/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- https://www.rmcomplexity.com _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/A6XL5GVEO74VT2OTWZMDS2FUNAC5FN3E/ Code of Conduct: http://python.org/psf/codeofconduct/