How can I sort out code from a class to another file?
For example I have a large class called “Writer”. it has dozens of defs and they call each other. I want to move some defs to another .py file to keep the overview.
My attempt was to take some def from class “Writer” to a new file, put them there into a class called e.g. “ESwriter”.
The point is that the defs in calss ESwriter in turn calls some other defs in class Writer. This compiles but when executed the other defs in calss Writer do not return anything.
An example:
Sounds like you have a circular dependency, but I believe your code could still run.
If you either could share the working code (before change), a minimal running example (after the change), or both. That would be good to better know what gets called when, and what is supposed to happen.
The file that should be split is attached:
writer.py
From this file the defs named “*ElectrostaticSolver” of the class “Writer” should be sorted out. Here is my attempt to sort them out to a new file:
electrostatic_writer.py
Do I understand correctly that you have added something like this in writer.py?
def _handleElectrostatic(self):
...
if activeIn:
ESW = test.ESwriter(self.solver, self.directory)
ESW._handleElectrostaticConstants()
If so. You’re creating a new instance of Writer when you create an instance of ESwriter. That looks suspicious. If you just want to split the code into separate files this should be enough:
Yes and this is why I am stuck. I only want to split the too long writer.py but get a circular dependency.
many thanks.
However this still elads to a circular dependency.
I have now this:
# writer.py
from .equations import electrostatic_writer as ES_writer
class Writer(object):
def __init__(self, solver, directory, testmode=False):
self.analysis = solver.getParentGroup()
...
def _handleElectrostatic(self):
...
if activeIn:
ESW = ES_writer.ESwriter(this, self.solver)
ESW._handleElectrostaticConstants()
...
# electrostatic_writer.py
class ESwriter:
def __init__(self, writer, solver):
self.writer = writer
self.solver = solver
def _getElectrostaticSolver(self, equation):
# check if we need to update the equation
self._updateElectrostaticSolver(equation)
...
This gives me this error:
File "D:\FreeCAD-build\Mod\Fem\femsolver\elmer\writer.py", line 98, in write_solver_input
self._handleElectrostatic()
File "D:\FreeCAD-build\Mod\Fem\femsolver\elmer\writer.py", line 857, in _handleElectrostatic
ESW = ES_writer.ESwriter(this, self.solver)
NameError: name 'this' is not defined
05:59:31 File "D:\FreeCAD-build\Mod\Fem\femsolver\elmer\writer.py", line 857, in _handleElectrostatic
05:59:31 ESW = ES_writer.ESwriter(self, self.solver)
05:59:31 File "D:\FreeCAD-build\Mod\Fem\femsolver\elmer\equations\electrostatic_writer.py", line 41, in __init__
05:59:31 self.write = writer.Writer(self.solver, self.directory)
05:59:31 File "D:\FreeCAD-build\Mod\Fem\femsolver\elmer\writer.py", line 79, in __init__
05:59:31 self.analysis = solver.getParentGroup()
05:59:31 AttributeError: 'Writer' object has no attribute 'getParentGroup'
What I need is that the def “_getElectrostaticSolver” from the ESWriter calls uses the defs in the already loaded Writer class and not to re-initialize the Writer class.
Side note: it appears you are making a public function that you prefix with an underscore. In Python we do not do that, the underscore is used to indicate that a function is “private”, that is, that your IDE should not list it as a possible completion for outside code to call. It’s just a convention, of course, Python itself doesn’t have the idea of private functions. Nevertheless, it appears from the code blocks in this discussion that you should lose the underscore in the method name.
Two things jump out at me: first, you do not need to import writer – since you are passing it into the class, there is no need for the line that also imports its definition. Python doesn’t care – as long as the writer object provides the needed functions at call-time, you are good to go.
Second, you appear to be referencing a non-existent object (write):
def _getElectrostaticSolver(self, equation):
# check if we need to update the equation
self._updateElectrostaticSolver(equation)
# output the equation parameters
s = self.write._createLinearSolver(equation)
As far as I can see, there is no “self.write” – maybe you mean “self.writer”?
Have this open for a long time.
In case it may be useful again, I guess you could use dynamic subclassing in Python. Here is a very simple example to demonstrate :
class Writer:
def __init__(self, es=False):
self.testme()
App.Console.PrintMessage("Testing if needs dynamic subclassing\n")
if es:
self.__class__ = ESWriter
self.specificInit()
self.testme()
App.Console.PrintMessage("---------------\n")
def testme(self):
App.Console.PrintMessage("I'm a Writer\n")
class ESWriter(Writer):
def __init__(self):
super.__init__()
specificInit()
def specificInit(self):
# do specific init actions here
pass
def testme(self):
App.Console.PrintMessage("I'm a ESWriter\n")
Writer()
Writer(True)