Dexter Hill wrote:
> Steve Jorgensen wrote:
> > Would we want something more general that could deal with cases where the 
> > input does not have a 1-to-1 mapping to the field that differ only, 
> > perhaps, in type hint? What if we want 1 argument to initializes 2 
> > properties or vice verse, etc.?
> > That's definitely an improvement that could be made, although I think it 
> > would require a large amount of changes. I don't know if you had syntax in 
> > mind for it, or an easy way to represent it, but at least from what I 
> > understand you would probably a whole new function like `field`, but that 
> > handles just that functionality, otherwise it would add a lot of arguments 
> > to `field`.
> Steve Jorgensen wrote:
> > In any case, having a new `InitFn` is worth digging into, I don't think it 
> > needs to have 2 arguments for type since the type annotation already covers 
> > 1 of those cases. I think it makes the most sense for the type annotation 
> > to apply to the property and the type of the argument to be provided either 
> > through an optional argument to `InitFn` or maybe that can be derived from 
> > the signature of the function that `InitFn` refers to.
> > So the use case would be either this:
> ```py
> @dataclass
> class Foo:
>     x: InitFn[str] = field(converter=chr)
> ```
> where the field `x` has the type string, and the type for the `x` parameter 
> in `__init__` would be derrived from `chr`, or optionally:
> ```py
> @dataclass
> class Foo:
>     x: InitFn[str, int] = field(converter=chr)
> ```
> where you can provide a second type argument that specifies the type 
> parameter for `__init__`?

How about this variation?

Use with `init_using` instead of `converter` as the name of the argument to 
field, allow either a callable or a method name to be supplied, and expect the 
custom init function to behave like `__post_init__` in that it assigns to 
properties rather than returning a converted value. That will allow it to 
initialize more than 1 property. Next, we can say that if the same callable 
object or the same method name is passed to `init_using`, then it is called 
only once. Finally, we say that the class' init argument(s) and their type 
hints are taken from the `init_using` target.

```
@dataclass
class DocumentFile:
    filename: str = field(init_using='_init_name_and_ctype')
    content_type: str = field(init_using='_init_name_and_ctype')
    description: str | None = field(default=None)

    # In this case, the function takes a `file_name` argument which is the same
    # as one of the property names that it initializes, but it could take an 
argument
    # with a completely different name, and the class init would have that as 
its
    # an argument instead.
    def _init_name_and_ctype(self, filename: str | Path = '/tmp/example.txt') 
-> None:
        self.filename = str(filename)
        self.content_type = mimetypes.guess_type(filename)

# Roughly translates to

class DocumentFile:
    filename: str
    content_type: str
    description: str | None

    def __init__(self, filename: str | Path = '/tmp/example.txt', description: 
str | None = None):
        self.description = description
        self._init_name_and_ctype(filename)

    def _init_name_and_ctype(self, file_name: str | Path = '/tmp/example.txt') 
-> None:
        self.file_name = str(file_name)
        self.content_type = mimetypes.guess_type(file_name)
```
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/CGOCLL2YRITOXJWQB55PHYUTYKF4BLSB/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to