[Python-ideas] Re: Auto assignment of attributes

2022-05-07 Thread Steven D'Aprano
On Sun, May 08, 2022 at 11:02:22AM +1000, Chris Angelico wrote:
> On Sun, 8 May 2022 at 10:23, Steven D'Aprano  wrote:

> > Outside of that narrow example of auto-assignment of attributes, can
> > anyone think of a use-case for this?
> >
> 
> Honestly, I don't know of any. But in response to the objection that
> it makes no sense, I offer the perfectly reasonable suggestion that it
> could behave identically to other multiple assignment in Python.

Nobody says that it makes "no sense". Stephen Turnbull suggested it 
doesn't make "much sense", but in context I think it is clear that he 
meant there are no good uses for generalising this dotted parameter 
name idea, not that we can't invent a meaning for the syntax.


> There's not a lot of places where people use "for x, x.y in iterable",
> but it's perfectly legal. Do we need a use-case for that one to
> justify having it, or is it justified by the simple logic that
> assignment targets are populated from left to right?

The analogy breaks down because we aren't talking about assignment 
targets, but function parameters. Function parameters are only 
*kinda sorta* like assignment targets, and the process of binding 
function arguments passed by the caller to those parameters is not as 
simple as

 self, x, x.y = args

The interpreter also does a second pass using keyword arguments, and a 
third pass assigning defaults if needed. Or something like that -- I 
don't think the precise implementation matters.

Of course we could make it work by giving *some* set of defined 
semantics, but unless it is actually useful, why should we bother? Hence 
my comment YAGNI.


> I'm not advocating for this, but it shouldn't be pooh-poohed just
> because it has more power than you personally can think of uses for.

Power to do *what*?

If nobody can think of any uses for this (beyond the auto-assignment of 
attributes), then what power does it really have?

I don't think "power" of a programming language feature has a purely 
objective, precise definition. But if it did, it would surely have 
something to do with the ability to solve actual problems.


-- 
Steve
___
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/AJEWB5MCHPMKUVJSPMNAU5XTP4F4AX2P/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-07 Thread Chris Angelico
On Sun, 8 May 2022 at 10:23, Steven D'Aprano  wrote:
>
> On Sat, May 07, 2022 at 11:38:19AM -0700, Ethan Furman wrote:
>
> > > I'd define it very simply. For positional args, these should be
> > > exactly equivalent:
> > >
> > > def func(self, x, x.y):
> > >  ...
> > >
> > > def func(*args):
> > >  self, x, x.y = args
> > >  ...
> >
> > Simple or not, I don't think Python needs that much magic.
>
> Indeed. Just because we can imagine semantics for some syntax, doesn't
> make it useful. Aside from the very special case of attribute binding in
> initialisation methods (usually `__init__`), and not even all, or even a
> majority, of those, this is a great example of YAGNI.
>
> Outside of that narrow example of auto-assignment of attributes, can
> anyone think of a use-case for this?
>

Honestly, I don't know of any. But in response to the objection that
it makes no sense, I offer the perfectly reasonable suggestion that it
could behave identically to other multiple assignment in Python.
There's not a lot of places where people use "for x, x.y in iterable",
but it's perfectly legal. Do we need a use-case for that one to
justify having it, or is it justified by the simple logic that
assignment targets are populated from left to right?

I'm not advocating for this, but it shouldn't be pooh-poohed just
because it has more power than you personally can think of uses for.

ChrisA
___
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/63ZZWZI6MVZMUFLU54ASTNPITXFLKGNS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-07 Thread Steven D'Aprano
On Sat, May 07, 2022 at 11:38:19AM -0700, Ethan Furman wrote:

> > I'd define it very simply. For positional args, these should be
> > exactly equivalent:
> >
> > def func(self, x, x.y):
> >  ...
> >
> > def func(*args):
> >  self, x, x.y = args
> >  ...
> 
> Simple or not, I don't think Python needs that much magic.

Indeed. Just because we can imagine semantics for some syntax, doesn't 
make it useful. Aside from the very special case of attribute binding in 
initialisation methods (usually `__init__`), and not even all, or even a 
majority, of those, this is a great example of YAGNI.

Outside of that narrow example of auto-assignment of attributes, can 
anyone think of a use-case for this?

And as far as auto-assignment of attributes goes, I want to remind 
everyone that we have that already, in a simple two-liner:

vars(self).update(locals())
del self.self

which will work for most practical cases where auto-assignment would be 
useful. (It doesn't work with slots though.)

This is a useful technique that isn't widely known enough. I believe 
that if it were more widely know, we wouldn't be having this discussion 
at all.


-- 
Steve
___
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/CTVO5ZA2XUYZTG45DP6HPFQNQOKJKXP7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-07 Thread Ethan Furman

On 5/7/22 06:24, Chris Angelico wrote:
> On Sat, 7 May 2022 at 23:15, Stephen J. Turnbull wrote:
>>
>>  def foo(self, x, y):
>>  x.y = y
>>
>> is not a pattern I can recall ever seeing
>
> I'd define it very simply. For positional args, these should be
> exactly equivalent:
>
> def func(self, x, x.y):
>  ...
>
> def func(*args):
>  self, x, x.y = args
>  ...

Simple or not, I don't think Python needs that much magic.

--
~Ethan~
___
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/AWRAA7MTXHV5SXCBVSK4BMSO2G3EAKX5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-07 Thread Christopher Barker
On Sat, May 7, 2022 at 6:28 AM Chris Angelico  wrote:

> >  > What would this do?
> >  >
> >  > def __init__(self, spam.x, eggs.y): pass
> >  >
> >  > How about this?
> >  >
> >  > def __init__(self, x, x.y): pass
> > IMO, both of those should be errors.  This syntax only makes much
> > sense for the first formal argument of a method definition,


I really don't like this --hard to put my finger on it exactly, but I think
it's because Python doesn't use any magic in method definitions. There is a
touch of magic in binding methods to classes, but that comes later.

so while:

class Foo:
def method(self, ...)

Looks special, that's only because:
- it's defined in the class definition directly
- its using the self convention

But
class Foo:
pass

def method(fred, ...):
pass

Foo.method = method

Means exactly the same thing.

So then we have:

def fun(foo, foo.bar):
...

Is legal, but:

def fun(this, foo, foo.bar):
   ...

Is not.

> it's the only formal argument which has a fixed definition.


yes, but only in one specific context -- so I don't like it leaking out of
that context.


> I'd define it very simply. For positional args, these should be
> exactly equivalent:
>
> def func(self, x, x.y):
> ...
>
> def func(*args):
> self, x, x.y = args
> ...
>

I like that -- it's simple to understand, clear, it doesn't only make sense
for methods, and it might even be useful in other contexts [*].

I think:

def fun(x, y.z):
...
would work fine, too. e.g. you wouldn't be restricted to using other
parameters.

That being said, I'm still -1 on the idea.

[*] -- the "other contexts" is key for me -- if someone can show that this
is a useful pattern in other contexts, I think it would be a stronger
proposal.

-CHB

-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/4OFW6LVJ5DUMUT3O7HL4FFMAUY3QKYOF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-07 Thread Chris Angelico
On Sat, 7 May 2022 at 23:15, Stephen J. Turnbull
 wrote:
>
> Steven D'Aprano writes:
>
>  > What would this do?
>  >
>  > def __init__(self, spam.x, eggs.y): pass
>  >
>  > How about this?
>  >
>  > def __init__(self, x, x.y): pass
>
> IMO, both of those should be errors.  This syntax only makes much
> sense for the first formal argument of a method definition, because
> it's the only formal argument which has a fixed definition.  The form
> "def foo(self, x, x.y)" has an interpretation, I guess, but
>
> def foo(self, x, y):
> x.y = y
>
> is not a pattern I can recall ever seeing, and it could be relatively
> easily relaxed if it were requested enough.  On the other hand, folks
> do frequently request a way to DRY out long suites of "self.x = x"
> assignments.
>

I'd define it very simply. For positional args, these should be
exactly equivalent:

def func(self, x, x.y):
...

def func(*args):
self, x, x.y = args
...

The logical extension to kwargs would work in natural parallel.

ChrisA
___
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/PAG2UK5FY4DRZZHM2VH6AHZC22GGFWF2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-07 Thread Stephen J. Turnbull
Steven D'Aprano writes:

 > What would this do?
 > 
 > def __init__(self, spam.x, eggs.y): pass
 > 
 > How about this?
 > 
 > def __init__(self, x, x.y): pass

IMO, both of those should be errors.  This syntax only makes much
sense for the first formal argument of a method definition, because
it's the only formal argument which has a fixed definition.  The form
"def foo(self, x, x.y)" has an interpretation, I guess, but

def foo(self, x, y):
x.y = y

is not a pattern I can recall ever seeing, and it could be relatively
easily relaxed if it were requested enough.  On the other hand, folks
do frequently request a way to DRY out long suites of "self.x = x"
assignments.

This could, of course, be done with a symbol such as '@' or even '.',
but '@' could also be used for other purposes (late binding, for
example), and "def foo(self, .x, .y):" looks like both grit on Tim's
screen and a typo.  On the other hand, I can't imagine what else might
be meant by "def foo(self, self.x):".

All that said, I'm not a fan of this feature as such.  But giving this
semantics to formal arguments of the form "self.x" is the most
intuitive (in the sense of "hard to give another interpretation") of
the proposals I've seen.

___
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/Z6DHYTG7F27IBER33UN7QOWZSFUQHUNL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-04 Thread Eric V. Smith

On 5/4/2022 1:19 PM, Paul Moore wrote:

Maybe. But really what I want is a way to say "this is what type the
attribute is, but don't assume the init argument is the same type". Or
just not bother with all this at all. This is where it starts to just
become not worth trying to make dataclasses do what I want, I might as
well do it myself via init=False.


Not that it matters much, but you don't need to use init=False, just 
implement your own __init__:


>>> @dataclass
... class C:
...   x: int
...   y: int
...   def __init__(self, x):
... self.x = x
... self.y = x * 2
...
>>> C(3)
C(x=3, y=6)

Eric


___
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/UKOVPQN3MXQ6O2XEZKTEWTXBXIGSUONH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-04 Thread Paul Moore
On Wed, 4 May 2022 at 17:04, Christopher Barker  wrote:
>
> Bringing this back on list -- I hope that was an accident.

If it was, it was me not spotting that your reply to me was on-list, I
thought you're replied offlist so I followed suit. Not a problem
though, I'm fine with this being on-list (although we're quite a lot
off topic now, so others may want me to shut up ;-))

>>  The problem with __post_init__ (I think) is
>> that it confuses the type checkers (beware, untested code below!):
>
> Does the attrs approach work any better for this?

Not notably. But I haven't explored it in detail, I'll be honest -
there's a lot of options, and I may have missed a good one.

>> @dataclass
>> class Metadata:
>> version: str  # Actually a Version, but that's not the type we
>> want the constructor to accept.
>>
>> def __post_init__(self):
>> self.version = Version(self.version)
>>
>> And the reality is worse. We want the constructor to take a Version,
>> or anything that can be converted to a Version
>
>> (which, if I check the
>> source of the library, *is* just str - but I don't want to necessarily
>> copy that declaration as it might change). And yet we want the
>> typechecker to know that metadata.version is always a Version. All of
>> that information is available statically (we call Version on the input
>> data, and self.version is always the result of that call) but I can't
>> see how to explain that to the type checker.
>
>
> Frankly, I see that as a limitation of static typing -- how does one describe 
> "anything that can be turned into a Version? -- sure, the Version __init__ 
> can take either a Version or a str -- but only certain strs will make any 
> sense -- so what's the point?

Well, while I do agree it's a limitation of static typing, if a value
is passed to Version(), the type checker can infer that it must have a
type that matches the argument declaration. The problem is that
there's no way in Python to *describe* that type so that I can use it
in the attribute declaration. So I have to copy the definition. And
anyway, what I want is to say that the *attribute* has type Version,
but the *constructor argument* has a different type. And I don't think
type checkers can handle that, because of how dataclasses work
(auto-generating the init function).

> Honestly, I think if you want your code to be statically "safe" then you 
> should have this metadata class require a Version object, which would require 
> its users to do the conversion first.

