Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > __autoinit__ (Was: Proposal: reducing self.x=x; self.y=y;self.z=z boilerplate code)

Reply
Thread Tools

__autoinit__ (Was: Proposal: reducing self.x=x; self.y=y;self.z=z boilerplate code)

 
 
Ralf W. Grosse-Kunstleve
Guest
Posts: n/a
 
      07-09-2005
My initial proposal
(http://cci.lbl.gov/~rwgk/python/adop...005_07_02.html) didn't
exactly get a warm welcome...

And Now for Something Completely Different:

class autoinit(object):

def __init__(self, *args, **keyword_args):
self.__dict__.update(
zip(self.__autoinit__.im_func.func_code.co_varname s[1:], args))
self.__dict__.update(keyword_args)
self.__autoinit__(*args, **keyword_args)

class grouping(autoinit):

def __autoinit__(self, x, y, z):
print self.x, self.y, self.z

group = grouping(1,2,z=3)
group = grouping(z=1,x=2,y=3)
try: grouping(1)
except TypeError, e: print e
try: grouping(1,2,3,a=0)
except TypeError, e: print e


Almost like my original favorite solution, only better, and it doesn't require
a syntax change.

Under a hypothetical new proposal __autoinit__ would become a standard feature
of object.

Any takers?

Cheers,
Ralf


__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
 
Reply With Quote
 
 
 
 
Kay Schluehr
Guest
Posts: n/a
 
      07-09-2005

Ralf W. Grosse-Kunstleve schrieb:
> My initial proposal
> (http://cci.lbl.gov/~rwgk/python/adop...005_07_02.html) didn't
> exactly get a warm welcome...


Well ... yes

Ralf, if you want to modify the class instantiation behaviour you
should have a look on metaclasses. That's what they are for. It is not
a particular good idea to integrate a new method into the object base
class for each accidental idea and write a PEP for it.

I provide you an example which is actually your use case. It doesn't
change the class hierarchy : the metaclass semantics is not "is a" as
for inheritance but "customizes" as one would expect also for
decorators.

class autoattr(type):
'''
The autoattr metaclass is used to extract auto_xxx parameters from
the argument-tuple or the keyword arguments of an object
constructor __init__
and create object attributes mit name xxx and the value of auto_xxx
passed
into __init__
'''
def __init__(cls,name, bases, dct):
super(autoattr,cls).__init__(name,bases,dct)
old_init = cls.__init__
defaults = cls.__init__.im_func.func_defaults
varnames = cls.__init__.im_func.func_code.co_varnames[1:]

def new_init(self,*args,**kwd):
for var,default in zip(varnames[-len(defaults):],defaults):
if var.startswith("auto_"):
self.__dict__[var[5:]] = default
for var,arg in zip(varnames,args):
if var.startswith("auto_"):
self.__dict__[var[5:]] = arg
for (key,val) in kwd.items():
if key.startswith("auto_"):
self.__dict__[key[5:]] = val
old_init(self,*args,**kwd)
cls.__init__ = new_init

class app:
__metaclass__ = autoattr
def __init__(self, auto_x, y, auto_z = 9):
pass

>>> a = app(2,5)
>>> a.x

2
>>> a.z

9
>>> a.y

-> AttributeError


Kay

 
Reply With Quote
 
 
 
 
Scott David Daniels
Guest
Posts: n/a
 
      07-10-2005
Ralf W. Grosse-Kunstleve wrote:
> My initial proposal
> (http://cci.lbl.gov/~rwgk/python/adop...005_07_02.html) didn't
> exactly get a warm welcome...
>
> And Now for Something Completely Different:
>
> class autoinit(object):
>
> def __init__(self, *args, **keyword_args):
> self.__dict__.update(
> zip(self.__autoinit__.im_func.func_code.co_varname s[1:], args))
> self.__dict__.update(keyword_args)
> self.__autoinit__(*args, **keyword_args)

Should be:
class autoinit(object):
def __init__(self, *args, **keyword_args):
for name, value in zip(self.__autoinit__.im_func.func_code.
co_varnames[1:], args):
setattr(self, name, value)
for name, value in keyword_args.items():
setattr(self, name, value)
self.__autoinit__(*args, **keyword_args)

Since using setattr will take care of any slots used in other classes.
Not all data is stored in the __dict__.

For example:

class Example(autoinit):
__slots__ = 'abc',
def __autoinit__(self, a=1, abc=1):
print a, abc

a = Example(1,2)
print a.__dict__
print a.a
print a.abc


--Scott David Daniels
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Kay Schluehr
Guest
Posts: n/a
 
      07-10-2005
> I stripped your code down to the essence. See attachment.
> For the user your approach then becomes:
>
> class grouping:
> __metaclass__ = autoattr
> def __init__(self, x, y, z):
> pass


No. This is clearly NOT what I had in mind. I translated your original
proposal which introduced a punctuation syntax '.x' for constructor
parameters forcing the interpreter to create equally named object
attributes into a naming convention that can be handled by a metaclass
customizer. The grouping.__init__ above does exacly nothing according
to my implementation. I would never accept dropping fine-tuning
capabilities. The "auto_" prefix is all the declarative magic.

> My __autoinit__ suggestion would result in (assuming object supports
> this by default):
>
> class grouping(object):
> def __autoinit__(self, x, y, z):
> pass
>
> I think that's far more intuitive.


Being intuitive is relative to someones intuition.

Kay

 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      07-10-2005

"Ralf W. Grosse-Kunstleve" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed). yahoo.com...

I have a suggestion I don't remember seeing for flagging which vars to
autoinit without new syntax: use '_' instead of '.'. I have never seen
local vars with a leading '_'. So, in combination with whatever other
mechanism (metaclass, __init__ decorator?)

def __init__(self, _x, y, _z) :

would automatically do self.x = _x, self.z = _z, but not self.y = y.

Terry J. Reedy



 
Reply With Quote
 
Bengt Richter
Guest
Posts: n/a
 
      07-10-2005
On Sun, 10 Jul 2005 16:26:24 -0400, "Terry Reedy" <(E-Mail Removed)> wrote:

>
>"Ralf W. Grosse-Kunstleve" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed) .yahoo.com...
>
>I have a suggestion I don't remember seeing for flagging which vars to
>autoinit without new syntax: use '_' instead of '.'. I have never seen
>local vars with a leading '_'. So, in combination with whatever other
>mechanism (metaclass, __init__ decorator?)
>
> def __init__(self, _x, y, _z) :
>
>would automatically do self.x = _x, self.z = _z, but not self.y = y.
>

Of course, if it works for __init__, it should work for an arbitrary
method or even function (if a decorator is used).

I think I could write a byte-code-modifying decorator that would insert
code at the beginning of a function to do the
self.x = _x; self.z = _z # but not self.y = y
in your example, and similarly for others.
But I am not sure it's not a waste of time to do these byte-code things
except to see how using such decorators feels in practice, or whether any
byte-code munging after generation is a good idea.

What would be the next step? To implement the same in C as a built in decorator?
I'm wondering if the effort of munging byte code isn't misplaced, and would create
a growing maintenance problem as more built-in decorators like that accumulated.

So, if we want alternate code generated, perhaps we need a way of talking to the
original code generation process? I'm thinking some kind of source-processing-time
decorator (maybe marked with double-@, like
@@auto_init_self_attributes
def __init__(self, _x, y, _z) : print 'self.y=%r not set'%y

The idea is for @@deco to be intercepted as part of the AST of the unit being compiled,
and be converted at that time to call with the AST and its own location in the tree being
passed to it so it can do mods to the AST (and cut itself out), and then let the resulting
AST be compiled as normal. Multiple @@decorators would each get their chance to mod the AST
before compilation. This still would have some version dependency, but it wouldn't be
byte code hacking One of these days I'll think some more on @@. As an experiment, I think
the tokenizer could translate @@deco to _AT_AT_deco and let the AST be formed with that
apparent function call at that place in the code. Then the AST could be walked to find the _AT_AT_<deconame>
calls and extract them and compile them and execute them (the _AT_AT_deco functions would
obviously have to be defined already, so they might be looked up in some standard place
like trying to do place = __import__(_AT_AT_MODULE_) wher _AT_AT_MODULE_ gets defined sort
of like __METACLASS__.), passing the AST and the _AT_AT_deco call location therein, and the rest
of the parameters.

AST decoration would introduce macro-like capabilities, but restricted to transforming valid ASTs,
so it isn't like source text rewriting macros.

Sorry for the run-on stream of consciousness ;-/

Regards,
Bengt Richter
 
Reply With Quote
 
Dan Sommers
Guest
Posts: n/a
 
      07-10-2005
On Sun, 10 Jul 2005 16:26:24 -0400,
"Terry Reedy" <(E-Mail Removed)> wrote:

> "Ralf W. Grosse-Kunstleve" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed). yahoo.com...


> I have a suggestion I don't remember seeing for flagging which vars to
> autoinit without new syntax: use '_' instead of '.'. I have never seen
> local vars with a leading '_'. So, in combination with whatever other
> mechanism (metaclass, __init__ decorator?)


> def __init__(self, _x, y, _z) :


> would automatically do self.x = _x, self.z = _z, but not self.y = y.


> Terry J. Reedy


That's a pretty big change; now all formal parameters beginning with an
underscore have a brand new meaning.

How about this:

def __init__(self, self.x, y, self.z):
# self.x, self.z from first and third explicit parameters
do_something_with_y()

where "self" in "self.x" and "self.y" would have to match the first
parameter (so that the pathological among us could write this:

def __init__(this, this.x, y, this.z):
do_something_with_y()

instead).

(Sorry if this posts multiple times; gnus and/or my news server were not
happy when I was composing this reply.)

Regards,
Dan

--
Dan Sommers
<http://www.tombstonezero.net/dan/>
 
Reply With Quote
 
Paul Rubin
Guest
Posts: n/a
 
      07-10-2005
Dan Sommers <(E-Mail Removed)> writes:
> def __init__(self, self.x, y, self.z):
> # self.x, self.z from first and third explicit parameters
> do_something_with_y()


Hey, I like that.
 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      07-11-2005

"Dan Sommers" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed). name.yeah.right...
> On Sun, 10 Jul 2005 16:26:24 -0400,
> "Terry Reedy" <(E-Mail Removed)> wrote:
>> I have a suggestion I don't remember seeing for flagging which vars to
>> autoinit without new syntax: use '_' instead of '.'. I have never seen
>> local vars with a leading '_'. So, in combination with whatever other
>> mechanism (metaclass, __init__ decorator?)

