use of __new__ to permit "dynamic" completion within (any?) IDE ?

gst g.starck at gmail.com
Wed Dec 8 07:01:38 EST 2010


On 8 déc, 11:45, Steven D'Aprano <steve
+comp.lang.pyt... at pearwood.info> wrote:
> On Tue, 07 Dec 2010 07:52:06 -0800, gst wrote:
> > Hi,
>
> > But in my IDE I want the completion to also work from within the lower
> > level module when it's refering to the object passed from the upper
> > level:
>
> "The completion"? What do you mean?

Hi,

I mean the autocompletion feature of my IDE :

when I type "object."  then on the "." it shows me possible members/
methods of the 'object'. depending on what my IDE can guess about the
object possible type(s) ;  in the worst case it can't guess nothing
about it and that's my point below..


> > Well, I'm sure I'm not very clear in my terms (and probably a bit long
> > in the sentence) so here it is in code:
>
> I'm afraid I have to agree with your, your description is not clear to me.

I hope I'm now ;)

> Unfortunately, neither is your code, because I don't understand *why* you
> do the things you do.

damn. ok let's go..


> > file module1.py:
>
> > from subpackage.module2 import class2
>
> Is it relevant that class2 comes from another module?

yes.  hmmm or maybe not completely.. I think it only highly depends on
what the IDE can guess on an object type used inside some methods
depending on the files hierarchy..


> Would your concept work if class1 and class2 were defined in the same file?

I guess yes also.


> > class class1(object):
>
> >     def __new__(cls, _self=None, *args, **kwargs):
> >         if _self:  ## we've been passed an instance already
> > initialyzed
> >                      ## so directly return it instead of creating a
> > new object.
> >             return _self
> >         return object.__new__(cls)
>
> Depending on your application, this may be an unsafe assumption. If the
> caller says class1("spam"), your class will return "spam". This may or
> may not be what you want.

I'm always passing the good object type when I do this.


> >     def __init__(self, _self=None, *args, **kwargs):
> >         if _self:  ## we've been passed an instance already
> > initialyzed
> >                      ## so directly returns
> >             ## assert(self is _self) ?
> >             return
> >         self.object2 = class2(object1=self, "blip", "blop") # others
> >         init
>
> Okay, this seems like a fairly straightforward case of adding an
> attribute to your instance that includes a reference to itself. No big
> deal... there's nothing wrong with this, although you are creating a
> reference cycle, which is somewhat of a (mild) code-smell.

that is a worry effectively.  (hmm when you say it's a case of adding
an attribute that includes a ref to itself it's not really that (or i
badly understand) : it's adding an attribute to a lower level class
instance that contains a ref to an upper level class instance (which
also contains a ref to the lower level class' instance and that's the
cycle (and that's a bit my worry))

> > file module2.py:
>
> > class class2(object):
>
> >     def __init__(self, object1, *args, **kwargs):
>
> >         from ..module1 import class1
>
> Now you have a circular import, and that's a pretty major code smell.
> That's dangerous. Try to avoid it. Perhaps the easiest way to avoid it is
> to place class1 and class2 in the same module, and stop writing Java :)

damn if this looks like Java it's really not my will ;  I've not made
Java anymore for probably 10 years !

I'll try by putting class1 and  class2 in same module (or at same
directory level first) and see if that can do it..

>
> >         self.object1 = class1(_self=object1)    ## instead of:
> > self.object1 = object1
>
> >     ## others functions and/or init..
> >     ## where  now I've completion working on self.object1 : ## if I
> >     add(or remove) fields/methods in module1 (and save) then ## I have
> >     them available(or disappeared) in the completion when
> > executed from this submodule.
> >     ## This ofcourse permits to save me of remembering all of the
> > class1 attributes/methods when I'm working with self.object1 from within
> > one of class2 methods.
>
> I'm afraid I don't understand what you mean here in these comments. What
> do you mean, "save me of (from?) remembering all the class1 attributes/
> methods..." -- how does it save you from knowing the methods? Whether you
> write this:
>
> instance = class1()
> instance.method()
>
> or this:
>
> instance = class1()
> another_instance = class2(instance)
> another_instance.object1.method()
>
> you still need to know the name "method".
>
> It seems to me that this scheme is unnecessarily complex, convoluted and
> confusing, for very little gain. Perhaps you could try explaining what
> you hope to accomplish, giving examples?

Effectively I recognise that this seems like a bit silly/odd .. but as
it's working I wanted some advises so ;)

As I told I try to have some kind of "ultimate" autocompletion, always
working for this kind of case (I know exactly that a certain member of
a certain class' instance will always have the same type but my IDE
doesn't seem to guess/know it.. ; I guess the best answer would be :
bad IDE, change IDE but I'm guessing that others IDE can't do a lot
better in this case.

Anyway many thanks for your reply ; I'll do some further tests with
your comments already..

regards,

greg.

nb: so this "hack" is only relevant during dev ; once the project
would be finished the "hack" could be removed (i.e : in class2 init I
would directly do : self.object1 = object1)



More information about the Python-list mailing list