[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

py3k feature proposal: field auto-assignment in constructors

coldpizza

1/27/2008 5:06:00 PM

There is a pattern that occurs fairly often in constructors in Python
and other OOP languages.

Let's take an example:

class Server(object):
def __init__(self, host, port, protocol, bufsize, timeout):
self.host = host
self.port = port
self.protocol = protocol
self.bufsize = bufsize
self.maxthreads = maxthreads
self.timeout = timeout

Imho, in the class above the assignment to instance fields does not
contain much programming logic and therefore can be safely 'abstracted
away' by the language itself with a syntax which would look something
like this:

class Server(object):
def __init__(self, @host, @port, @protocol, @bufsize, @timeout):
pass

This would be equivalent to the first example above, yet it does not
obfuscate the code in any way. Or does it? It does look much cleaner
to me.

Of course, the ampersand is just an arbitrary choice and might have
bad connotations for those who read it as 'take address of' but @ has
some allusion to delegates which maybe is ok.

I am not an experienced programmer and I am not sure if this is
necessarily a good idea, so I wanted to get some feedback from more
experienced Pythonistas before submitting it elsewhere.


45 Answers

André

1/27/2008 5:46:00 PM

0

On Jan 27, 1:06 pm, coldpizza <vri...@gmail.com> wrote:
> There is a pattern that occurs fairly often in constructors in Python
> and other OOP languages.
>
> Let's take an example:
>
> class Server(object):
> def __init__(self, host, port, protocol, bufsize, timeout):
> self.host = host
> self.port = port
> self.protocol = protocol
> self.bufsize = bufsize
> self.maxthreads = maxthreads
> self.timeout = timeout
>
> Imho, in the class above the assignment to instance fields does not
> contain much programming logic and therefore can be safely 'abstracted
> away' by the language itself with a syntax which would look something
> like this:
>
> class Server(object):
> def __init__(self, @host, @port, @protocol, @bufsize, @timeout):
> pass
>
> This would be equivalent to the first example above, yet it does not
> obfuscate the code in any way. Or does it? It does look much cleaner
> to me.
>
> Of course, the ampersand is just an arbitrary choice and might have
> bad connotations for those who read it as 'take address of' but @ has
> some allusion to delegates which maybe is ok.
>
> I am not an experienced programmer and I am not sure if this is
> necessarily a good idea, so I wanted to get some feedback from more
> experienced Pythonistas before submitting it elsewhere.

If you search on this list, you will find that there has been *many*
proposals to remove self (which, I realize is slightly different than
what yo propose) and that the main argument can be summarized as
"Explicit is better than implicit."

Personally, I like the idea you suggest, with the modification that I
would use "." instead of "@", as in

class Server(object):
def __init__(self, .host, .port, .protocol, .bufsize, .timeout):
pass

André

Wildemar Wildenburger

1/27/2008 6:16:00 PM

0

André wrote:
> Personally, I like the idea you suggest, with the modification that I
> would use "." instead of "@", as in
>
> class Server(object):
> def __init__(self, .host, .port, .protocol, .bufsize, .timeout):
> pass
>
I like :)

However, you can probably cook up a decorator for this (not certain, I'm
not a decorator Guru), which is not that much worse.

Still, I'd support that syntax (and the general idea.).

/W

Diez B. Roggisch

1/27/2008 6:32:00 PM

0

Wildemar Wildenburger schrieb:
> André wrote:
>> Personally, I like the idea you suggest, with the modification that I
>> would use "." instead of "@", as in
>>
>> class Server(object):
>> def __init__(self, .host, .port, .protocol, .bufsize, .timeout):
>> pass
>>
> I like :)
>
> However, you can probably cook up a decorator for this (not certain, I'm
> not a decorator Guru), which is not that much worse.
>
> Still, I'd support that syntax (and the general idea.).

Just for the fun of it, I implemented a decorator:

from functools import *
from inspect import *

def autoassign(_init_):
@wraps(_init_)
def _autoassign(self, *args, **kwargs):
argnames, _, _, _ = getargspec(_init_)
for name, value in zip(argnames[1:], args):
setattr(self, name, value)
_init_(self, *args, **kwargs)

return _autoassign

class Test(object):
@autoassign
def __init__(self, foo, bar):
pass



t = Test(10, 20)

print t.bar


Diez

Torsten Bronger

1/27/2008 6:41:00 PM

0

Hallöchen!

Wildemar Wildenburger writes:

