Вопрос

In a module Foo I have a function :

def register_scheme(class_name,*properties_class):
    scheme_class = type(class_name, (Scheme,), dict( _properties_classes={c.__name__:c for c in properties_class} )) # Scheme is another class defined in Foo
    globals()[class_name] = scheme_class

In another module that imports Foo I do:

foo.register_scheme("ball",color,distance) # color and distance are two classes defined in this module

Now I can do this :

ball = foo.ball("color"=red,"distance"=0.5) # __init__ function of Scheme takes care of this, code not shown

The code works fine, but pydev complains with a red cross saying "undefined variable from import : ball".

It was to be expected. The issues is that I am going to register a lots of "scheme" in my code, resulting in error messages all over the place. I guess that will not have terrible consequences, but that will be really annoying.

Would anybody have a solution ?


EDIT

Here is my solution, which does not correspond exactly to what I wanted, but close enough

def register_scheme(class_name,*properties_class):
    #here some code checking if this class name is ok, removed for brevity #
    scheme_class = type(class_name, (Scheme,), dict( _properties_classes={c.__name__:c for c in properties_class} )) 
    Scheme._known_scheme_classes[class_name]=scheme_class # _known_scheme_classes is a class dict of Scheme

def create(scheme_class_name,**values):
    # some code checking such class has been registered, removed for brevity #
    return Scheme._known_scheme_classes[scheme_class_name](**values)

Now I can do this in other modules importing foo:

foo.register_scheme("ball",color,distance)
my_ball = foo.create("ball",color="red",distance=0.5)
Это было полезно?

Решение

Python is a dynamic language, so static code analyzer cannot introspect everything.

In your case it is absolutely normal that PyDev complains that foo.ball is an "undefined variable", because it ball was not defined in the foo module, it is created at run-time. Eclipse doesn't and cannot know this without actually running the program.

Generally it is bad idea to have this kind of magic.

You have this in your code:

globals()[class_name] = scheme_class

So you are dynamically creating a class without verifying if it was already created and then inject it into the globals.

Then would suggest you instead of injecting it just return it:

def crate_scheme(class_name, *properties_class):
    scheme_class = type(class_name, (Scheme,), dict( _properties_classes={c.__name__:c for c in properties_class} )) # Scheme is another class defined in Foo
    return scheme_class

Then you would do in another module:

Ball = foo.create_scheme("ball", color, distance)  # color and distance are two classes defined in this module
ball = Ball("color"=red, "distance"=0.5)  # __init__ function of Scheme takes care of this, code not shown

This should help getting rid of the PyDev complains, but anyway creating classes on the fly should be avoided if possible: explicit is better than implicit (import this).

Use composition instead of inheritance here.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top