>
>> def __init__(self, _x, y, _z) :

>
>> would automatically do self.x = _x, self.z = _z, but not self.y = y.

>
>> Terry J. Reedy

>
> That's a pretty big change; now all formal parameters beginning with an
> underscore have a brand new meaning.


As I said, 'in combination with whatever other mechanism', meaning one that
one has to intentionally invoke. So there would be no code breaking: the
suggestion is for a convention used with currently available mechanism
(assuming that such is possible) that would give the fine-grained control
not so easily possible with the current update_dict_with_locals idiom.

It would be easier to write the decorator if it were passed the (quoted)
names of the parameters to be 'attributed'. But then the user would have
to write and keep in synchrony two lists, one a (quoted) subset of the
other. So I thought it better to have the decorator writer and decorator
function work a little harder to introspect and interpret one list with
some items marked somehow in a currently legal but unusual manner.

> How about this:
>
> def __init__(self, self.x, y, self.z):
> # self.x, self.z from first and third explicit parameters


This is new syntax that is not currently legal. My suggestion was for a
solution that avoided that difficulty and that could, I believe, be
implemented now, in less time that this thread has been going on, rather
than maybe some years from now.

Terry J. Reedy



 
Reply With Quote
 
Dan Sommers
Guest
Posts: n/a
 
      07-11-2005
On Sun, 10 Jul 2005 20:11:38 -0400,
"Terry Reedy" <(E-Mail Removed)> wrote:

> "Dan Sommers" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed). name.yeah.right...


>> That's a pretty big change; now all formal parameters beginning with
>> an underscore have a brand new meaning.


> As I said, 'in combination with whatever other mechanism', meaning one
> that one has to intentionally invoke ...


My mistake; I didn't read carefully enough.

Regards,
Dan

--
Dan Sommers
<http://www.tombstonezero.net/dan/>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Reducing import try/except boilerplate Nick Coghlan Python 1 12-21-2005 05:48 PM
__autoinit__ (Was: Proposal: reducing self.x=x; self.y=y;self.z=z boilerplate code) falcon Python 0 07-31-2005 05:41 PM
Re: __autoinit__ (Was: Proposal: reducing self.x=x; self.y=y;self.z=z boilerplate code) Ralf W. Grosse-Kunstleve Python 2 07-12-2005 03:20 AM
Proposal: reducing self.x=x; self.y=y; self.z=z boilerplate code Ralf W. Grosse-Kunstleve Python 16 07-11-2005 09:28 PM
Boilerplate template code for database add/update/delete dwok ASP .Net 2 05-11-2005 03:38 PM



Advertisments