On Mon, 4 May 2020 at 19:13, Lewis Ball <lrjb...@gmail.com> wrote: > > I had a similar solution with a decorator using inspect.getfullargspec but it > is pretty fiddly and it is pretty easy to miss > some of the edge cases. Having a standard implementation would definitely > take care of this. And I imagine > static analysis tools would be able to cope with it, they do a good job with > all of the current language features!
I like this idea of having a decorator for that. Since the decorator can apply the arguments to the instance without actually fiddling into `locals` or on `__init__` code. It could also be used _with_ dataclasses, suplying the assignment boiler plate for when one wants to have an explicit __init__ method. (yes, there is post_init, but as seem recently in a thread here, it is tough to get it working cooperatively) But I suppose @autoassign def __init__(self, a, b, flag1, flag2, etcetera): ... could live in "functools" without causing great harm. > > On Mon, 4 May 2020, 22:11 Steele Farnsworth, <swfarnswo...@gmail.com> wrote: >> >> 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 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/ > > _______________________________________________ > 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/4SQF4E3XWQ4XKAS3DMTNYJYJBZEUQIKC/ > 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/6F26QAI7ZOU42FSUHJO3MMBXSY5DY5EU/ Code of Conduct: http://python.org/psf/codeofconduct/