How to optionally import/construct class to member variable that will support IDE autocomplete
I have a Python library design that I'm trying to clean up, but I noticed that one piece isn't auto-completing in Eclipse/PyDev. I'm familiar enough for this not to be a problem for me, but its a library that others will end up using and auto-complete that doesn't work for a feature chunk won't do.
I'll just explain quickly what its trying to do, I re-created the design below. It all works, but auto-complete isn't useful. Maybe someone can just set me straight.
In module test_module2.py
import Main from test_module.py
from test_module import Main
class Second(object):
_main = Main
def set_main_variable(self, var):
self._main.variable = var
In module test_module.py
import sys
class Main(object):
variable = 0
second = None
def __init__(self):
for x in sys.modules.keys():
if x.endswith("test_module2"):
y = sys.modules[x]
self.second = y.Second()
self.second._main = self
def print_variable(self):
print self.variable
In application test.py
import test_module
import test_module2
if __name__ == "__main__":
m = test_module.Main()
m.second.set_main_variable(10)
m.print_variable() # prints 10
With this, if the test_module2.py module is imported, you can access it via a separate namespace member variable Main.second. Keeps things separate, and if the module isn't available, then you don't have access to Second's features.
In test_module2.py, Main is imported (you can't use Second without Main anyways) and _main is default to Main. This allows auto-complete in Second when you're working on the parent _main reference that's setup when Main is constructed and Second was imported. (this is good)
In Main, Second is optional and is never directly calls from Main methods. So auto-complete isn't necessary. (this is fine)
In __main__, auto-complete naturally works for Main member variables and methods, but doesn't work with m.second. I can't default m.second to anything because I'd end up having to import test_module2.py from test_module.py. It's optional and is defined by __main__'s import of test_module2.py. e.g. if __main__ imports test_module2.py, then Second is automatically available to the application.
Anyone have a better way to have an optionally imported module/class construct to a member variable, that will work with IDE auto-completion?
Thanks in advance for any ideas.
I'm going to come to the conclusion that auto-completion with PyDev will only see a variable set to a class's members if the parent class inherits from it, or defaults the variable to the class itself. For example:
class Main(object):
second = Second
Then in __main__ you can auto-complete: main.second...
That or Main has to inherit from Second.
Ok, I need to go back and complain that this library design isn't going to work with IDE auto-completion. See if I can use an wrapper class to inherit if the import test_module2 is present and clean things up.
My solution: Here's what I came up with:
In module test_module2.py
import test_module
class Second(object):
_variable = 0 # overrided by Main's _variable
def set_main_variable(self, var):
self._variable = var
class Main(test_module.Main, Second):
def __init__(self):
super(Main, self).__init__()
In module test_module.py
class Main(o开发者_高级运维bject):
_variable = 0
second = None
def __init__(self):
super(Main, self).__init__()
def print_variable(self):
print self._variable
Now! In test.py if you import test_module or test_module2 (not both), you can construct Main with or without Second's added functionality. Second will have access to everything in Main, and because Main is inheriting Second, auto-complete works.
In application test.py
#import test_module
import test_module2
if __name__ == "__main__":
m = test_module.Main()
m.set_main_variable(10)
m.print_variable() # prints 10
I don't know if I can easily move Second's methods into a sub-namespace, like Main.second.set_variable(). I would have to explicitly set a Main reference within Second after Main constructs it as a variable, (in Main init, self.second = Second()) and not have Second inherited by Main. Then you could call m.second.set_main_variable(10), and keep all Second methods accesible from Main under the .second namespace.
First, Simple is better than complex -- your design appears to be complicated for no good reason. Maybe you should provide some details about your actual library.
Second, with Python as a dynamically typed language, it's just natural that there are cases when your IDE fails to auto-complete because your IDE has a static perspective. And you definitely shouldn't programm to suite the capabilites of your IDE.
精彩评论