Nope, I really shouldn't. The reasons are very specific to the
application logic, but a class that required the user to convert in
advance would be useless to me. (Sure, a complete redesign of the app
might make it possible, but that's not the point).

> Which is why I like the Dynamic nature of Python, and haven't gotten excited 
> about static typing.

I know, and I agree. But having autocompletion in VS Code is nice, and
mypy checks do sometimes pick up on errors. But too much of my time is
taken up trying to work around cases where type checkers get confused
or upset about very dynamic code. And they don't typically degrade
gracefully (by which I mean red "you got this wrong" error bars in my
editor, or errors I don't know how to suppress in mypy without adding
"I know what I'm doing" comments in my code.

So I'm mostly uninterested in adding types, but when I do, I'm
obsessive about getting them right :-(

> I suppose the way to solve this without dataclasses or auto-assignment is to 
> type the class attribute and the __init__ parameter separately, yes?

Possibly, I haven't experimented much. Although it's a PITA if, in

def f(v):
v1 = Version(v)
reveal_type(v1)
reveal_type(v)

type checkers can't infer that v1 is of type Version, and v is of a
type compatible with the argument of Version. Annoyingly, VS Code
appears to get the type of v1, but not of v. And mypy says:

❯ mypy .\tyex.py
tyex.py:5: note: Revealed type is "Any"
tyex.py:5: note: 'reveal_type' always outputs 'Any' in unchecked functions
tyex.py:6: note: Revealed type is "Any"
tyex.py:6: note: 'reveal_type' always outputs 'Any' in unchecked functions

> (which auto-assignment wouldn't help with, either)

Indeed.

[...]
> What this tells me is that if you want dataclasses to be more 
> typing-friendly, then there should be a way to specify the __init__ type 
> separately, which could be done with a parameter to the Field object.

Maybe. But really what I want is a way to say "this is what type the
attribute is, but don't assume the init argument is the same type". Or
just not bother with all this at all. This is where it starts to just
become not worth trying to make dataclasses do what I want, I might as
well do it myself via init=False.

> Bringing it back OT:
>
> As much as I hate to say it: For folks advocating an auto-assignment feature 
> -- you should probably consider how it would play with static typing :-(

That's probably a good point.

Paul

[Python-ideas] Re: Auto assignment of attributes

2022-05-04 Thread Christopher Barker
Bringing this back on list -- I hope that was an accident.

(NOTE: getting a touch off-topic here -- but I do bring it back around at
the end)

On Wed, May 4, 2022 at 4:38 AM Paul Moore  wrote:

> On Tue, 3 May 2022 at 17:46, Christopher Barker 
> wrote:
> > On Tue, May 3, 2022 at 5:39 AM Paul Moore  wrote:
> >>
> >> > > I have classes with 20+ parameters (packaging metadata). You can
> argue
> >> > > that a dataclass would be better,
> >
> > I sure would — I’ve done exactly this, and it seems to me to be exactly
> the right solution.
>
> Sorry, you're right. There are issues with a dataclass based approach
> (I've tried it, so I know ;-)) but they aren't around repeating self.x
> = x over and over. My point here was that the @-based solution isn't
> useful as often as people are claiming.


Agreed here -- I'm probably responsible for much of the talk about
dataclasses, so sorry about that. In fact, my only point there was that
dataclasses are a solution to the "I'm writing many versions of self.x = x
in my __init__ method, and that seems unnecessary" problem, and that I
think that very problem is the strongest case for auto-assignment. Ergo,
auto-assignment isn't a critical feature.


> "lots of
> parameters are simply hard, and in practical cases, @ doesn't help
> enough to make a difference"


Agreed -- if it's a complex case, neither datclasses nor auto-assignment
would help.

I've used attrs, which has field converters.

...

>  The problem with __post_init__ (I think) is
> that it confuses the type checkers (beware, untested code below!):
>

Does the attrs approach work any better for this?


@dataclass
> class Metadata:
> version: str  # Actually a Version, but that's not the type we
> want the constructor to accept.
>
> def __post_init__(self):
> self.version = Version(self.version)
>
> And the reality is worse. We want the constructor to take a Version,
> or anything that can be converted to a Version



> (which, if I check the
> source of the library, *is* just str - but I don't want to necessarily
> copy that declaration as it might change). And yet we want the
> typechecker to know that metadata.version is always a Version. All of
> that information is available statically (we call Version on the input
> data, and self.version is always the result of that call) but I can't
> see how to explain that to the type checker.


Frankly, I see that as a limitation of static typing -- how does one
describe "anything that can be turned into a Version? -- sure, the Version
__init__ can take either a Version or a str -- but only certain strs will
make any sense -- so what's the point?

Honestly, I think if you want your code to be statically "safe" then you
should have this metadata class require a Version object, which would
require its users to do the conversion first.

Which is why I like the Dynamic nature of Python, and haven't gotten
excited about static typing.

I suppose the way to solve this without dataclasses or auto-assignment is
to type the class attribute and the __init__ parameter separately, yes?

(which auto-assignment wouldn't help with, either)

(untested, and probably wrong, 'cause I'm not that familiar with typing)

Class Metadata:
version: Version
...
def __init__(self, version: Version | str, ...):
...
Is that right?

What this tells me is that if you want dataclasses to be more
typing-friendly, then there should be a way to specify the __init__ type
separately, which could be done with a parameter to the Field object.

Bringing it back OT:

As much as I hate to say it: For folks advocating an auto-assignment
feature -- you should probably consider how it would play with static
typing :-(

-CHB





> I'm not obsessive about
> typing, but dataclasses do naturally encourage using them. And if I do
> use types, I want them to be *right*, or VS Code and mypy will spend
> all their time complaining about correct code :-(
>
> This is all irrelevant to the discussion at hand, and quite possibly
> way too nitpicking to even be worth caring about, but it's what I mean
> when I say "things are still hard".
>
> Paul
>


-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/RELK2ZD5VXKH3PPXX4JNY7KGKZSNDN37/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-03 Thread Eric V. Smith
Autocarrot!

--
Eric

> On May 3, 2022, at 8:32 PM, Christopher Barker  wrote:
> 
> 
> 
> Sorry - auto-correct is not my friend :-(
> 
> -CHB
> 
>> On Tue, May 3, 2022 at 12:07 PM Ethan Furman  wrote:
>> On 5/2/22 23:21, Christopher Barker wrote:
>> 
>>  > But yes, there are many use cases not suited to dataclasses. The question 
>> is how many of these would
>>  > rap parge benefit from auto-assigning syntax?
>> 
>> How did you get to "rap parge" from "reap the" ?
>> 
>> 
>> On 5/2/22 20:32, Christopher Barker wrote:
>> 
>>  > Anyway, I think thee we conversation has moved beyond this.
>> 
>> And "thee we" from "that the" ?
>> 
>> Do we get bonus points if we break the code?  ;-)
>> 
>> --
>> ~Ethan~
>> ___
>> 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/U7YHFKV7SBUCQTXM3F3A7SP3M7VIKSBZ/
>> Code of Conduct: http://python.org/psf/codeofconduct/
> -- 
> Christopher Barker, PhD (Chris)
> 
> Python Language Consulting
>   - Teaching
>   - Scientific Software Development
>   - Desktop GUI and Web Development
>   - wxPython, numpy, scipy, Cython
> ___
> 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/3ZDY2Q33AQJOOT65NVVYVPANHPL2GE4R/
> 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/REOE63KAZYHBGO3QS6Z67CPRP22JYJE7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-03 Thread Christopher Barker
Sorry - auto-correct is not my friend :-(

-CHB

On Tue, May 3, 2022 at 12:07 PM Ethan Furman  wrote:

> On 5/2/22 23:21, Christopher Barker wrote:
>
>  > But yes, there are many use cases not suited to dataclasses. The
> question is how many of these would
>  > rap parge benefit from auto-assigning syntax?
>
> How did you get to "rap parge" from "reap the" ?
>
>
> On 5/2/22 20:32, Christopher Barker wrote:
>
>  > Anyway, I think thee we conversation has moved beyond this.
>
> And "thee we" from "that the" ?
>
> Do we get bonus points if we break the code?  ;-)
>
> --
> ~Ethan~
> ___
> 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/U7YHFKV7SBUCQTXM3F3A7SP3M7VIKSBZ/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/3ZDY2Q33AQJOOT65NVVYVPANHPL2GE4R/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-03 Thread Ethan Furman

On 5/2/22 23:21, Christopher Barker wrote:

> But yes, there are many use cases not suited to dataclasses. The question is 
how many of these would
> rap parge benefit from auto-assigning syntax?

How did you get to "rap parge" from "reap the" ?


On 5/2/22 20:32, Christopher Barker wrote:

> Anyway, I think thee we conversation has moved beyond this.

And "thee we" from "that the" ?

Do we get bonus points if we break the code?  ;-)

--
~Ethan~
___
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/U7YHFKV7SBUCQTXM3F3A7SP3M7VIKSBZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-03 Thread Pablo Alcain
On Tue, May 3, 2022 at 6:36 AM Paul Moore  wrote:

> On Tue, 3 May 2022 at 03:04, Steven D'Aprano  wrote:
> >
> > On Mon, May 02, 2022 at 07:44:14PM +0100, Paul Moore wrote:
> >
> > > I have classes with 20+ parameters (packaging metadata). You can argue
> > > that a dataclass would be better, or some other form of refactoring,
> > > and you may actually be right. But it is a legitimate design for that
> > > use case.
> >
> > Indeed. 20+ parameters is only a code smell, it's not *necessarily*
> > wrong. Sometimes you just need lots of parameters, even if it is ugly.
> >
> > For reference, open() only takes 8, so 20 is a pretty wiffy code smell,
> > but it is what it is.
>
> It's worth noting that dataclasses with lots of attributes by default
> generate constructors that require all of those as parameters. So it's
> a code smell yes, but by that logic so are dataclasses with many
> attributes (unless you write a bunch of custom code). Genuine question
> - what *is* a non-smelly way of writing a dataclass with 24
> attributes?
>
> I've written about 20 variations on this particular class so far, and
> none of them feel "right" to me :-(
>
> > > Of course the real problem is that you often don't want to
> > > *quite* assign the argument unchanged - `self.provides_extras =
> > > set(provides_extras or [])` or `self.requires_python = requires_python
> > > or specifiers.SpecifierSet()` are variations that break the whole
> > > "just assign the argument unchanged" pattern.
> >
> > Indeed. Once we move out of that unchanged assignment pattern, we need
> > to read more carefully rather than skim
> >
> > self._spam = (spam or '').lower().strip()
> >
> > but you can't replace that with auto assignment.
>
> Precisely.
>
> > > As a variation on the issue, which the @ syntax *wouldn't* solve, in
> > > classmethods for classes like this, I often find myself constructing
> > > dictionaries of arguments, copying multiple values from one dict to
> > > another, sometimes with the same sort of subtle variation as above:
> > >
> > > @classmethod
> > > def from_other_args(cls, a, b, c, d):
> > > kw = {}
> > > kw["a"] = a
> > > kw["b"] = b
> > > kw["c"] = c
> > > kw["d"] = d
> > > return cls(**kw)
> >
> > You may find it easier to make a copy of locals() and delete the
> > parameters you don't want, rather than retype them all like that:
> >
> > params = locals().copy()
> > for name in ['cls', 'e', 'g']:
> > del params[name]
> > return cls(**params)
> >
> >
> > > Again, in "real code", not all of these would be copied, or some would
> > > have defaults, etc. The pattern's the same, though - enough args
> > > arecopied to make the idea of marking them with an @ seem attractive.
> >
> > But the @ proposal here won't help. If you mark them with @, won't they
> > be auto-assigned onto cls?
>
> Again, precisely.
>
> My point here is that the @ proposal is, in my experience, useful in
> far fewer situations than people are claiming. What *is* common (again
> in my experience) is variations on a pattern that can be described as
> "lots of repetitive copying of values from one location to another,
> possibly with minor modifications". Having a way of addressing the
> broader problem *might* be of sufficient use to be worth pursuing, and
> it might even be possible to do something useful in a library, not
> needing new syntax.
>

It's a good point. We have been thinking a bit about how to measure the
"usefulness" of the proposal. What we have so far is mainly an intuition
driven by code that we and colleagues developed and a couple of statistics (
https://github.com/quimeyps/analize_autoassign in case anyone reading this
doesn't have the link nearby). Although I think that code analysis can be a
way to find out the usefulness of the proposal, the statistics that we have
so far feel a bit coarse-grained to be honest. So any idea on what would be
good metrics to answer the question of "how ofthen the syntax would be
useful" will be more than welcome!

>
> On the other hand, the @ syntax as proposed *doesn't* address enough
> use cases (for me!) to be worthwhile, especially not if new syntax is
> needed rather than just something like a decorator.
>
> Paul
> ___
> 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/CD3HRBE2Q6WIKOJDE5GCLFVVHMGR42VZ/
> 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 

[Python-ideas] Re: Auto assignment of attributes

2022-05-03 Thread Pablo Alcain
On Mon, May 2, 2022 at 11:48 AM Steven D'Aprano  wrote:

> On Mon, May 02, 2022 at 10:34:56AM -0600, Pablo Alcain wrote:
>
> > For what it's worth,
> > the choice of the `@` was because of two different reasons: first,
> because
> > we were inspired by Ruby's syntax (later on learned that CoffeeScript and
> > Crystal had already taken the approach we are proposing) and because the
> > `@` token is already used as an infix for `__matmul__` (
> > https://peps.python.org/pep-0465/). I believe it's the only usage that
> it
> > has, so it probably won't be that confusing to give it this new semantic
> as
> > well.
>
> Did you forget decorators?
>

totally forgot decorators, my bad!


>
> What other languages support this feature, and what syntax do they use?
>

you mean languages other than those two? I haven't found any. In case you
mean the syntax for those two, I know a tiny bit Crystal's. It leverages
the fact that they use `@` for referring to `self`, as in Ruby.

so you would be able to write something like this:

```
class Person
  def initialize(@name : String)
  end

  def greet
print("Hello, ", @name)
  end
end

p = Person.new "Terry"
p.greet
```



>
> Personally, I don't like the idea of introducing syntax which looks
> legal in any function call at all, but is only semantically meaningful
> in methods, and not all methods. Mostly only `__init__`.


Yes, it's a good point. Allowing functions in the wild to use this syntax
would simplify the usage for monkeypatching... but how often would you want
to monkeypatch an `__init__`? and how often would you want to use the
auto-assign outside of the `__init__`? i believe that it's too little. so
in that case, maybe we can make it legal only in all methods. I agree, if
we forego monkeypatching, that semantically it wouldn't be meaningful in
functions; but, in methods, I think that semantically it would make sense
apart from the `__init__`; the thing is that probably it wouldn't be that
useful.


>


> How would this feature work with immutable classes where you want to
> assign attributes to the instance in the `__new__` method?
>
> I fear that this is too magical, too cryptic, for something that people
> only use in a tiny fraction of method. 17% of `__init__` methods is
> probably less than 1% of methods, which means that it is going to be a
> rare and unusual piece of syntax.
>
> Beginners and casual coders (students, scientists, sys admins, etc,
> anyone who dabbles in Python without being immersed in the language) are
> surely going to struggle to recognise where `instance.spam` gets
> assigned, when there is no `self.spam = spam` anywhere in the class or
> its superclasses. There is nothing about "@" that hints that it is an
> assignment.
>
> (Well, I suppose there is that assignment and at-sign both start with A.)
>
> I realise that this will not satisfy those who want to minimize the
> amount of keystrokes, but remembering that code is read perhaps 20-100
> times more than it is written, perhaps we should consider a keyword:
>
> def __init__(self, auto spam:int, eggs:str = ''):
> # spam is automatically bound to self.spam
> self.eggs = eggs.lower()
>
> I dunno... I guess because of that "code is read more than it is
> written" thing, I've never felt that this was a major problem needing
> solving. Sure, every time I've written an __init__ with a bunch of
> `self.spam = spam` bindings, I've felt a tiny pang of "There has to be a
> better way!!!".
>
> But **not once** when I have read that same method later on have I
> regretted that those assignments are explicitly written out, or wished
> that they were implicit and invisible.
>
> Oh, by the way, if *all* of the parameters are to be bound:
>
> def __init__(self, spam, eggs, cheese, aardvark):
> vars(self).update(locals())
> del self.self
>
> Still less magical and more explicit than this auto-assignment proposal.
>
>
>
> --
> Steve
> ___
> 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/C5I33AB2WLW77I77QAJFKZFBJOVNJ7RR/
> 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/JOFVYZG5CSV4C4GVE3QCAKBAENAYROMO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-03 Thread Paul Moore
On Tue, 3 May 2022 at 03:04, Steven D'Aprano  wrote:
>
> On Mon, May 02, 2022 at 07:44:14PM +0100, Paul Moore wrote:
>
> > I have classes with 20+ parameters (packaging metadata). You can argue
> > that a dataclass would be better, or some other form of refactoring,
> > and you may actually be right. But it is a legitimate design for that
> > use case.
>
> Indeed. 20+ parameters is only a code smell, it's not *necessarily*
> wrong. Sometimes you just need lots of parameters, even if it is ugly.
>
> For reference, open() only takes 8, so 20 is a pretty wiffy code smell,
> but it is what it is.

It's worth noting that dataclasses with lots of attributes by default
generate constructors that require all of those as parameters. So it's
a code smell yes, but by that logic so are dataclasses with many
attributes (unless you write a bunch of custom code). Genuine question
- what *is* a non-smelly way of writing a dataclass with 24
attributes?

I've written about 20 variations on this particular class so far, and
none of them feel "right" to me :-(

> > Of course the real problem is that you often don't want to
> > *quite* assign the argument unchanged - `self.provides_extras =
> > set(provides_extras or [])` or `self.requires_python = requires_python
> > or specifiers.SpecifierSet()` are variations that break the whole
> > "just assign the argument unchanged" pattern.
>
> Indeed. Once we move out of that unchanged assignment pattern, we need
> to read more carefully rather than skim
>
> self._spam = (spam or '').lower().strip()
>
> but you can't replace that with auto assignment.

Precisely.

> > As a variation on the issue, which the @ syntax *wouldn't* solve, in
> > classmethods for classes like this, I often find myself constructing
> > dictionaries of arguments, copying multiple values from one dict to
> > another, sometimes with the same sort of subtle variation as above:
> >
> > @classmethod
> > def from_other_args(cls, a, b, c, d):
> > kw = {}
> > kw["a"] = a
> > kw["b"] = b
> > kw["c"] = c
> > kw["d"] = d
> > return cls(**kw)
>
> You may find it easier to make a copy of locals() and delete the
> parameters you don't want, rather than retype them all like that:
>
> params = locals().copy()
> for name in ['cls', 'e', 'g']:
> del params[name]
> return cls(**params)
>
>
> > Again, in "real code", not all of these would be copied, or some would
> > have defaults, etc. The pattern's the same, though - enough args
> > arecopied to make the idea of marking them with an @ seem attractive.
>
> But the @ proposal here won't help. If you mark them with @, won't they
> be auto-assigned onto cls?

Again, precisely.

My point here is that the @ proposal is, in my experience, useful in
far fewer situations than people are claiming. What *is* common (again
in my experience) is variations on a pattern that can be described as
"lots of repetitive copying of values from one location to another,
possibly with minor modifications". Having a way of addressing the
broader problem *might* be of sufficient use to be worth pursuing, and
it might even be possible to do something useful in a library, not
needing new syntax.

On the other hand, the @ syntax as proposed *doesn't* address enough
use cases (for me!) to be worthwhile, especially not if new syntax is
needed rather than just something like a decorator.

Paul
___
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/CD3HRBE2Q6WIKOJDE5GCLFVVHMGR42VZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-03 Thread Christopher Barker
On Mon, May 2, 2022 at 9:30 PM Joao S. O. Bueno 
wrote:

> Anyway, there is something dataclasses do today that prevent you from jsut
> adding a @dataclass for binding __init__ attributes from an otherwise
> "complete class that does things":
>

I nor anyone else ever claimed dataclasses could be used for everything.

You are quite right that you can’t make a dataclass that subclasses a
non-dataclass— particularly when the subclass takes fewer parameters in its
__init__. But that’s a bit of an anti-pattern anyway.

In [17]: from dataclasses import dataclass
>
> In [18]:
>
> In [18]: @dataclass
>...: class A:
>...: a: int
>...: def __post_init__(self, **kwargs):
>...: print(kwargs)
>...:
>
> In [19]: A(1, b=3)
> ---
> TypeError Traceback (most recent call
> last)
> Input In [19], in ()
> > 1 A(1, b=3)
>
> TypeError: A.__init__() got an unexpected keyword argument 'b'
>

Why would you not write that as:

@dataclass
class A:
a: int
b: int
def __post_init__(self, **kwargs):
print(kwargs)

If you really don't want b, you could remove it in the __post_init__ -- but
as stated earlier in this thread, dataclasses are not a good idea if you
have to do a lot of hand-manipulation -- you might as well write a standard
class.

And if you are subclassing, and need to have a parameter passed on to the
superclass, you need to deal with that by hand anyway:

class A(B):
def __init__(self, a):
super.__init__(a, b)

is clearly not going to work, so you do:

class A(B):
def __init__(self, a, b):
super.__init__(a, b)

unless you do:

class A(B):
def __init__(self, a, *args, **kwags):
super.__init__(a, *args, **kwargs)

which is indeed a common pattern, and not supported by datclasses *yet --
there's talk of adding a way to support **kwargs.

The problem with toy examples is that we can have no idea how best to solve
a non-problem -- so we have no idea if the point being made is valid --
it's a challenge.

But yes, there are many use cases not suited to dataclasses. The question
is how many of these would rap parge benefit from auto-assigning syntax?

I re-iterate that while I'd find this an useful addition,
>

I agree.


> I think new syntax for this would be overkill.
>

And I agree there, too.

-CHB
___
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/KC6TXDU5YLAXGV426GUXOBPL7QVW5J5V/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Joao S. O. Bueno
Anyway, there is something dataclasses do today that prevent you from jsut
adding a @dataclass for binding __init__ attributes from an otherwise
"complete class that does things": it overwrites __init__ itself - one hass
to resort to write  "__post_init__" instead,¨

That means that if some class you would like to have all the explicit named
parameters associated as attributes, and then pass other parameters to be
taken care of by the super-class, it simply does not work:


```


In [17]: from dataclasses import dataclass

In [18]:

In [18]: @dataclass
   ...: class A:
   ...: a: int
   ...: def __post_init__(self, **kwargs):
   ...: print(kwargs)
   ...:

In [19]: A(1, b=3)
---
TypeError Traceback (most recent call last)
Input In [19], in ()
> 1 A(1, b=3)

TypeError: A.__init__() got an unexpected keyword argument 'b'

```
No way to have "b" reach "__post_init__" and even less ways to have it be
passed on to any super().__init__ of "A", unless I manually write
A.__init__

A "language dedicated method" to do just the part of auto assigning the
attributes, is much more straightforward than converting the whole thing
into a dataclass.

I re-iterate that while I'd find this an useful addition, I think new
syntax for this would be overkill.

On Tue, May 3, 2022 at 12:34 AM Christopher Barker 
wrote:

> On Mon, May 2, 2022 at 7:42 PM Steven D'Aprano 
> wrote:
>
>> On Sun, May 01, 2022 at 10:40:49PM -0700, Christopher Barker wrote:
>>
>> > Yes, any class  could use this feature (though it's more limited than
>> what
>> > dataclasses do) -- what I was getting is is that it would not be
>> > (particularly) useful for all classes -- only classes where there are a
>> lot
>> > of __init__ parameters that can be auto-assigned. And that use case
>> > overlaps to some extent with dataclasses.
>>
>> Ah, the penny drops! That makes sense.
>>
>>
>> > > Named tuples support all of that too.
>> > >
>> >
>> > No, they don't -- you can add methods, though with a klunky interface,
>>
>> Its the same class+def interface used for adding methods to any class,
>> just with a call to namedtuple as the base class.
>>
>> class Thingy(namedtuple("Thingy", "spam eggs cheese")):
>> def method(self, arg):
>> pass
>>
>> I think it is a beautifully elegant interface.
>>
>>
>> > and they ARE tuples under the hood which does come with restrictions.
>>
>> That is a very good point.
>>
>>
>> > And the
>> > immutability means that added methods can't actually do very much.
>>
>> TIL that string and Decimal methods don't do much.
>>
>> *wink*
>>
>>
>> > > One of the reasons I have not glommed onto dataclasses is that for my
>> > > purposes, they don't seem to add much that named tuples didn't already
>> > > give us.
>> > >
>> >
>> > ahh -- that may be because you think of them as "mutable named tuples"
>> --
>> > that is, the only reason you'd want to use them is if you want your
>> > "record" to be mutable. But I think you miss the larger picture.
>> [...]
>> > I suspect you may have missed the power of datclasses because you
>> started
>> > with this assumption. Maybe it's because I'm not much of a database guy,
>> > but I don't think in terms of records.
>>
>> I'm not a database guy either. When I say record, I mean in the sense of
>> Pascal records, or what C calls structs. A collection of named fields
>> holding data.
>>
>> Objects fundamentally have three properties: identity, state, and
>> behaviour. The behaviour comes from methods operating on the object's
>> state. And that state is normally a collection of named fields holding
>> data. That is, a record.
>>
>> If your class is written in C, like the builtins, you can avoid
>> exposing the names of your data fields, thus giving the illusion from
>> Python that they don't have a name. But at the C level, they have a
>> name, otherwise you can't refer to them from your C code.
>>
>>
>> > For me, datclasses are a way to make a general purpose class that hold a
>> > bunch of data,
>>
>> I.e. a bunch of named fields, or a record :-)
>>
>>
>> > and have the boilerplate written for me.
>>
>> Yes, I get that part.
>>
>> I just find the boilerplate to be less of a cognitive burden than
>> learning the details of dataclasses. Perhaps that's because I've been
>> fortunate enough to not have to deal with classes with vast amounts of
>> boilerplate. Or I'm just slow to recognise Blub features :-)
>>
>>
>> > And what
>> > dataclasses add that makes them so flexible is that they:
>> >
>> > - allow for various custom fields:
>> >- notably default factories to handle mutable defaults
>> > - provide a way to customise the initialization
>> > - and critically, provide a collection of field objects that can be
>> used to
>> > customize behavior.
>>
>> That sounds like a class builder mini-framework.
>
>
> Now you get it :-)
>
> What you describe as 

[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Christopher Barker
On Mon, May 2, 2022 at 7:42 PM Steven D'Aprano  wrote:

> On Sun, May 01, 2022 at 10:40:49PM -0700, Christopher Barker wrote:
>
> > Yes, any class  could use this feature (though it's more limited than
> what
> > dataclasses do) -- what I was getting is is that it would not be
> > (particularly) useful for all classes -- only classes where there are a
> lot
> > of __init__ parameters that can be auto-assigned. And that use case
> > overlaps to some extent with dataclasses.
>
> Ah, the penny drops! That makes sense.
>
>
> > > Named tuples support all of that too.
> > >
> >
> > No, they don't -- you can add methods, though with a klunky interface,
>
> Its the same class+def interface used for adding methods to any class,
> just with a call to namedtuple as the base class.
>
> class Thingy(namedtuple("Thingy", "spam eggs cheese")):
> def method(self, arg):
> pass
>
> I think it is a beautifully elegant interface.
>
>
> > and they ARE tuples under the hood which does come with restrictions.
>
> That is a very good point.
>
>
> > And the
> > immutability means that added methods can't actually do very much.
>
> TIL that string and Decimal methods don't do much.
>
> *wink*
>
>
> > > One of the reasons I have not glommed onto dataclasses is that for my
> > > purposes, they don't seem to add much that named tuples didn't already
> > > give us.
> > >
> >
> > ahh -- that may be because you think of them as "mutable named tuples" --
> > that is, the only reason you'd want to use them is if you want your
> > "record" to be mutable. But I think you miss the larger picture.
> [...]
> > I suspect you may have missed the power of datclasses because you started
> > with this assumption. Maybe it's because I'm not much of a database guy,
> > but I don't think in terms of records.
>
> I'm not a database guy either. When I say record, I mean in the sense of
> Pascal records, or what C calls structs. A collection of named fields
> holding data.
>
> Objects fundamentally have three properties: identity, state, and
> behaviour. The behaviour comes from methods operating on the object's
> state. And that state is normally a collection of named fields holding
> data. That is, a record.
>
> If your class is written in C, like the builtins, you can avoid
> exposing the names of your data fields, thus giving the illusion from
> Python that they don't have a name. But at the C level, they have a
> name, otherwise you can't refer to them from your C code.
>
>
> > For me, datclasses are a way to make a general purpose class that hold a
> > bunch of data,
>
> I.e. a bunch of named fields, or a record :-)
>
>
> > and have the boilerplate written for me.
>
> Yes, I get that part.
>
> I just find the boilerplate to be less of a cognitive burden than
> learning the details of dataclasses. Perhaps that's because I've been
> fortunate enough to not have to deal with classes with vast amounts of
> boilerplate. Or I'm just slow to recognise Blub features :-)
>
>
> > And what
> > dataclasses add that makes them so flexible is that they:
> >
> > - allow for various custom fields:
> >- notably default factories to handle mutable defaults
> > - provide a way to customise the initialization
> > - and critically, provide a collection of field objects that can be used
> to
> > customize behavior.
>
> That sounds like a class builder mini-framework.


Now you get it :-)

What you describe as "flexible" I describe as "overcomplex". All that
> extra complexity to just avoid writing a class and methods.


I don’t think much of that complexity is exposed if you don’t need it.

I'm saying that all classes contain, at their core, a record of named
> fields containing data.


Exactly — which is why data classes can be a base for a lot of use cases.

Anyway, I think thee we conversation has moved beyond this.

-CHB
-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/JY5FLNRRGTYNGFRZBH7EU3U335ZP2MGD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Steven D'Aprano
On Sun, May 01, 2022 at 10:40:49PM -0700, Christopher Barker wrote:

> Yes, any class  could use this feature (though it's more limited than what
> dataclasses do) -- what I was getting is is that it would not be
> (particularly) useful for all classes -- only classes where there are a lot
> of __init__ parameters that can be auto-assigned. And that use case
> overlaps to some extent with dataclasses.

Ah, the penny drops! That makes sense.


> > Named tuples support all of that too.
> >
> 
> No, they don't -- you can add methods, though with a klunky interface,

Its the same class+def interface used for adding methods to any class, 
just with a call to namedtuple as the base class.

class Thingy(namedtuple("Thingy", "spam eggs cheese")):
def method(self, arg):
pass

I think it is a beautifully elegant interface.


> and they ARE tuples under the hood which does come with restrictions.

That is a very good point.


> And the
> immutability means that added methods can't actually do very much.

TIL that string and Decimal methods don't do much.

*wink*


> > One of the reasons I have not glommed onto dataclasses is that for my
> > purposes, they don't seem to add much that named tuples didn't already
> > give us.
> >
> 
> ahh -- that may be because you think of them as "mutable named tuples" --
> that is, the only reason you'd want to use them is if you want your
> "record" to be mutable. But I think you miss the larger picture.
[...]
> I suspect you may have missed the power of datclasses because you started
> with this assumption. Maybe it's because I'm not much of a database guy,
> but I don't think in terms of records.

I'm not a database guy either. When I say record, I mean in the sense of 
Pascal records, or what C calls structs. A collection of named fields 
holding data.

Objects fundamentally have three properties: identity, state, and 
behaviour. The behaviour comes from methods operating on the object's 
state. And that state is normally a collection of named fields holding 
data. That is, a record.

If your class is written in C, like the builtins, you can avoid 
exposing the names of your data fields, thus giving the illusion from 
Python that they don't have a name. But at the C level, they have a 
name, otherwise you can't refer to them from your C code.


> For me, datclasses are a way to make a general purpose class that hold a
> bunch of data, 

I.e. a bunch of named fields, or a record :-)


> and have the boilerplate written for me.

Yes, I get that part.

I just find the boilerplate to be less of a cognitive burden than 
learning the details of dataclasses. Perhaps that's because I've been 
fortunate enough to not have to deal with classes with vast amounts of 
boilerplate. Or I'm just slow to recognise Blub features :-)


> And what
> dataclasses add that makes them so flexible is that they:
> 
> - allow for various custom fields:
>- notably default factories to handle mutable defaults
> - provide a way to customise the initialization
> - and critically, provide a collection of field objects that can be used to
> customize behavior.

That sounds like a class builder mini-framework.

What you describe as "flexible" I describe as "overcomplex". All that 
extra complexity to just avoid writing a class and methods.

Anyway, I'm not trying to discourage you from using dataclasses, or 
persuade you that they are "bad". I'm sure you know your use-cases, and 
I have not yet sat down and given dataclasses a real solid workout. 
Maybe I will come around to them once I do.


> All this makes them very useful for more general purpose classes than a
> simple record.

I'm not saying that all classes *are* a simple record, heavens not!

I'm saying that all classes contain, at their core, a record of named 
fields containing data. Of course classes extend that with all sorts of 
goodies, like inheritance, object identity, methods to operate on that 
data in all sorts of ways, a nice OOP interface, and more.

Anyway, I think I now understand where you are coming from, thank you 
for taking the time to elaborate.


> I'm suggesting that folks find
> evidence for how often auto-assigned parameters would be very useful when
> dataclasses would not.

+1



-- 
Steve
___
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/S25Y3L3HAK6XR2VOI7IDFRPBUMCCBOZ3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Steven D'Aprano
On Mon, May 02, 2022 at 07:44:14PM +0100, Paul Moore wrote:

> I have classes with 20+ parameters (packaging metadata). You can argue
> that a dataclass would be better, or some other form of refactoring,
> and you may actually be right. But it is a legitimate design for that 
> use case.

Indeed. 20+ parameters is only a code smell, it's not *necessarily* 
wrong. Sometimes you just need lots of parameters, even if it is ugly.

For reference, open() only takes 8, so 20 is a pretty wiffy code smell, 
but it is what it is.


> In that sort of case, 20+ lines of assignments in the
> constructor *are* actually rather unreadable, not just a pain to
> write.

I don't know. Its pretty easy to skim lines when reading, especially 
when they follow a pattern:

self.spam = spam
self.eggs = eggs
self.cheese = cheese
self.aardvark = aardvark
self.hovercraft = hovercraft
self.grumpy = grumpy
self.dopey = dopey
self.doc = doc
self.happy = happy
self.bashful = bashful
self.sneezy = sneezy
self.sleepy = sleepy
self.foo = foo
self.bar = bar
self.baz = baz
self.major = major
self.minor = minor
self.minimus = minimus
self.quantum = quantum
self.aether = aether
self.phlogiston = phlogiston

Oh that was painful to write!

But I only needed to write it once, and I bet that 99% of people reading 
it will just skim down the list rather than read each line in full.

To be fair, having written it once, manual refactoring may require me to 
rewrite it again, or at least edit it. In early development, sometimes 
the parameters are in rapid flux, and that's really annoying.

But that's just a minor period of experimental coding, not an on-going 
maintenance issue.


> Of course the real problem is that you often don't want to
> *quite* assign the argument unchanged - `self.provides_extras =
> set(provides_extras or [])` or `self.requires_python = requires_python
> or specifiers.SpecifierSet()` are variations that break the whole
> "just assign the argument unchanged" pattern.

Indeed. Once we move out of that unchanged assignment pattern, we need 
to read more carefully rather than skim

self._spam = (spam or '').lower().strip()

but you can't replace that with auto assignment.


> As a variation on the issue, which the @ syntax *wouldn't* solve, in
> classmethods for classes like this, I often find myself constructing
> dictionaries of arguments, copying multiple values from one dict to
> another, sometimes with the same sort of subtle variation as above:
> 
> @classmethod
> def from_other_args(cls, a, b, c, d):
> kw = {}
> kw["a"] = a
> kw["b"] = b
> kw["c"] = c
> kw["d"] = d
> return cls(**kw)

You may find it easier to make a copy of locals() and delete the 
parameters you don't want, rather than retype them all like that:

params = locals().copy()
for name in ['cls', 'e', 'g']:
del params[name]
return cls(**params)


> Again, in "real code", not all of these would be copied, or some would
> have defaults, etc. The pattern's the same, though - enough args
> arecopied to make the idea of marking them with an @ seem attractive.

But the @ proposal here won't help. If you mark them with @, won't they 
be auto-assigned onto cls?


-- 
Steve
___
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/TPRCJTZJRHVUVSHHPDFXN3O2LDWGZRRB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Paul Moore
On Mon, 2 May 2022 at 18:46, Steven D'Aprano  wrote:
>
> But **not once** when I have read that same method later on have I
> regretted that those assignments are explicitly written out, or wished
> that they were implicit and invisible.

I have classes with 20+ parameters (packaging metadata). You can argue
that a dataclass would be better, or some other form of refactoring,
and you may actually be right. But it is a legitimate design for that
use case. In that sort of case, 20+ lines of assignments in the
constructor *are* actually rather unreadable, not just a pain to
write. Of course the real problem is that you often don't want to
*quite* assign the argument unchanged - `self.provides_extras =
set(provides_extras or [])` or `self.requires_python = requires_python
or specifiers.SpecifierSet()` are variations that break the whole
"just assign the argument unchanged" pattern.

As a variation on the issue, which the @ syntax *wouldn't* solve, in
classmethods for classes like this, I often find myself constructing
dictionaries of arguments, copying multiple values from one dict to
another, sometimes with the same sort of subtle variation as above:

@classmethod
def from_other_args(cls, a, b, c, d):
kw = {}
kw["a"] = a
kw["b"] = b
kw["c"] = c
kw["d"] = d
return cls(**kw)

Again, in "real code", not all of these would be copied, or some would
have defaults, etc. The pattern's the same, though - enough args
arecopied to make the idea of marking them with an @ seem attractive.

Overall, as described I don't think the @arg proposal provides enough
benefit to justify new syntax (and I think trying to extend it would
end badly...). On the other hand, if someone were to come up with a
useful, general way of bulk-copying named values from one "place"[1]
to another, possibly with minor modifications, I think I'd find that
very useful. Call it a DSL for bulk data initialisation, if you like.
I think such a thing could pretty easily be designed as a library. But
I doubt anyone will bother, as adhoc "on the fly" solutions tend to be
sufficient in practice.

Paul

[1] A "place" might be a dictionary - dict["name"] or an object -
getattr(self, "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/Y7KWHYQE7Q7GWEM73RKCT3ITC74LNGPI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Steven D'Aprano
On Mon, May 02, 2022 at 10:34:56AM -0600, Pablo Alcain wrote:

> For what it's worth,
> the choice of the `@` was because of two different reasons: first, because
> we were inspired by Ruby's syntax (later on learned that CoffeeScript and
> Crystal had already taken the approach we are proposing) and because the
> `@` token is already used as an infix for `__matmul__` (
> https://peps.python.org/pep-0465/). I believe it's the only usage that it
> has, so it probably won't be that confusing to give it this new semantic as
> well.

Did you forget decorators?

What other languages support this feature, and what syntax do they use?

Personally, I don't like the idea of introducing syntax which looks 
legal in any function call at all, but is only semantically meaningful 
in methods, and not all methods. Mostly only `__init__`.

How would this feature work with immutable classes where you want to 
assign attributes to the instance in the `__new__` method?

I fear that this is too magical, too cryptic, for something that people 
only use in a tiny fraction of method. 17% of `__init__` methods is 
probably less than 1% of methods, which means that it is going to be a 
rare and unusual piece of syntax.

Beginners and casual coders (students, scientists, sys admins, etc, 
anyone who dabbles in Python without being immersed in the language) are 
surely going to struggle to recognise where `instance.spam` gets 
assigned, when there is no `self.spam = spam` anywhere in the class or 
its superclasses. There is nothing about "@" that hints that it is an 
assignment.

(Well, I suppose there is that assignment and at-sign both start with A.)

I realise that this will not satisfy those who want to minimize the 
amount of keystrokes, but remembering that code is read perhaps 20-100 
times more than it is written, perhaps we should consider a keyword:

def __init__(self, auto spam:int, eggs:str = ''):
# spam is automatically bound to self.spam
self.eggs = eggs.lower()

I dunno... I guess because of that "code is read more than it is 
written" thing, I've never felt that this was a major problem needing 
solving. Sure, every time I've written an __init__ with a bunch of 
`self.spam = spam` bindings, I've felt a tiny pang of "There has to be a 
better way!!!".

But **not once** when I have read that same method later on have I 
regretted that those assignments are explicitly written out, or wished 
that they were implicit and invisible.

Oh, by the way, if *all* of the parameters are to be bound:

def __init__(self, spam, eggs, cheese, aardvark):
vars(self).update(locals())
del self.self

Still less magical and more explicit than this auto-assignment proposal.



-- 
Steve
___
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/C5I33AB2WLW77I77QAJFKZFBJOVNJ7RR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Pablo Alcain
On Mon, May 2, 2022 at 7:21 AM Steven D'Aprano  wrote:

> On Sun, May 01, 2022 at 06:22:08PM -0700, Devin Jeanpierre wrote:
>
> > Is it unreasonable to instead suggest generalizing the assignment target
> > for parameters? For example, if parameter assignment happened left to
> > right, and allowed more than just variables, then one could do:
> >
> > def __init__(self, self.x, self.y): pass
>
> What would this do?
>
> def __init__(self, spam.x, eggs.y): pass
>
> Would it try to assign to variables spam and eggs in the surrounding
> scopes?
>
> How about this?
>
> def __init__(self, x, x.y): pass
>

Yes, I agree. I don't think that the syntax is unreasonable, but it looks
like it would be putting `self` at the same "level" of all the other
possible parameters and could lead to this kind of confusion.

What _might_ be a possibility (I'm not advocating in favor of it) is, like
ruby does, to also add the `@x` as syntactic sugar for `self.x` in the body
of the methods. This way the `@x` in the signature would be consistent, but
I believe it can conflict conceptually with the "explicit self" philosophy.


>
>
> --
> Steve
> ___
> 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/WDRZ7QYQWXCL3QTV4YVIL2YUAS4DNK7I/
> 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/LKVUSGMXYWZHBK432UHL2ACVZOWNWH5P/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Pablo Alcain
On Sun, May 1, 2022 at 10:35 AM Ethan Furman  wrote:

> On 5/1/22 00:21, Christopher Barker wrote:
>  > On Sat, Apr 30, 2022 at 2:17 PM Pablo Alcain wrote:
>
>
>  >> It shows that out of 20k analyzed classes in the selected libraries
> (including black,
>  >> pandas, numpy, etc), ~17% of them could benefit from the usage of
> auto-assign syntax.
>  >
>  > I only read English, and haven't studied the coe, so I don't know how
> that works, but
>  > assuming it's accurately testing for the simple cases that
> auto-assigning could work for;
>  >
>  > That's not that much actually --  for approx every six-parameter
> function, one of them
>  > could be auto-assigned.or for every six functions, one could make good
> use of auto-
>  > assignment (and maybe be a dataclass?)
>
> I think you place too much emphasis on dataclasses -- none of my projects
> use them, nor could they.
>
> Going through a one of my smaller projects, this is what I found:
>
> - number of `__init__`s: 11
> - number of total params (not counting self): 25
> - number of those params assigned as-is: 19
> - number of `__init__`s where all are assigned as-is: 6
> - number of non-`__init__`s where this would useful: 0
>
>
>  > And I'm not trying to be a Negative Nelly here -- I honestly don't
> know, I actually
>  > expected it to be higher than 17% -- but in any case, I think it should
> be higher than
>  > 17% to make it worth a syntax addition.
>
> 17% is a massive amount of code.
>
>  > But pandas and numpy may not be the least bit representative [...]?
>
> This would not be the first time Python was improved to help the
> scientific community.
>
> My own thoughts about the proposal:  It seems interesting, and assigning
> as-is arguments is a chore -- but I'm not sure
> using up a token to help only one method per class is a good trade.
>

Yes, I agree that the cost/benefit should be analyzed. For what it's worth,
the choice of the `@` was because of two different reasons: first, because
we were inspired by Ruby's syntax (later on learned that CoffeeScript and
Crystal had already taken the approach we are proposing) and because the
`@` token is already used as an infix for `__matmul__` (
https://peps.python.org/pep-0465/). I believe it's the only usage that it
has, so it probably won't be that confusing to give it this new semantic as
well. All of this, I believe, mitigate the "using up a token", but it's not
enough to make it a clear decision, so I 100% agree with your concern.



>
> --
> ~Ethan~
> ___
> 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/2GR5G67IKJZDSFU4QYJQF7R4BCZUZPMJ/
> 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/V4TF6WRERLQBOQ72BGWHYAXCYX6MCT6J/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Steven D'Aprano
On Mon, May 02, 2022 at 05:57:45PM +0900, Stephen J. Turnbull wrote:

> def __init__(s, s.x, s.y): pass

I think that if this proposal threatens to encourage people to write 
that horro, that would be enough of a reason to reject it.

-- 
Steve
___
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/JW35VR36AF3NP2KTDGORHKQZOST2LUSI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Steven D'Aprano
On Sun, May 01, 2022 at 06:22:08PM -0700, Devin Jeanpierre wrote:

> Is it unreasonable to instead suggest generalizing the assignment target
> for parameters? For example, if parameter assignment happened left to
> right, and allowed more than just variables, then one could do:
> 
> def __init__(self, self.x, self.y): pass

What would this do?

def __init__(self, spam.x, eggs.y): pass

Would it try to assign to variables spam and eggs in the surrounding 
scopes?

How about this?

def __init__(self, x, x.y): pass


-- 
Steve
___
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/WDRZ7QYQWXCL3QTV4YVIL2YUAS4DNK7I/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-02 Thread Stephen J. Turnbull
Devin Jeanpierre writes:

 > Is it unreasonable to instead suggest generalizing the assignment target
 > for parameters? For example, if parameter assignment happened left to
 > right, and allowed more than just variables, then one could do:
 > 
 > def __init__(self, self.x, self.y): pass

At a glance, this is the most attractive syntax I've seen for this.
If you're a keystroke minimizer, you can't do quite as well as

def __init__(self, @x, @y): pass

but

def __init__(s, s.x, s.y): pass

isn't bad at all.


 > 
 > Python 2 had non-variable parameters (but not attributes, just unpacking:
 > def foo((x, y)): pass), but it was removed in Python 3, because of issues
 > with introspection (among other, perhaps less significant, issues):
 > https://peps.python.org/pep-3113/
 > 
 > Perhaps now that positional-only parameters exist, and the introspection
 > APIs have evolved over time, there is a way to work this into the
 > introspection APIs sensibly.
 > 
 > (a "@foo" parameter does not have this problem, because it's just a
 > parameter named `foo` with some extra stuff.)
 > 
 > -- Devin
 > ___
 > 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/UY2TQTPRFAPN3OG3TBPCOYMAYZWFZ3E4/
 > 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/KBWASQWSLY2TAOTU6KKJI433SGOFM2JX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-01 Thread Christopher Barker
On Sun, May 1, 2022 at 1:16 AM Steven D'Aprano  wrote:

> > > On Sat, Apr 23, 2022 at 12:11:07PM -0700, Christopher Barker wrote:
> > > > Absolutely. However, this is not an "all Classes" question.
> > > Isn't it? I thought this was a proposal to allow any class to partake
> in
> > > the dataclass autoassignment feature.
>

Yes, any class  could use this feature (though it's more limited than what
dataclasses do) -- what I was getting is is that it would not be
(particularly) useful for all classes -- only classes where there are a lot
of __init__ parameters that can be auto-assigned. And that use case
overlaps to some extent with dataclasses.

Perhaps your answer isn't as clear as you think it is.
>

apparently not.


> > > > But do think they are for classes that are primarily about storing a
> > > > defined set of data.
> > >
> > > Ah, mutable named tuples, with or without defaults? :-)
>

"primarily" -- but the key difference is that dataclasses are far more
customisable and flexible.

They are more like "classes with boiler plate dunders auto-generated"

That is, a lot more like "regular" classes than they are like tuples.
Whereas namedtupels are , well, tuples where the item have names. That's
kinda it.

 > well, no. - the key is that you can add other methods to them, and
produce

> > all sort of varyingly complex functionality.
>
> Named tuples support all of that too.
>

No, they don't -- you can add methods, though with a klunky interface, and
they ARE tuples under the hood which does come with restrictions. And the
immutability means that added methods can't actually do very much.

One of the reasons I have not glommed onto dataclasses is that for my
> purposes, they don't seem to add much that named tuples didn't already
> give us.
>

ahh -- that may be because you think of them as "mutable named tuples" --
that is, the only reason you'd want to use them is if you want your
"record" to be mutable. But I think you miss the larger picture.


> * Record- or struct-like named fields? Check.
>
> * Automatic equality? Check.
>
> * Nice repr? Check.
>
> * Can add arbitrary methods and override existing methods? Check.
>

that's a little klunky though, isn't it? Have you seen much use of named
tuples like that? For that matter do folks do that with tuples much either?

Perhaps named tuples offer *too much**:
>
> * Instances of tuple;
> * Equality with other tuples;
>

Yes, that can be a downside, indeed.

and maybe dataclasses offer some features I haven't needed yet, but it
> seems to me that named tuples and dataclasses are two solutions to the
> same problem: how to create a record with named fields.
>

I suspect you may have missed the power of datclasses because you started
with this assumption. Maybe it's because I'm not much of a database guy,
but I don't think in terms of records.

For me, datclasses are a way to make a general purpose class that hold a
bunch of data, and have the boilerplate written for me. And what
dataclasses add that makes them so flexible is that they:

- allow for various custom fields:
   - notably default factories to handle mutable defaults
- provide a way to customise the initialization
- and critically, provide a collection of field objects that can be used to
customize behavior.

All this makes them very useful for more general purpose classes than a
simple record.

I guess a way to think if them is this:

if you are writing a class in which the __init__ assigns most of the
parameters to the instance, then a dataclass could be helpful.

which is why I think they solve *part* of the problem that special auto
assigning syntax would solve.

Not all of the problem, which is why I'm suggesting that folks find
evidence for how often auto-assigned parameters would be very useful when
dataclasses would not.

So I don't understand what you think dataclasses are, if you vehemently
> deny that they are records (not just one nope, but three).
>

It's not that they can't be used as records, it's that they can be so much
more. After all what is any class but a collection of attributes (some of
which may be methods) ?


> And since I don't understand your concept of dataclasses, I don't know
> how to treat your position in this discussion. Should I treat it as
> mainstream, or idiosyncratic? Right now, it seems pretty idiosyncratic.
>

perhaps it is -- the mainstream may not have noticed how much one can do
with dataclasses.

> But anyway, the rest of my post was the real point, and we're busy arguing
> > semantics here.
>
> Well yes, because if we don't agree on semantics, we cannot possibly
> communicate.


sure -- I should have been more explicit -- arguing about what "mutable
named tuple" means didn't seem useful.

But in retrospect I was wrong -- it may matter to this discussion, and
that's why I originally pointed out that I don't think of dataclasses as
"mutable named tuples" -- perhaps I should have said not *only* mutable
named tuples.

The relevant point here is that 

[Python-ideas] Re: Auto assignment of attributes

2022-05-01 Thread Devin Jeanpierre
On Sun, May 1, 2022 at 9:35 AM Ethan Furman  wrote:

> My own thoughts about the proposal:  It seems interesting, and assigning
> as-is arguments is a chore -- but I'm not sure
> using up a token to help only one method per class is a good trade.
>

Is it unreasonable to instead suggest generalizing the assignment target
for parameters? For example, if parameter assignment happened left to
right, and allowed more than just variables, then one could do:

def __init__(self, self.x, self.y): pass

Python 2 had non-variable parameters (but not attributes, just unpacking:
def foo((x, y)): pass), but it was removed in Python 3, because of issues
with introspection (among other, perhaps less significant, issues):
https://peps.python.org/pep-3113/

Perhaps now that positional-only parameters exist, and the introspection
APIs have evolved over time, there is a way to work this into the
introspection APIs sensibly.

(a "@foo" parameter does not have this problem, because it's just a
parameter named `foo` with some extra stuff.)

-- Devin
___
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/UY2TQTPRFAPN3OG3TBPCOYMAYZWFZ3E4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-01 Thread Ethan Furman

On 5/1/22 00:21, Christopher Barker wrote:
> On Sat, Apr 30, 2022 at 2:17 PM Pablo Alcain wrote:


>> It shows that out of 20k analyzed classes in the selected libraries 
(including black,
>> pandas, numpy, etc), ~17% of them could benefit from the usage of 
auto-assign syntax.
>
> I only read English, and haven't studied the coe, so I don't know how that 
works, but
> assuming it's accurately testing for the simple cases that auto-assigning 
could work for;
>
> That's not that much actually --  for approx every six-parameter  function, 
one of them
> could be auto-assigned.or for every six functions, one could make good use of 
auto-
> assignment (and maybe be a dataclass?)

I think you place too much emphasis on dataclasses -- none of my projects use 
them, nor could they.

Going through a one of my smaller projects, this is what I found:

- number of `__init__`s: 11
- number of total params (not counting self): 25
- number of those params assigned as-is: 19
- number of `__init__`s where all are assigned as-is: 6
- number of non-`__init__`s where this would useful: 0


> And I'm not trying to be a Negative Nelly here -- I honestly don't know, I 
actually
> expected it to be higher than 17% -- but in any case, I think it should be 
higher than
> 17% to make it worth a syntax addition.

17% is a massive amount of code.

> But pandas and numpy may not be the least bit representative [...]?

This would not be the first time Python was improved to help the scientific 
community.

My own thoughts about the proposal:  It seems interesting, and assigning as-is arguments is a chore -- but I'm not sure 
using up a token to help only one method per class is a good trade.


--
~Ethan~
___
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/2GR5G67IKJZDSFU4QYJQF7R4BCZUZPMJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-01 Thread Steven D'Aprano
On Sat, Apr 30, 2022 at 11:54:47PM -0700, Christopher Barker wrote:
> On Sat, Apr 30, 2022 at 6:40 PM Steven D'Aprano  wrote:
> 
> > On Sat, Apr 23, 2022 at 12:11:07PM -0700, Christopher Barker wrote:
> > > Absolutely. However, this is not an "all Classes" question.
> >
> > Isn't it? I thought this was a proposal to allow any class to partake in
> > the dataclass autoassignment feature.
> >
> 
> no -- it's about only a small part of that.

How so? Dataclasses support autoassignment. This proposes to allow 
**all classes** (including non-dataclasses) to also support 
autoassignment.

So can you pleae clarify your meaning. To me, this does look like an 
"all Classes" question. What am I missing?


> > > I don't think of dataclasses as "mutable namedtuples with defaults" at
> > all.
> > What do you think of them as?
> >
> 
> I answered that in the next line, that you quote.

Perhaps your answer isn't as clear as you think it is. See below.


> > > But do think they are for classes that are primarily about storing a
> > > defined set of data.
> >
> > Ah, mutable named tuples, with or without defaults? :-)
> >
> 
> well, no. - the key is that you can add other methods to them, and produce
> all sort of varyingly complex functionality. I have done that myself.

Named tuples support all of that too.

One of the reasons I have not glommed onto dataclasses is that for my 
purposes, they don't seem to add much that named tuples didn't already 
give us.

* Record- or struct-like named fields? Check.

* Automatic equality? Check.

* Nice repr? Check.

* Can add arbitrary methods and override existing methods? Check.

Perhaps named tuples offer *too much**:

* Instances of tuple;

* Equality with other tuples;

and maybe dataclasses offer some features I haven't needed yet, but it 
seems to me that named tuples and dataclasses are two solutions to the 
same problem: how to create a record with named fields.


> > Or possibly records/structs.
> >
> 
> nope, nope, and nope.

Okay, I really have no idea what you think dataclasses are, if you don't 
think of them as something like an object-oriented kind of record or 
struct (a class with named data fields).

You even define them in terms of storing a defined set of data, except 
you clearly don't mean a set in the mathematical meaning of an unordered 
collection (i.e. set()). A set of data is another term for a record.

So I don't understand what you think dataclasses are, if you vehemently
deny that they are records (not just one nope, but three).

And since I don't understand your concept of dataclasses, I don't know 
how to treat your position in this discussion. Should I treat it as 
mainstream, or idiosyncratic? Right now, it seems pretty idiosyncratic.

Maybe that's because I don't understand you. See below.


> But anyway, the rest of my post was the real point, and we're busy arguing
> semantics here.

Well yes, because if we don't agree on semantics, we cannot possibly 
communicate. Semantics is the **meaning of our words and concepts**. If 
we don't agree on what those words mean, then how do we understand each 
other?

I've never understood people who seem to prefer to talk past one another 
with misunderstanding after misunderstanding rather than "argue 
semantics" and clarify precisely what they mean.


-- 
Steve
___
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/WYQA2TFZEVVQRFMWBBJXSFA4WXKYNZWT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-01 Thread Christopher Barker
On Sat, Apr 30, 2022 at 2:17 PM Pablo Alcain  wrote:

>
>>> B) Most __init__ params need specialized behavior, and are quite
>> distinct from what's needed by __eq__ and __repr__
>>
>> (B) is well covered by the current, you-need-to-specify-everything
>> approach.
>>
>
> I don’t see B as a “extreme approach”.
>

It's not and "extreme" approach -- it's one end of a continuum.


> I think that comparing python classes with the specific dataclass is not
> helpful. The B scenario is simply the
>


> $ grep -Ie "self\.\(\w\+\) = \1" -r cpython/Lib | wc
> 2095
>
> I did the same in two libraries that I use regularly: pandas and
> scikit-learn:
>
> $ grep -Ie "self\.\(\w\+\) = \1" -r sklearn | wc -l
> 1786
>
> $ grep -Ie "self\.\(\w\+\) = \1" -r pandas | wc -l
> 650
>
> That’s a total of ~4.5k lines of code (again, this is an overestimation,
> but it can give us an idea of the ballpark estimate)
>

That, well, is pretty much useless, if I understand the re correctly -- the
fact that a class is assigning to self doesn't mean it's directly assigning
the parameters with no other logic. And any number of those self
assignments could be in non-__init__ methods. All that shows is that
instance attributes are used. I don't think anyone is questioning that.

For a better and more fine-grained analysis, Quimey wrote this small
> library (https://github.com/quimeyps/analize_autoassign) that uses the
> Abstract Syntax Tree to analyze a bunch of libraries and identify when the
> “autoassign” could work.
>

It shows that out of 20k analyzed classes in the selected libraries
> (including black, pandas, numpy, etc), ~17% of them could benefit from the
> usage of auto-assign syntax.
>

I only read English, and haven't studied the coe, so I don't know how that
works, but assuming it's accurately testing for the simple cases that
auto-assigning could work for;

That's not that much actually --  for approx every six-parameter  function,
one of them could be auto-assigned.

or for every six functions, one could make good use of auto-assignment (and
maybe be a dataclass?)

So it looks like the isolated pattern of `self. = `
> is used a lot.
>

I don't think that's ever been in question. The question, as I see it, is
what fraction of parameters could get auto-assigned in general -- for
classes where dataclasses wouldn't make sense.

And I'm not trying to be a Negative Nelly here -- I honestly don't know, I
actually expected it to be higher than 17% -- but in any case, I think it
should be higher than 17% to make it worth a syntax addition.

But pandas and numpy may not be the least bit representative -- maybe run
the most popular packages on PyPi?

I thought I made this point, but it seems to have gotten lost:

What I'm saying is that, for example, if a class __init__ has 6 parameters,
and one of them could be auto-assigned, then yes, auto-assigning could be
used, but you really haven't gained much from that -- it would not be worth
the syntax change.

And any class with an __init__ in which most or all parameters could be
auto-assigned -- then those might be a good candidate for a dataclass.

So how many are there where say, more than half of  __init__
parameters could be auto-assigned, where dataclasses wouldn't be helpful? A
lot? then, yes, new syntax may be warranted.

But, obviously, it entails a further of discussion whether it makes sense
> to add new syntax for this, considering the maintenance that it implies.
>

It's not so much the maintenance -- it's the transition burden, and the
burden of yet more complexity in the language, particularly
parameters/arguments:

Try to teach a newbie about arguments/parameters in Python, there is a
remarkable complexity there already:

positional vs keyword
*args, **kwargs
keyword-only.

(and all of these from both the caller and callee perspective)

That's a lot of possible combinations -- believe me, it's pretty darn
complex and hard to explain!

-CHB

-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/QLYDWJBVMVKRE2RRN7WFCVUQWOEFMHOE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-05-01 Thread Christopher Barker
On Sat, Apr 30, 2022 at 6:40 PM Steven D'Aprano  wrote:

> On Sat, Apr 23, 2022 at 12:11:07PM -0700, Christopher Barker wrote:
> > Absolutely. However, this is not an "all Classes" question.
>
> Isn't it? I thought this was a proposal to allow any class to partake in
> the dataclass autoassignment feature.
>

no -- it's about only a small part of that.


> > I don't think of dataclasses as "mutable namedtuples with defaults" at
> all.
> What do you think of them as?
>

I answered that in the next line, that you quote.

>
> > But do think they are for classes that are primarily about storing a
> > defined set of data.
>
> Ah, mutable named tuples, with or without defaults? :-)
>

well, no. - the key is that you can add other methods to them, and produce
all sort of varyingly complex functionality. I have done that myself.


> Or possibly records/structs.
>

nope, nope, and nope.

But anyway, the rest of my post was the real point, and we're busy arguing
semantics here.

-CHB

-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/FASJHCH5OV453YGZAFAJ5GHGKS45MVII/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-30 Thread Steven D'Aprano
On Sat, Apr 23, 2022 at 12:11:07PM -0700, Christopher Barker wrote:
> On Sat, Apr 23, 2022 at 10:53 AM Pablo Alcain  wrote:
> 
> > Overall, I think that not all Classes can be thought of as Dataclasses
> > and, even though dataclasses solutions have their merits, they probably
> > cannot be extended to most of the other classes.
> >
> 
> Absolutely. However, this is not an "all Classes" question.

Isn't it? I thought this was a proposal to allow any class to partake in 
the dataclass autoassignment feature.

(Not necessarily the implementation.)


> I don't think of dataclasses as "mutable namedtuples with defaults" at all.

What do you think of them as?


> But do think they are for classes that are primarily about storing a
> defined set of data.

Ah, mutable named tuples, with or without defaults? :-)

Or possibly records/structs.


-- 
Steve
___
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/T2AWTW54AW5SNJSNDCZ6YNK2T6QWNLQT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-30 Thread Pablo Alcain
On Sat, Apr 23, 2022, 1:11 PM Christopher Barker 
wrote:

> On Sat, Apr 23, 2022 at 10:53 AM Pablo Alcain 
> wrote:
>
>> Overall, I think that not all Classes can be thought of as Dataclasses
>> and, even though dataclasses solutions have their merits, they probably
>> cannot be extended to most of the other classes.
>>
>
> Absolutely. However, this is not an "all Classes" question.
>
> I don't think of dataclasses as "mutable namedtuples with defaults" at all.
>

Although I agree that dataclasses have definitely grown beyond this scope,
the definition of “mutable namedtuples with defaults” come from the
original PEP (https://peps.python.org/pep-0557/#abstract). The main point
here is that there are several usecases for classes that do not fit
conceptually the “dataclass” goal.


> But do think they are for classes that are primarily about storing a
> defined set of data.
>
> I make heavy use of them for this, when I am adding quite a bit of
> ucntionatily, but their core function is still to store a collection of
> data. To put it less abstractly:
>
> Dataclasses are good for classes in which the collection of fields is a
> primary focus -- so the auto-generated __init__, __eq__ etc are appropriate.
>
> It's kind of a recursive definition: dataclasses work well for those
> things that data classes' auto generated methods work well for :-)
>
> If, indeed, you need a lot of custom behavior for teh __init__, and
> __eq__, and ... then datclasses are not for you.
>

I agree 100%. This proposal, at its core, is not related with dataclasses.
There are some cases in which dataclasses are the solution, but there are
many many times in which you will want to use just classes.

>
> And the current Python class system is great for fully customized
> behaviour. It's quite purposeful that parameters of the __init__ have no
> special behavior, and that "self" is explicit -- it gives you full
> flexibility, and everything is explicit. That's a good thing.
>
> But, of course, the reason this proposal is on the table (and it's not the
> first time by any means) is that it's a common pattern to assign (at least
> some of) the __init__ parameters to instance attributes as is.
>
> So we have two extremes -- on one hand:
>
> A) Most __init__ params are assigned as instance attributes as is, and
> these are primarily needed for __eq__ and __repr__
>
> and on the other extreme:
>
> B) Most __init__ params need specialized behavior, and are quite distinct
> from what's needed by __eq__ and __repr__
>
> (A) is, of course, the entire point of dataclasses, so that's covered.
>
> (B) is well covered by the current, you-need-to-specify-everything
> approach.
>

I don’t see B as a “extreme approach”. I think that comparing python
classes with the specific dataclass is not helpful. The B scenario is
simply the general case for class usage. Scenario A, I agree, is a very
common one and fortunately we have dataclasses for them.


> So the question is -- how common is it that you have code that's far
> enough toward the (A) extreme as far as __init__ params being instance
> attributes that we want special syntax, when we don't want most of the
> __eq__ and __repr__ behaviour.
>

I agree that this is the main question. For what it’s worth, a quick grep
on the stdlib (it’s an overestimation) provides:

$ grep -Ie "self\.\(\w\+\) = \1" -r cpython/Lib | wc
2095

I did the same in two libraries that I use regularly: pandas and
scikit-learn:

$ grep -Ie "self\.\(\w\+\) = \1" -r sklearn | wc -l
1786

$ grep -Ie "self\.\(\w\+\) = \1" -r pandas | wc -l
650

That’s a total of ~4.5k lines of code (again, this is an overestimation,
but it can give us an idea of the ballpark estimate)

For a better and more fine-grained analysis, Quimey wrote this small
library (https://github.com/quimeyps/analize_autoassign) that uses the
Abstract Syntax Tree to analyze a bunch of libraries and identify when the
“autoassign” could work. It shows that out of 20k analyzed classes in the
selected libraries (including black, pandas, numpy, etc), ~17% of them
could benefit from the usage of auto-assign syntax.

So it looks like the isolated pattern of `self. = `
is used a lot. I don’t think that moving all of these cases to dataclasses
can provide a meaningful solution. When I take a look at these numbers (and
reflect in my own experience and my colleagues) it looks like there is a
use case for this feature. And this syntax modification looks small and
kind of clean, not adding any boilerplate. But, obviously, it entails a
further of discussion whether it makes sense to add new syntax for this,
considering the maintenance that it implies.


> In my experience, not all that much -- my code tends to be on one extreme
> or the other.
>
> But I think that's the case that needs to be made -- that there's a lot of
> use cases for auto-assigning instance attributes, that also need
> highly customized behaviour for other attributes and __eq__  and __repr__.
>
> NOTE: another key 

[Python-ideas] Re: Auto assignment of attributes

2022-04-29 Thread Christopher Barker
On Thu, Apr 28, 2022 at 10:26 PM Ethan Furman  wrote:

>  > One thing you can say about dataclasses is that they provide a way to
> handle all parameters, mutable and immutable.
>
> Really?  I did not know that.  Interesting.
>
> Definitely an issue of dataclasses being special, though, and not
> attributable to the syntax used to make a dataclass.
>

Absolutely -- my point is that if you want to auto-assign all parameters,
then a dataclass is a good way to do it.

If you need to write handling code for most parameters, then the current
do-it-by-hand approach is fine.

A new syntax would help most when you need to write custom code for a few
parameters, but auto-assign the rest.

I brought up mutable defaults, as they would require custom code, making
the auto-assignment a tad less useful.

But perhaps if the recent ideas for late-bound parameters ever bears fruit,
then combining that with  auto-assigning would increase the usefulness of
both features.

-CHB




>
> --
> ~Ethan~
> ___
> 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/76GFMSU7OVG3GMFXD52TJFSPG47N2QLR/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/OZXLAM4KBZSGT3HLLXVU5RHDW4JMTQTF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-28 Thread Ethan Furman

On 4/28/22 21:46, Christopher Barker wrote:

> One thing you can say about dataclasses is that they provide a way to handle 
all parameters, mutable and immutable.

Really?  I did not know that.  Interesting.

Definitely an issue of dataclasses being special, though, and not attributable 
to the syntax used to make a dataclass.

--
~Ethan~
___
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/76GFMSU7OVG3GMFXD52TJFSPG47N2QLR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-28 Thread Christopher Barker
On Thu, Apr 28, 2022 at 4:15 PM Ethan Furman  wrote:

>  > NOTE: another key question for this proposal is how you would handle
> mutable defaults -- anything
>  > special, or "don't do that"?
>
> Why should they be handled at all?  If the programmer writes
>
>  def __init__(a, @b, @c=[]):
>  pass
>
> then all instances that didn't have `c` given will share the same list --
> just like if the code was:
>
>  def __init__(a, b, c=[]):
>  self.b = b
>  self.c = c
>

so the answer is "don't do that" (unless, in the rare case, that's what you
actually want).

The purpose of the syntax is to automatically save arguments to same-named
> attributes, not to perform any other magic.


> If the programmer writes

 def __init__(a, @b, @c=[]):
 pass

sure but that's the coon case -- more common would be:

def __init__(a, @b, c=None):
handle_a
if c is None:
c = []

or some such.

so  without "any other magic", then we have a less useful proposal. One
thing you can say about dataclasses is that they provide a way to handle
all parameters, mutable and immutable.

Anyway, I just thought it should be clearly said.

-CHB

-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/HYRQPWXMPJ727FQWEJ4GY2SMUEABKEGW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-28 Thread Ethan Furman

On 4/23/22 12:11, Christopher Barker wrote:

> NOTE: another key question for this proposal is how you would handle mutable 
defaults -- anything
> special, or "don't do that"?

Why should they be handled at all?  If the programmer writes

def __init__(a, @b, @c=[]):
pass

then all instances that didn't have `c` given will share the same list -- just 
like if the code was:

def __init__(a, b, c=[]):
self.b = b
self.c = c

The purpose of the syntax is to automatically save arguments to same-named 
attributes, not to perform any other magic.

--
~Ethan~
___
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/HXQ6K6RF5AZ7XLNWRXGSNKN4KOIYZZ7E/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-28 Thread Ethan Furman

On 4/21/22 15:12, Joao S. O. Bueno wrote:
> On Thu, Apr 21, 2022 at 5:17 PM Pablo Alcain wrote:

>> I think that discussion can probably belong to a specific thread with the 
proposal with
>> your questions summary there so everyone can contribute to the 
implementation that, clearly,
>> has some interesting points that it would be better if we could discuss in 
detail.
>
> Sorry. It looks like you are claiming... the _thread_ , is that it?
>
> Very well. The thread may be all yours!

Well, Pablo is the OP of this thread, so that seems entirely reasonable.  ;-)

--
~Ethan~
___
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/TF2JHUEUDYLEZ33PPWCTT3VPKD5UNPQO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-28 Thread Ethan Furman

On 4/21/22 10:29, Joao S. O. Bueno wrote:

> I take the freedom to interpret 'no news == good news' on this thread -
> nominally that there are no major disagreements that a decorator
> to auto-commit `__init__` atributes to the instance could be a nice addition
> to the stdlib.

I am strongly against using a decorator for this purpose.  It would only be useful when *all* the arguments are saved 
as-is; in those cases where only *some* of them are, it either wouldn't work at all or would need to retype the names 
which would eliminate all benefits of using a decorator.


--
~Ethan~
___
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/7XRIXX2XP7KXAFV4XU4GQTP5YLERY7EH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-23 Thread Christopher Barker
On Sat, Apr 23, 2022 at 10:53 AM Pablo Alcain  wrote:

> Overall, I think that not all Classes can be thought of as Dataclasses
> and, even though dataclasses solutions have their merits, they probably
> cannot be extended to most of the other classes.
>

Absolutely. However, this is not an "all Classes" question.

I don't think of dataclasses as "mutable namedtuples with defaults" at all.

But do think they are for classes that are primarily about storing a
defined set of data.

I make heavy use of them for this, when I am adding quite a bit of
ucntionatily, but their core function is still to store a collection of
data. To put it less abstractly:

Dataclasses are good for classes in which the collection of fields is a
primary focus -- so the auto-generated __init__, __eq__ etc are appropriate.

It's kind of a recursive definition: dataclasses work well for those things
that data classes' auto generated methods work well for :-)

If, indeed, you need a lot of custom behavior for teh __init__, and __eq__,
and ... then datclasses are not for you.

And the current Python class system is great for fully customized
behaviour. It's quite purposeful that parameters of the __init__ have no
special behavior, and that "self" is explicit -- it gives you full
flexibility, and everything is explicit. That's a good thing.

But, of course, the reason this proposal is on the table (and it's not the
first time by any means) is that it's a common pattern to assign (at least
some of) the __init__ parameters to instance attributes as is.

So we have two extremes -- on one hand:

A) Most __init__ params are assigned as instance attributes as is, and
these are primarily needed for __eq__ and __repr__

and on the other extreme:

B) Most __init__ params need specialized behavior, and are quite distinct
from what's needed by __eq__ and __repr__

