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

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Dec 8 05:45:55 EST 2010


On Tue, 07 Dec 2010 07:52:06 -0800, gst wrote:

> Hi,
> 
> I met a situation where I was passing an object created in/with an upper
> level module class to a lower level module class' instance in one of its
> __init__ argument and saving a ref of the upper object in that lower
> level class' new instance.
> 
> 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?


> 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.

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


> files:
> module1.py
> subpackage/module2.py
> 
> 
> file module1.py:
> 
> from subpackage.module2 import class2

Is it relevant that class2 comes from another module? Would your concept 
work if class1 and class2 were defined in the same file?

By the way, it's conventional (but not compulsory) to name classes with 
an initial capital letter, and instances in all lowercase.



> 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.


>     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.

 
> 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 :)


>         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?


-- 
Steven



More information about the Python-list mailing list