Thomas <thomas.d.mc...@gmail.com> added the comment:

Hello everyone,

A quick look on SO and Google + this python issue + this blog post and its 
comments: 
https://florimond.dev/en/posts/2018/10/reconciling-dataclasses-and-properties-in-python/
 show that this is still a problem where dataclass users keep hitting a wall.

The gist here seems to be that there's two ways to solve this:
- have descriptor be treated differently when found as default value in the 
__init__. I like this solution. The argument against is that users might want 
to have the descriptor object itself as an instance attribute and this solution 
would prevent them from doing it. I'd argue that, if the user intention was to 
have the descriptor object as a default value, the current dataclass 
implementation allows it in a weird way: as shown above, it actually sets and 
gets the descriptor using the descriptor as its own getter/setter (although it 
makes sense when one thinks of how dataclass are implemented, specifically 
"when" the dataclass modifies the class, it is nonetheless jarring at first 
glance).

- add an "alias/name/public_name/..." keyword to the field constructor so that 
we could write _bar: int = field(default=4, alias="bar"). The idea here keeps 
the usage of this alias to the __init__ method but I'd go further. The alias 
should be used everywhere we need to show the public API of the dataclass 
(repr, str, to_dict, ...). Basically, if a field has an alias, we only ever 
show / give access to the alias and essentially treat the original attribute 
name as a private name (i.e.: if the dataclass maintainer changes the attribute 
name, none of the user code should break).

I like both solutions for the given problem but I still have a preference for 
the first, as it covers more cases that are not shown by the example code: what 
if the descriptor doesn't delegate to a private field on the class? It is a bit 
less common, but one could want to have a field in the init that delegates to a 
resource that is not a field on the dataclass. The first solution allows that, 
the second doesn't.

So I'd like to propose a variation of the first solution that, hopefully, also 
solves the counter argument to that solution:

@dataclass
class FileObject:
    _uploaded_by: str = field(init=False)

    @property
    def uploaded_by(self):
        return self._uploaded_by

    @uploaded_by.setter
    def uploaded_by(self, uploaded_by):
        print('Setter Called with Value ', uploaded_by)
        self._uploaded_by = uploaded_by

    uploaded_by: str = field(default=None, descriptor=uploaded_by)


Basically, add an argument to the field constructor that allows developers to 
tell the dataclass constructor that this field requires special handling: in 
the __init__, it should use the default value as it would do for normal fields 
but at the class level, it should install the descriptor, instead of the 
default value.

What do you think ?

----------
nosy: +Thomas701

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue39247>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to