(A) is, of course, the entire point of dataclasses, so that's covered.

(B) is well covered by the current, you-need-to-specify-everything approach.

So the question is -- how common is it that you have code that's far enough
toward the (A) extreme as far as __init__ params being instance attributes
that we want special syntax, when we don't want most of the __eq__ and
__repr__ behaviour.

In my experience, not all that much -- my code tends to be on one extreme
or the other.

But I think that's the case that needs to be made -- that there's a lot of
use cases for auto-assigning instance attributes, that also need
highly customized behaviour for other attributes and __eq__  and __repr__.

NOTE: another key question for this proposal is how you would handle
mutable defaults -- anything special, or "don't do that"?

-CHB

--
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/YSM5THFP7HSLPKTR6HOKU6LFZCWO2YL3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-23 Thread Pablo Alcain
On Thu, Apr 21, 2022 at 7:33 PM Josh Rosenberg <
shadowranger+pythonid...@gmail.com> wrote:

>
> On Wed, Apr 20, 2022 at 3:31 PM Pablo Alcain 
> wrote:
>
>>
>> About dataclasses, the point that Chris mentions, I think that they are
>> in a different scope from this, since they do much more stuff. But, beyond
>> this, a solution on the dataclass style would face a similar scenario:
>> since the `__init__` is autogenerated, you would also be in a tight spot in
>> the situation of "how would I bind only one of the items?". Again, now I'm
>> talking about my experience, but I think that it's very hard to think that
>> we could replace "classes" with "dataclasses" altogether. Here's an example
>> of one of the (unexpected for me) things that happen when you try to do
>> inheritance on dataclasses: https://peps.python.org/pep-0557/#inheritance
>> .
>>
>> dataclasses, by default, do four things with the annotated fields defined
> in the class:
>
> 1. Generate a __init__
> 2. Generate a reasonable __repr__
> 3. Generate a reasonable __eq__
> 4. Automatically support destructuring with match statements
>

