I agree that dataclasses are for a slightly different use case. It looks like this could be implemented as a decorator using the functionality afforded by `inspect.signature`, though what I've come up with so far is a bit clunky because you have to account for parameters that could be positional or keyword and assigning default values for missing arguments.
If this were added, I assume that static analysis tools would need to be updated to account for the assumption that each instance has attributes with the same names that appear in the `__init__` signature, and I have no idea what that would entail. It would probably pose a similar issue for automated refactoring. On Mon, May 4, 2020 at 4:48 PM Lewis Ball <lrjb...@gmail.com> wrote: > I did think about data classes and although I haven't really used them > much they do seem to be for a different use case, for example they don't > support keyword-only args or positional-only args. I'm not sure if there > are any other differences. Maybe a data class which supported kW-only args > and pos-only args would suit my use case. > > On Mon, 4 May 2020, 21:19 Henk-Jaap Wagenaar, <wagenaarhenkj...@gmail.com> > wrote: > >> You are not the first to have this idea. Unless I am mistaken you might >> find what you are looking for in dataclasses which were added in Python 3.7: >> >> https://docs.python.org/3/library/dataclasses.html >> >> On Mon, 4 May 2020 at 19:06, Lewis Ball <lrjb...@gmail.com> wrote: >> >>> Hi All, >>> >>> First of all, if this is something which has been discussed in the past >>> the please point me in the right direction. >>> >>> *Problem:* >>> >>> When creating classes in Python, I find myself writing the __init__ >>> method in a very similar way a lot of the time, that is: >>> ``` >>> def __init__(self, argument_1, argument_2, argument_3=None): >>> self.argument_1 = argument_1 >>> self.argument_2 = argument_2 >>> self.argument_3 = argument_3 >>> # then maybe some other attribute setting and logic follows >>> ``` >>> >>> Every argument of __init__ gets a corresponding attribute with the same >>> name. This means that each `argument_i` has been typed 3 times, which seems >>> overly-verbose as well as being easy to mistype. This pattern is easy to >>> find in various popular python libraries, and in some it is actually >>> enforced. For example, I do quite a bit of work with classifiers using the >>> sklearn estimator API, and for various reasons sklearn enforce this pattern >>> for an __init__ (see here >>> <https://scikit-learn.org/stable/developers/develop.html#instantiation> >>> if interested). >>> >>> Here is an example of this pattern from the standard library (from >>> textwrap.TextWrapper): >>> ``` >>> def __init__(self, >>> width=70, >>> initial_indent="", >>> subsequent_indent="", >>> expand_tabs=True, >>> replace_whitespace=True, >>> fix_sentence_endings=False, >>> break_long_words=True, >>> drop_whitespace=True, >>> break_on_hyphens=True, >>> tabsize=8, >>> *, >>> max_lines=None, >>> placeholder=' [...]'): >>> self.width = width >>> self.initial_indent = initial_indent >>> self.subsequent_indent = subsequent_indent >>> self.expand_tabs = expand_tabs >>> self.replace_whitespace = replace_whitespace >>> self.fix_sentence_endings = fix_sentence_endings >>> self.break_long_words = break_long_words >>> self.drop_whitespace = drop_whitespace >>> self.break_on_hyphens = break_on_hyphens >>> self.tabsize = tabsize >>> self.max_lines = max_lines >>> self.placeholder = placeholder >>> ``` >>> >>> With a quick scan of the top 50 or so most used python packages, *1 in >>> 4* __init__ methods that takes arguments has the line `self.argument_i >>> = argument_i` for every single argument, with several of them having 10+ >>> arguments. >>> >>> *Suggestion:* >>> >>> A new built-in called something like `assign()` which would assign every >>> single __init__ arg to a corresponding attribute. e.g. the snippet from >>> above could be rewritten to: >>> ``` >>> def __init__(self, argument_1, argument_2, argument_3=None): >>> assign() >>> # other init logic goes here >>> ``` >>> >>> This could alternatively be implemented as a decorator, like so >>> ``` >>> @assign >>> def __init__(self, argument_1, argument_2, argument_3=None): >>> # other init logic goes here >>> ``` >>> but then this requires a `pass` if no other logic is needed inside the >>> __init__. There may also be some other syntax for this which would be even >>> easier to use. >>> >>> Is this something that others would find useful? >>> >>> Thanks, >>> >>> Lewis >>> _______________________________________________ >>> 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/VLI3DOFA5VWMGJMJGRDC7JZTRKEPPZNU/ >>> Code of Conduct: http://python.org/psf/codeofconduct/ >>> >> _______________________________________________ > 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/SCTXSEKOWDRDGVXXOEB7JUC6WE7XKGMO/ > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ 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/3QY6NIT7Y37PHKCYGJXJAONS35E3YZWH/ Code of Conduct: http://python.org/psf/codeofconduct/