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 -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/CGOCLL2YRITOXJWQB55PHYUTYKF4BLSB/
Code of Conduct: http://python.org/psf/codeofconduct/