This is very interesting. I use dataclasses quite a lot tbh, but I do think
that the purpose is different: the  `__repr__` and `__eq__` they generate,
for example, are reasonable when you consider that the classes are "mutable
namedtuples with defaults". the effective use of dataclasses indeed goes
beyond the "mutable namedtuples" thing, but as this happens then the
"reasonability" of the default `__repr__` and `__eq__` also starts to fade.
as a small experience token: in one point in time, I ended up having a
`dataclass` that reimplemented both `__init__` (through `__post_init__`)
and `__repr__`. Then I realized that I probably didn't want a dataclass to
begin with.


>
>

> And you can independently disable any/all of them with arguments to the
> decorator. They *can* do much more, but I find it pretty unusual to *ever*
> write a class that I wouldn't want most of those for. The __init__ it
> generates is essentially automatically writing the boilerplate you're
> trying to avoid, so it seems entirely reasonable to consider this the same
> scope.
>
> As for "how would I bind only one/some of the items?", dataclasses already
> support this with dataclasses.InitVar and a custom __post_init__ method; so:
>
> class MyClass:
>
> def __init__(self, @a, @b, c):
>
> ... do something with c that doesn't just assign it as self.c...
>
> where you directly move values from the a and b arguments to self.a and
> self.b, but use c for some other purpose, is spelled (using typing.Any as a
> placeholder annotation when there's no better annotation to use):
>
> @dataclass
> class MyClass:
> a: Any
> b: Any
> c: InitVar[Any]
> def __post_init__(self, c):
> ... do something with c that doesn't just assign it as self.c;
> self.a and self.b already exist ...
>
> The only name repeated is c (because you're not doing trivial assignment
> with it), and it's perfectly readable. I'm really not seeing how this is
> such an unwieldy solution that it's worth adding dedicated syntax to avoid
> a pretty trivial level of boilerplate that is already avoidable with
> dataclasses anyway.
>

I think that in some scenarios it can be done, but it doesn't look very
clean: namely with the explicit declaration of `InitVar` and the usage of
the `__post_init__`. It looks like this case in which you don't like the
autogenerated solution and patch it to reflect your actual goal. It's ok,
but it's also going to lead towards harder to mantain and interpret code.


>
> -Josh
>

Overall, I think that not all Classes can be thought of as Dataclasses and,
even though dataclasses solutions have their merits, they probably cannot
be extended to most of the other classes.

Pablo
___
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/B6Q4LFCETYYY6HOR7UT4ZC5MQ73SJ3YA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-21 Thread Josh Rosenberg
On Wed, Apr 20, 2022 at 3:31 PM Pablo Alcain  wrote:

>
> About dataclasses, the point that Chris mentions, I think that they are in
> a different scope from this, since they do much more stuff. But, beyond
> this, a solution on the dataclass style would face a similar scenario:
> since the `__init__` is autogenerated, you would also be in a tight spot in
> the situation of "how would I bind only one of the items?". Again, now I'm
> talking about my experience, but I think that it's very hard to think that
> we could replace "classes" with "dataclasses" altogether. Here's an example
> of one of the (unexpected for me) things that happen when you try to do
> inheritance on dataclasses: https://peps.python.org/pep-0557/#inheritance.
>
> dataclasses, by default, do four things with the annotated fields defined
in the class:

1. Generate a __init__
2. Generate a reasonable __repr__
3. Generate a reasonable __eq__
4. Automatically support destructuring with match statements

And you can independently disable any/all of them with arguments to the
decorator. They *can* do much more, but I find it pretty unusual to *ever*
write a class that I wouldn't want most of those for. The __init__ it
generates is essentially automatically writing the boilerplate you're
trying to avoid, so it seems entirely reasonable to consider this the same
scope.

As for "how would I bind only one/some of the items?", dataclasses already
support this with dataclasses.InitVar and a custom __post_init__ method; so:

class MyClass:

def __init__(self, @a, @b, c):

... do something with c that doesn't just assign it as self.c...

where you directly move values from the a and b arguments to self.a and
self.b, but use c for some other purpose, is spelled (using typing.Any as a
placeholder annotation when there's no better annotation to use):

@dataclass
class MyClass:
a: Any
b: Any
c: InitVar[Any]
def __post_init__(self, c):
... do something with c that doesn't just assign it as self.c;
self.a and self.b already exist ...

The only name repeated is c (because you're not doing trivial assignment
with it), and it's perfectly readable. I'm really not seeing how this is
such an unwieldy solution that it's worth adding dedicated syntax to avoid
a pretty trivial level of boilerplate that is already avoidable with
dataclasses anyway.

-Josh
___
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/SSG2VXIMBQI5FC5S3G72GQ3XQTL6RSWS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-21 Thread Joao S. O. Bueno
On Thu, Apr 21, 2022 at 5:17 PM Pablo Alcain  wrote:

> Hey Joao! For what it's worth, I'm not a big fan of the proposal to be
> honest, for the reasons I have already mentioned. I'm not heavily against
> it, but I would most likely not use it. Nevertheless, I believe it would
> need a PEP since it probably can change substantially the way Python code
> is being written.
>
> I think that discussion can probably belong to a specific thread with the
> proposal with your questions summary there so everyone can contribute to
> the implementation that, clearly, has some interesting points that it would
> be better if we could discuss in detail.
>
> I would very much like for us to evaluate, in this thread, the original
> proposal we sent, regarding if anyone else thinks it would make sense to
> add a new syntax for the binding of attributes.
>
>
Sorry. It looks like you are claiming... the _thread_ , is that it?

Very well. The thread may be all yours!

BTW, I am -1 on these changes.


> Pablo
>
___
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/MSNOSJK2M3QLCUDUBVQNEFMDQF3YWIWD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-21 Thread Pablo Alcain
Hey Joao! For what it's worth, I'm not a big fan of the proposal to be
honest, for the reasons I have already mentioned. I'm not heavily against
it, but I would most likely not use it. Nevertheless, I believe it would
need a PEP since it probably can change substantially the way Python code
is being written.

I think that discussion can probably belong to a specific thread with the
proposal with your questions summary there so everyone can contribute to
the implementation that, clearly, has some interesting points that it would
be better if we could discuss in detail.

I would very much like for us to evaluate, in this thread, the original
proposal we sent, regarding if anyone else thinks it would make sense to
add a new syntax for the binding of attributes.

Pablo
___
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/7FKGRN2NQOZJK5MPVCYGDHDM6L2VCA4D/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-21 Thread Joao S. O. Bueno
I take the freedom to interpret 'no news == good news' on this thread -
nominally that there are no major disagreements that a decorator
to auto-commit `__init__` atributes to the instance could be a nice addition
to the stdlib.

I also assume it is uncontroversial enough for not needing a PEP.

I remember a similar thread from a couple years ago where the thread ended
up agreeing on such a decorator as well.

I would then like to take the opportunity to bike-shed  a bit on this, and
maybe we
can get out of here with a BPO and an actual implementation.

So,

1) Would it live better in "dataclasses" or "functools"? Or some other
package?

2) What about: the usage of the decorator without arguments would imply in
committing all of
`__init__` arguments as instance attributes, and two, mutually exclusive,
optional kwonly
 "parameters" and "except" parameters could be used with a list of
