Agreed the __pre_init__ idea is no improvement. I think we're back where
you started -- just use `object.__setattr__` to set the attribute in
`__post_init__`. That's what the PEP says is used by the generated
`__init__`, so I think it is reasonable to copy that pattern. Presumably
the situation doesn't occur that frequently in real code (__post_init__
feels like a last resort hack anyway).

On Sat, Feb 17, 2018 at 5:59 PM, Ben Lewis <benlew...@gmail.com> wrote:

> Why can'y you make `name` on `NamedObjectItem` a property that returns `
>> self.obj.name`? Why store a duplicate copy of the name?
>>
>
> Agreed, it's probably a better design not to store a duplicate reference
> to name. But when I tried that, the property clashed with the inherited
> field. This caused the creation of the dataclass to fail as it thought that
> the property was the default value for the field 'name'. Even if I set a
> default for the obj field, it crashed as it tried to set the default value
> for name to the read-only property.
>
> Although I can think of situations where properties wouldn't be sufficent
> as you only want to calculate the value once per instance on creation. My
> thought is that most dataclasses would still be sensible and useful even
> if all mutation ability was removed from them. Taking an example directly
> from the PEP:
>
> @dataclass
> class C:
>     i: int
>     j: int = None
>     database: InitVar[DatabaseType] = None
>
>     def __post_init__(self, database):
>         if self.j is None and database is not None:
>             self.j = database.lookup('j')
>
> Maybe I'm thinking of dataclasses wrong but this still make complete sense
> and is useful even if its declared as frozen.
>
> My thought is that initialisation logic and immutability is orthogonal to
> each other. Possibly initialisation logic like this should occur before the
> instance is created so it would work for immutable types as well.
>
> A possible idea could be, instead of __post_init__, there is __pre_init__
> which allows altering of fields before the instance is created. It would
> take a dict as first argument which contain the field values passed into
> the 'constructor' and default values would also be filled out.
>
> @dataclass
> class C:
>     i: int
>     j: int = None
>     database: InitVar[DatabaseType]
>
>     @classmethod
>     def __pre_init__(cls, fields: Dict[str, Any], database: DatabaseType):
>         if fields['j'] is None and database is not None:
>             fields['j'] = database.lookup('j')
>
> I personally see two problems with this idea:
> 1. This isn't as ergonomic as __post_init__ is as its modifing a
> dictionary instead of its instance.
> 2. To implement this, it would require a metaclass.
>



-- 
--Guido van Rossum (python.org/~guido)
_______________________________________________
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

Reply via email to