On 27 March 2018 at 00:40, Eric V. Smith <e...@trueblade.com> wrote: > https://bugs.python.org/issue33141 points out an interesting issue with > dataclasses and descriptors. > > Given this code: > > from dataclasses import * > > class D: > """A descriptor class that knows its name.""" > def __set_name__(self, owner, name): > self.name = name > def __get__(self, instance, owner): > if instance is not None: > return 1 > return self > > > @dataclass > class C: > d: int = field(default=D(), init=False) > > C.d.name is not set, because d.__set_name__ is never called. However, in > this case: > > class X: > d: int = D() > > X.d.name is set to 'd' when d.__set_name__ is called during type.__new__. > > The problem of course, is that in the dataclass case, when class C is > initialized, and before the decorator is called, C.d is set to a Field() > object, not to D(). It's only when the dataclass decorator is run that I > change C.d from a Field to the value of D(). That means that the call to > d.__set_name__(C, 'd') is skipped. See > https://www.python.org/dev/peps/pep-0487/#implementation-details for details > on how type.__new__ works. > > The only workaround I can think of is to emulate the part of PEP 487 where > __set_name__ is called. I can do this from within the @dataclass decorator > when I'm initializing C.d. I'm not sure how great this solution is, since > it's moving the call from class creation time to class decorator time. I > think in 99+% of cases this would be fine, but you could likely write code > that depends on side effects of being called during type.__new__. > > Unless anyone has strong objections, I'm going to make the call to > __set_name__ in the @datacalss decorator. Since this is such a niche use > case, I don't feel strongly that it needs to be in today's beta release, but > if possible I'll get it in. I already have the patch written. And if it does > get in but the consensus is that it's a bad idea, we can back it out.
Would it be feasible to define `Field.__set_name__`, and have that call `default.__set_name__` when the latter exists, and be a no-op otherwise? Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com