arguments to set?

2.1)  The usage of a "parameters" argument to the decorator would even pick
names from an
eventual "**kwargs" "__init__" parameter, which otherwise would be
commited be left alone/
2.2) would it make sense to have another argument to specify how "**kwargs"
should be treated?
I see three options: (i) ignore it altogether, (ii) commit it  as a
dictionary, (iii) commit all keys in kwargs as
instance attributes, (iii.a) "safe commit" keys in kwargs, avoiding
overriding methods and class attributes.
(whatever the option here, while the principle of "less features are
safer" in a first release, should consider
 if it would be possible to include the new features later in a
backwards compatible way)

3) While the Python implementation for such a decorator is somewhat
straightforward, are there any chances
of making it static-annotation friendly? AFAIK dataclasses just work with
static type checking because
the @dataclass thecorator is special-cased in the checker tools themselves.
Would that be the same case here?

4) Naming. What about "@commitargs"?

5) Should it emit a warning (or TypeError) when decorating anything but a
function named `__init__ ` ?



On Wed, Apr 20, 2022 at 3:14 PM Joao S. O. Bueno 
wrote:

>
>
> On Wed, Apr 20, 2022 at 12:30 PM Pablo Alcain 
> wrote:
>
>>
>> Regarding the usage of a decorator to do the auto-assignment, I think
>> that it has an issue regarding how to select a subset of the variables that
>> you would be setting. In the general case, you can probably get away with
>> calling `autoassign`. But, for example, if you want to set a but not b,
>> you'd probably have to use a string as the identifier of the parameters
>> that you want to assign:
>>
>> ```
>> class MyKlass:
>> @autoassign('a')
>> def __init__(self, a, b):
>> print(b)
>>
>> ```
>>
>> This, in my perspective, brings two things: the first one is that you'd
>> be repeating everywhere the list of names, so for example doing refactors
>> like changing a variable name would be a bit error-prone: If you change the
>> variable from `a` to `my_var_name`, you'd have to also change the list in
>> the autoassign. It's not a lot, but it can induce some errors because of
>> the repetition. On the other hand, I guess it would be a bit hard for IDEs
>> and static checkers to follow this execution path. I know that I'm only one
>> data point, but for what it's worth, I was very excited with the idea but
>> this prevented me from actually implementing this solution on a day-to-day
>> basis: it felt a bit fragile and induced me to some errors.
>>
>
> IMO, that is trivially resolvable by doing the decorator, by default,
> assign all parameters. If it tkaes a string or sequence with parameter
> names, then, it will just bind those (still shorter than one line
> `self.attr = attr` for each attribute.
>
> And for the fragility: that is the advantage of having a robust
> implementation of something like this on the stdlib: it is not something
> most people will go out of their way to write their own, since the tradeoff
> is just
> copy and paste a bunch of plain assignments.
>
> But having it right and known, could chop off tens of lines of useless
> code in, probably the majority of Python projects.
>
>
> Also answering Christopher Barker:
>
> This has a subtle, but different use than dataclasses.
> It might be grouped in the dataclasses module, on the stdlib.
>
>
>
>>
>> About dataclasses, the point that Chris mentions, I think that they are
>> in a different scope from this, since they do much more stuff. But, beyond
>> this, a solution on the dataclass style would face a similar scenario:
>> since the `__init__` is autogenerated, you would also be in a tight spot in
>> the situation of "how would I bind only one of the items?". Again, now I'm
>> talking about my experience, but I think that it's very hard to think that
>> we could replace "classes" with "dataclasses" altogether. Here's an example
>> of one of the (unexpected for me) things that happen when you try to do
>> inheritance on dataclasses: 

[Python-ideas] Re: Auto assignment of attributes

2022-04-20 Thread Joao S. O. Bueno
On Wed, Apr 20, 2022 at 12:30 PM Pablo Alcain  wrote:

>
> Regarding the usage of a decorator to do the auto-assignment, I think that
> it has an issue regarding how to select a subset of the variables that you
> would be setting. In the general case, you can probably get away with
> calling `autoassign`. But, for example, if you want to set a but not b,
> you'd probably have to use a string as the identifier of the parameters
> that you want to assign:
>
> ```
> class MyKlass:
> @autoassign('a')
> def __init__(self, a, b):
> print(b)
>
> ```
>
> This, in my perspective, brings two things: the first one is that you'd be
> repeating everywhere the list of names, so for example doing refactors like
> changing a variable name would be a bit error-prone: If you change the
> variable from `a` to `my_var_name`, you'd have to also change the list in
> the autoassign. It's not a lot, but it can induce some errors because of
> the repetition. On the other hand, I guess it would be a bit hard for IDEs
> and static checkers to follow this execution path. I know that I'm only one
> data point, but for what it's worth, I was very excited with the idea but
> this prevented me from actually implementing this solution on a day-to-day
> basis: it felt a bit fragile and induced me to some errors.
>

IMO, that is trivially resolvable by doing the decorator, by default,
assign all parameters. If it tkaes a string or sequence with parameter
names, then, it will just bind those (still shorter than one line
`self.attr = attr` for each attribute.

And for the fragility: that is the advantage of having a robust
implementation of something like this on the stdlib: it is not something
most people will go out of their way to write their own, since the tradeoff
is just
copy and paste a bunch of plain assignments.

But having it right and known, could chop off tens of lines of useless code
in, probably the majority of Python projects.


Also answering Christopher Barker:

This has a subtle, but different use than dataclasses.
It might be grouped in the dataclasses module, on the stdlib.



>
> About dataclasses, the point that Chris mentions, I think that they are in
> a different scope from this, since they do much more stuff. But, beyond
> this, a solution on the dataclass style would face a similar scenario:
> since the `__init__` is autogenerated, you would also be in a tight spot in
> the situation of "how would I bind only one of the items?". Again, now I'm
> talking about my experience, but I think that it's very hard to think that
> we could replace "classes" with "dataclasses" altogether. Here's an example
> of one of the (unexpected for me) things that happen when you try to do
> inheritance on dataclasses: https://peps.python.org/pep-0557/#inheritance.
>
> Overall, I think that it's hard to think about a solution to this problem
> that is clean and robust without adding new syntax with it. I would like to
> hear your thoughts on this (and everyone else's of course!)
>
> Cheers,
> Pablo
>
> On Mon, Apr 18, 2022 at 9:55 PM Christopher Barker 
> wrote:
>
>> On Mon, Apr 18, 2022 at 4:24 PM Joao S. O. Bueno 
>> wrote:
>>
>>> I for one am all for the inclusion of a decorator targeting either the
>>> __init__ method
>>> or the class itself to perform this binding of known arguments to
>>> instance attributes
>>> prior to entering __init__. It could live either in functools or
>>> dataclasses itself.
>>>
>>
>> Isn’t this what dataclasses already accomplish? I understand that it’s
>> the reverse— with a dataclass, you specify the fields, and the __init__ is
>> generated, whereas this proposal is ttt be at you’d write an __init__, and
>> the attributes would be set — but other than taste, is there a practical
>> difference?
>>
>> -CHB
>>
>>
>>> On Sat, Apr 16, 2022 at 5:49 PM Pablo Alcain 
>>> wrote:
>>>
 The problem of assigning init arguments as attributes has appeared
 several times in the past (
 https://mail.python.org/archives/list/python-ideas@python.org/message/VLI3DOFA5VWMGJMJGRDC7JZTRKEPPZNU/
 was the most recent we could find) and is already handled in dataclasses.

 Lately, discussing this topic with a friend, we thought that using a
 specific token could be a possible approach, so you could do:

 class MyClass:

 def __init__(self, @a, @b, c):

 pass

 and it would be analogous to doing:

 class MyClass:

 def __init__(self, a, b, c):

 self.a = a

 self.b = b

 Then, you would instantiate the class as usual, and the variables
 tagged with `@` would be bound to the object:

 >>> objekt = MyClass(2, 3, 4)

 >>> print(objekt.b)

 3

 >>> print(objekt.c)

 AttributeError: 'MyClass' object has no attribute 'c'


 We have a working implementation here if anyone wants to take a look
 at: 

[Python-ideas] Re: Auto assignment of attributes

2022-04-20 Thread Yves Duprat
Joao S. O. Bueno wrote:
> There is no need for a whole new syntax for what can trivially be
> accomplished by a decorator,
> and a simple one, in this cases.
> I for one am all for the inclusion of a decorator targeting either the
> __init__ method
> or the class itself to perform this binding of known arguments to instance
> attributes
> prior to entering __init__. It could live either in functools or
> dataclasses itself.
> On Sat, Apr 16, 2022 at 5:49 PM Pablo Alcain pabloalc...@gmail.com wrote:
> > The problem of assigning init arguments as attributes has appeared several
> > times in the past (
> > https://mail.python.org/archives/list/python-ideas@python.org/message/VLI3DO...
> > was the most recent we could find) and is already handled in dataclasses.
> > Lately, discussing this topic with a friend, we thought that using a
> > specific token could be a possible approach, so you could do:
> > class MyClass:
> > def __init__(self, @a, @b, c):
> > 
> > pass
> > 
> > 
> > and it would be analogous to doing:
> > class MyClass:
> > def __init__(self, a, b, c):
> > 
> > self.a = a
> > 
> > self.b = b
> > 
> > 
> > Then, you would instantiate the class as usual, and the variables tagged
> > with `@` would be bound to the object:
> > objekt = MyClass(2, 3, 4)
> > print(objekt.b)
> > 3
> > print(objekt.c)
> > AttributeError: 'MyClass' object has no attribute 'c'
> > We have a working implementation here if anyone wants to take a look at:
> > https://github.com/pabloalcain/cpython/tree/feature/auto_attribute. Keep
> > in mind that we have limited knowledge about how to modify cpython itself,
> > and which would the best places be to do the modifications, so it's more
> > than likely that some design decisions aren't very sound (
> > https://devguide.python.org/grammar/ and
> > https://devguide.python.org/parser/ were incredibly helpful).
> > Besides the implementation, we would like to know what the community
> > thinks on whether this might have any value. While developing this, we
> > realized that Crystal already has this feature (eg
> > https://github.com/askn/crystal-by-example/blob/master/struct/struct.cr)
> > with the same syntax; which is kind of expected, considering it's syntax is
> > based on Ruby.
> > Random collection of thoughts:
> > 
> > If auto-assignment made sense in general, one of the reasons we went
> > 
> > for this rather than the decorator approach is that we wouldn't like to
> > have a list of strings that can vary decoupled from the actual argument
> > name.
> > 
> > The current implementation of `@` works for any function, not only
> > 
> > init. We don't know if this would actually be a desirable feature.
> > 
> > It also works with any function in the wild. This mostly allows for
> > 
> > monkey-patching to work out of the box:
> > class Klass:
> > ... def __init__(self):
> > ... pass
> > ...
> > def add_parameter(k, @p):
> > ... pass
> > ...
> > Klass.add_parameter = add_parameter
> > objekt = Klass()
> > print(objekt.p)
> > Traceback (most recent call last):
> > File "", line 1, in 
> > AttributeError: 'Klass' object has no attribute 'p'
> > objekt.add_parameter(11)
> > print(objekt.p)
> > 11
> > Again, we are not sure if this is desirable, but it's what made most sense
> > for us at the moment.
> > 
> > Adding the `@` token to the argument doesn’t remove the variable from
> > 
> > the function/method scope, so this would be perfectly valid:
> > def my_function(k, @parameter):
> > ... print(parameter)
> > my_function(objekt, 4)
> > 4
> > k.parameter
> > 4
> > 
> > We didn’t implement it for lambda functions.
> > 
> > Cheers,
> > Pablo and Quimey
> > 
> > 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/SCXHEW...
> > Code of Conduct: http://python.org/psf/codeofconduct/
> >
I had already used this small library in the past, 
https://pypi.org/project/initify/ , based on a decorator. 
May be it could be useful for your needs, without adding `@`token to a 
parameter ?

Yves
___
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/UYTDOF4O6NCETVYD2DAELD3QUPDPWPEK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto assignment of attributes

2022-04-20 Thread Pablo Alcain
Regarding the usage of a decorator to do the auto-assignment, I think that
it has an issue regarding how to select a subset of the variables that you
would be setting. In the general case, you can probably get away with
calling `autoassign`. But, for example, if you want to set a but not b,
you'd probably have to use a string as the identifier of the parameters
that you want to assign:

```
class MyKlass:
@autoassign('a')
def __init__(self, a, b):
print(b)

```

This, in my perspective, brings two things: the first one is that you'd be
repeating everywhere the list of names, so for example doing refactors like
changing a variable name would be a bit error-prone: If you change the
variable from `a` to `my_var_name`, you'd have to also change the list in
the autoassign. It's not a lot, but it can induce some errors because of
the repetition. On the other hand, I guess it would be a bit hard for IDEs
and static checkers to follow this execution path. I know that I'm only one
data point, but for what it's worth, I was very excited with the idea but
this prevented me from actually implementing this solution on a day-to-day
basis: it felt a bit fragile and induced me to some errors.

About dataclasses, the point that Chris mentions, I think that they are in
a different scope from this, since they do much more stuff. But, beyond
this, a solution on the dataclass style would face a similar scenario:
since the `__init__` is autogenerated, you would also be in a tight spot in
the situation of "how would I bind only one of the items?". Again, now I'm
talking about my experience, but I think that it's very hard to think that
we could replace "classes" with "dataclasses" altogether. Here's an example
of one of the (unexpected for me) things that happen when you try to do
inheritance on dataclasses: https://peps.python.org/pep-0557/#inheritance.

Overall, I think that it's hard to think about a solution to this problem
that is clean and robust without adding new syntax with it. I would like to
hear your thoughts on this (and everyone else's of course!)

Cheers,
Pablo

On Mon, Apr 18, 2022 at 9:55 PM Christopher Barker 
wrote:

> On Mon, Apr 18, 2022 at 4:24 PM Joao S. O. Bueno 
> wrote:
>
>> I for one am all for the inclusion of a decorator targeting either the
>> __init__ method
>> or the class itself to perform this binding of known arguments to
>> instance attributes
>> prior to entering __init__. It could live either in functools or
>> dataclasses itself.
>>
>
> Isn’t this what dataclasses already accomplish? I understand that it’s the
> reverse— with a dataclass, you specify the fields, and the __init__ is
> generated, whereas this proposal is ttt be at you’d write an __init__, and
> the attributes would be set — but other than taste, is there a practical
> difference?
>
> -CHB
>
>
>> On Sat, Apr 16, 2022 at 5:49 PM Pablo Alcain 
>> wrote:
>>
>>> The problem of assigning init arguments as attributes has appeared
>>> several times in the past (
>>> https://mail.python.org/archives/list/python-ideas@python.org/message/VLI3DOFA5VWMGJMJGRDC7JZTRKEPPZNU/
>>> was the most recent we could find) and is already handled in dataclasses.
>>>
>>> Lately, discussing this topic with a friend, we thought that using a
>>> specific token could be a possible approach, so you could do:
>>>
>>> class MyClass:
>>>
>>> def __init__(self, @a, @b, c):
>>>
>>> pass
>>>
>>> and it would be analogous to doing:
>>>
>>> class MyClass:
>>>
>>> def __init__(self, a, b, c):
>>>
>>> self.a = a
>>>
>>> self.b = b
>>>
>>> Then, you would instantiate the class as usual, and the variables tagged
>>> with `@` would be bound to the object:
>>>
>>> >>> objekt = MyClass(2, 3, 4)
>>>
>>> >>> print(objekt.b)
>>>
>>> 3
>>>
>>> >>> print(objekt.c)
>>>
>>> AttributeError: 'MyClass' object has no attribute 'c'
>>>
>>>
>>> We have a working implementation here if anyone wants to take a look at:
>>> https://github.com/pabloalcain/cpython/tree/feature/auto_attribute.
>>> Keep in mind that we have limited knowledge about how to modify cpython
>>> itself, and which would the best places be to do the modifications, so it's
>>> more than likely that some design decisions aren't very sound (
>>> https://devguide.python.org/grammar/ and
>>> https://devguide.python.org/parser/ were incredibly helpful).
>>>
>>> Besides the implementation, we would like to know what the community
>>> thinks on whether this might have any value. While developing this, we
>>> realized that Crystal already has this feature (eg
>>> https://github.com/askn/crystal-by-example/blob/master/struct/struct.cr)
>>> with the same syntax; which is kind of expected, considering it's syntax is
>>> based on Ruby.
>>>
>>>
>>> Random collection of thoughts:
>>>
>>> 1. If auto-assignment made sense in general, one of the reasons we went
>>> for this rather than the decorator approach is that we wouldn't like to
>>> have a list of strings that can vary decoupled 

[Python-ideas] Re: Auto assignment of attributes

2022-04-18 Thread Christopher Barker
On Mon, Apr 18, 2022 at 4:24 PM Joao S. O. Bueno 
wrote:

> I for one am all for the inclusion of a decorator targeting either the
> __init__ method
> or the class itself to perform this binding of known arguments to instance
> attributes
> prior to entering __init__. It could live either in functools or
> dataclasses itself.
>

Isn’t this what dataclasses already accomplish? I understand that it’s the
reverse— with a dataclass, you specify the fields, and the __init__ is
generated, whereas this proposal is ttt be at you’d write an __init__, and
the attributes would be set — but other than taste, is there a practical
difference?

-CHB


> On Sat, Apr 16, 2022 at 5:49 PM Pablo Alcain 
> wrote:
>
>> The problem of assigning init arguments as attributes has appeared
>> several times in the past (
>> https://mail.python.org/archives/list/python-ideas@python.org/message/VLI3DOFA5VWMGJMJGRDC7JZTRKEPPZNU/
>> was the most recent we could find) and is already handled in dataclasses.
>>
>> Lately, discussing this topic with a friend, we thought that using a
>> specific token could be a possible approach, so you could do:
>>
>> class MyClass:
>>
>> def __init__(self, @a, @b, c):
>>
>> pass
>>
>> and it would be analogous to doing:
>>
>> class MyClass:
>>
>> def __init__(self, a, b, c):
>>
>> self.a = a
>>
>> self.b = b
>>
>> Then, you would instantiate the class as usual, and the variables tagged
>> with `@` would be bound to the object:
>>
>> >>> objekt = MyClass(2, 3, 4)
>>
>> >>> print(objekt.b)
>>
>> 3
>>
>> >>> print(objekt.c)
>>
>> AttributeError: 'MyClass' object has no attribute 'c'
>>
>>
>> We have a working implementation here if anyone wants to take a look at:
>> https://github.com/pabloalcain/cpython/tree/feature/auto_attribute. Keep
>> in mind that we have limited knowledge about how to modify cpython itself,
>> and which would the best places be to do the modifications, so it's more
>> than likely that some design decisions aren't very sound (
>> https://devguide.python.org/grammar/ and
>> https://devguide.python.org/parser/ were incredibly helpful).
>>
>> Besides the implementation, we would like to know what the community
>> thinks on whether this might have any value. While developing this, we
>> realized that Crystal already has this feature (eg
>> https://github.com/askn/crystal-by-example/blob/master/struct/struct.cr)
>> with the same syntax; which is kind of expected, considering it's syntax is
>> based on Ruby.
>>
>>
>> Random collection of thoughts:
>>
>> 1. If auto-assignment made sense in general, one of the reasons we went
>> for this rather than the decorator approach is that we wouldn't like to
>> have a list of strings that can vary decoupled from the actual argument
>> name.
>>
>> 2. The current implementation of `@` works for any function, not only
>> init. We don't know if this would actually be a desirable feature.
>>
>> 3. It also works with any function in the wild. This mostly allows for
>> monkey-patching to work out of the box:
>>
>> >>> class Klass:
>>
>> ... def __init__(self):
>>
>> ... pass
>>
>> ...
>>
>> >>> def add_parameter(k, @p):
>>
>> ... pass
>>
>> ...
>>
>> >>> Klass.add_parameter = add_parameter
>>
>> >>> objekt = Klass()
>>
>> >>> print(objekt.p)
>>
>> Traceback (most recent call last):
>>
>>   File "", line 1, in 
>>
>> AttributeError: 'Klass' object has no attribute 'p'
>>
>> >>> objekt.add_parameter(11)
>>
>> >>> print(objekt.p)
>>
>> 11
>>
>> Again, we are not sure if this is desirable, but it's what made most
>> sense for us at the moment.
>>
>> 4. Adding the `@` token to the argument doesn’t remove the variable from
>> the function/method scope, so this would be perfectly valid:
>>
>> >>> def my_function(k, @parameter):
>>
>> ... print(parameter)
>>
>> >>> my_function(objekt, 4)
>>
>> 4
>>
>> >>> k.parameter
>>
>> 4
>>
>>
>>
>> 5. We didn’t implement it for lambda functions.
>>
>> Cheers,
>>
>> Pablo and Quimey
>>
>> ___
>> 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/SCXHEWCHBJN3A7DPGGPPFLSTMBLLAOTX/
>> 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/HUGRGXVT7NBWSXI2ILZOMFIRWV4KIQ5Q/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, 

[Python-ideas] Re: Auto assignment of attributes

2022-04-18 Thread Joao S. O. Bueno
There is no need for a whole new syntax for what can trivially be
accomplished by a decorator,
and a simple one, in this cases.

I for one am all for the inclusion of a decorator targeting either the
__init__ method
or the class itself to perform this binding of known arguments to instance
attributes
prior to entering __init__. It could live either in functools or
dataclasses itself.

On Sat, Apr 16, 2022 at 5:49 PM Pablo Alcain  wrote:

> The problem of assigning init arguments as attributes has appeared several
> times in the past (
> https://mail.python.org/archives/list/python-ideas@python.org/message/VLI3DOFA5VWMGJMJGRDC7JZTRKEPPZNU/
> was the most recent we could find) and is already handled in dataclasses.
>
> Lately, discussing this topic with a friend, we thought that using a
> specific token could be a possible approach, so you could do:
>
> class MyClass:
>
> def __init__(self, @a, @b, c):
>
> pass
>
> and it would be analogous to doing:
>
> class MyClass:
>
> def __init__(self, a, b, c):
>
> self.a = a
>
> self.b = b
>
> Then, you would instantiate the class as usual, and the variables tagged
> with `@` would be bound to the object:
>
> >>> objekt = MyClass(2, 3, 4)
>
> >>> print(objekt.b)
>
> 3
>
> >>> print(objekt.c)
>
> AttributeError: 'MyClass' object has no attribute 'c'
>
>
> We have a working implementation here if anyone wants to take a look at:
> https://github.com/pabloalcain/cpython/tree/feature/auto_attribute. Keep
> in mind that we have limited knowledge about how to modify cpython itself,
> and which would the best places be to do the modifications, so it's more
> than likely that some design decisions aren't very sound (
> https://devguide.python.org/grammar/ and
> https://devguide.python.org/parser/ were incredibly helpful).
>
> Besides the implementation, we would like to know what the community
> thinks on whether this might have any value. While developing this, we
> realized that Crystal already has this feature (eg
> https://github.com/askn/crystal-by-example/blob/master/struct/struct.cr)
> with the same syntax; which is kind of expected, considering it's syntax is
> based on Ruby.
>
>
> Random collection of thoughts:
>
> 1. If auto-assignment made sense in general, one of the reasons we went
> for this rather than the decorator approach is that we wouldn't like to
> have a list of strings that can vary decoupled from the actual argument
> name.
>
> 2. The current implementation of `@` works for any function, not only
> init. We don't know if this would actually be a desirable feature.
>
> 3. It also works with any function in the wild. This mostly allows for
> monkey-patching to work out of the box:
>
> >>> class Klass:
>
> ... def __init__(self):
>
> ... pass
>
> ...
>
> >>> def add_parameter(k, @p):
>
> ... pass
>
> ...
>
> >>> Klass.add_parameter = add_parameter
>
> >>> objekt = Klass()
>
> >>> print(objekt.p)
>
> Traceback (most recent call last):
>
>   File "", line 1, in 
>
> AttributeError: 'Klass' object has no attribute 'p'
>
> >>> objekt.add_parameter(11)
>
> >>> print(objekt.p)
>
> 11
>
> Again, we are not sure if this is desirable, but it's what made most sense
> for us at the moment.
>
> 4. Adding the `@` token to the argument doesn’t remove the variable from
> the function/method scope, so this would be perfectly valid:
>
> >>> def my_function(k, @parameter):
>
> ... print(parameter)
>
> >>> my_function(objekt, 4)
>
> 4
>
> >>> k.parameter
>
> 4
>
>
>
> 5. We didn’t implement it for lambda functions.
>
> Cheers,
>
> Pablo and Quimey
>
> ___
> 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/SCXHEWCHBJN3A7DPGGPPFLSTMBLLAOTX/
> 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/HUGRGXVT7NBWSXI2ILZOMFIRWV4KIQ5Q/
Code of Conduct: http://python.org/psf/codeofconduct/