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, <wagenaarhenkjaap@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 <lrjball@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-leave@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/