> André wrote:
>
>> Personally, I like the idea you suggest, with the modification
>> that I would use "." instead of "@", as in
>>
>> class Server(object):
>> def __init__(self, .host, .port, .protocol, .bufsize, .timeout):
>> pass
>
> I like :)
>
> However, you can probably cook up a decorator for this (not
> certain, I'm not a decorator Guru), which is not that much worse.
>
> Still, I'd support that syntax (and the general idea.).

Well, you save one or two lines per class. Not enough in my
opinion.

Tschö,
Torsten.

--
Torsten Bronger, aquisgrana, europa vetus
Jabber ID: bronger@jabber.org
(See http://ime.... for further contact info.)

Wildemar Wildenburger

1/27/2008 6:48:00 PM

0

Diez B. Roggisch wrote:
> Just for the fun of it, I implemented a decorator:
>
> from functools import *
> from inspect import *
>
> def autoassign(_init_):
> @wraps(_init_)
> def _autoassign(self, *args, **kwargs):
> argnames, _, _, _ = getargspec(_init_)
> for name, value in zip(argnames[1:], args):
> setattr(self, name, value)
> _init_(self, *args, **kwargs)
>
> return _autoassign
>

This is neat. :) Could that maybe be extended to only assign selected
args to the instance and let others pass unchanged. So that, for instance:

@autoassign("foo", "bar")
def __init__(self, foo, bar, baz):
super(baz)

?W

André

1/27/2008 7:00:00 PM

0

On Jan 27, 2:48 pm, Wildemar Wildenburger
<lasses_w...@klapptsowieso.net> wrote:
> Diez B. Roggisch wrote:
> > Just for the fun of it, I implemented a decorator:
>
> > from functools import *
> > from inspect import *
>
> > def autoassign(_init_):
> > @wraps(_init_)
> > def _autoassign(self, *args, **kwargs):
> > argnames, _, _, _ = getargspec(_init_)
> > for name, value in zip(argnames[1:], args):
> > setattr(self, name, value)
> > _init_(self, *args, **kwargs)
>
> > return _autoassign
>
> This is neat. :) Could that maybe be extended to only assign selected
> args to the instance and let others pass unchanged. So that, for instance:
>
> @autoassign("foo", "bar")
> def __init__(self, foo, bar, baz):
> super(baz)
>
> ?W

If one goes back to the original idea instead, the decision of using
automatic assignment should depend on the signature of the __init__
function. Here's an implementation (using "_" instead of "." as it
would lead to a syntax error):

from functools import *
from inspect import *

def autoassign(_init_):
@wraps(_init_)
def _autoassign(self, *args, **kwargs):
argnames, _, _, _ = getargspec(_init_)
for name, value in zip(argnames[1:], args):
if name.startswith("_"):
setattr(self, name[1:], value)
_init_(self, *args, **kwargs)

return _autoassign

class Test(object):
@autoassign
def __init__(self, _foo, _bar, baz):
print 'baz =', baz

t = Test(1, 2, 3)
print t.foo
print t.bar
print t.baz

#== the output is

baz = 3
1
2
Traceback (most recent call last):
File "/Users/andre/CrunchySVN/branches/andre/src/tools_2k.py", line
24, in exec_code
exec code in local_dict
File "User's code", line 23, in <module>
AttributeError: 'Test' object has no attribute 'baz'

#======
André

Dustan

1/27/2008 11:26:00 PM

0

On Jan 27, 12:41 pm, Torsten Bronger <bron...@physik.rwth-aachen.de>
wrote:
> Hallöchen!
>
>
>
> Wildemar Wildenburger writes:
> > André wrote:
>
> >> Personally, I like the idea you suggest, with the modification
> >> that I would use "." instead of "@", as in
>
> >> class Server(object):
> >> def __init__(self, .host, .port, .protocol, .bufsize, .timeout):
> >> pass
>
> > I like :)
>
> > However, you can probably cook up a decorator for this (not
> > certain, I'm not a decorator Guru), which is not that much worse.
>
> > Still, I'd support that syntax (and the general idea.).
>
> Well, you save one or two lines per class. Not enough in my
> opinion.

Are you referring to the alternate syntax or to the decorator? Either
way, you could be saving 4 or 5 or more lines, if you have enough
arguments.

Wildemar Wildenburger

1/27/2008 11:39:00 PM

0

Dustan wrote:
>> Well, you save one or two lines per class. Not enough in my
>> opinion.
>
> Are you referring to the alternate syntax or to the decorator? Either
> way, you could be saving 4 or 5 or more lines, if you have enough
> arguments.

OK, but then again, every decent IDE should give you the tools to write
an automation for that. Not that I don't like the idea of
auto-assignment, but, you know ...

/W

Terry Reedy

1/28/2008 12:13:00 AM

0


"André" <andre.roberge@gmail.com> wrote in message
news:7dcc86da-6ed7-48ec-9a9e-ada5574ae06e@v17g2000hsa.googlegroups.com...
If one goes back to the original idea instead, the decision of using
automatic assignment should depend on the signature of the __init__
function. Here's an implementation (using "_" instead of "." as it
would lead to a syntax error):

from functools import *
from inspect import *

def autoassign(_init_):
@wraps(_init_)
def _autoassign(self, *args, **kwargs):
argnames, _, _, _ = getargspec(_init_)
for name, value in zip(argnames[1:], args):
if name.startswith("_"):
setattr(self, name[1:], value)
_init_(self, *args, **kwargs)

return _autoassign

class Test(object):
@autoassign
def __init__(self, _foo, _bar, baz):
print 'baz =', baz

t = Test(1, 2, 3)
print t.foo
print t.bar
print t.baz

#== the output is

baz = 3
1
2
Traceback (most recent call last):
File "/Users/andre/CrunchySVN/branches/andre/src/tools_2k.py", line
24, in exec_code
exec code in local_dict
File "User's code", line 23, in <module>
AttributeError: 'Test' object has no attribute 'baz'
=================================

I think this version, with this name convention, is nice enough to possibly
go in the stdlib if there were an appropriate place for it. Not sure where
though. If there were a classtools module....

tjr



Ben Finney

1/28/2008 12:50:00 AM

0

"André" <andre.roberge@gmail.com> writes:

> Personally, I like the idea you suggest, with the modification that I
> would use "." instead of "@", as in
>
> class Server(object):
> def __init__(self, .host, .port, .protocol, .bufsize, .timeout):
> pass

-1.

That leading dot is too easy to miss when looking over the code.

--
\ "Intellectual property is to the 21st century what the slave |
`\ trade was to the 16th." â??David Mertz |
_o__) |
Ben Finney