I am a novice of Python and I am trying to understand how to use OOP paradigm to improve my scripts. My scripts usually read some data from a formatted csv file and perform some numerical analysis. Here is a short example:
SIMPLY SUPPORTED BEAM NNODES <NNnodes><Node,X,Y> 2 1,0,0 2,1,0
This input is for a script for solving a structural analysis problem. Generally one may want to extend the functionalities of the script adding new features, for instance adding elements, materials, section properties and so on.
My idea is to set up the code in such way one can include those functionalities in the easiest possible way.
My solution is to create a class, and then extend it using inheritance. Here what I wrote so far:
- A class for the properties of the problem, named
- Two initial instance variables storing the name of the input file and the title (first row of the csv file)
- A method for reading information from the file, named
class Mesh() : 'class defining the property of the problem' def __init__(self) : self.name = None self.title = None def read_input(self, input_name) : self.name = input_name with open(self.name) as file : self.title = file.readline()
Let's say that one may want to improve the script including the number of nodes (NNODES in the csv file). First I create a class for node, storing ID and coordinates:
class Node() : 'class for defining a node' def __init__(self, input1 , input2 , input3) : self.ID = int(input1) self.x = float(input2) self.y = float(input3)
Then I add "functionalities" to the class defining a new child class (with the same name of the parent class, because I don't actually need a new child class, just a redefinition of the initial
Mesh class ). The new class reads:
- New constructor, using super() to include the parent class constructor and new instance variables.
- Redefinition of the
read_inputmethod to include the new lines of the csv file.
class Mesh(Mesh) : 'Mesh that includes nodal loads' def __init__ (self) : super().__init__() self.Nnodes = None self.nodes = list() def read_input(self, input_name) : super().read_input(input_name) with open(self.name) as file : while not file.readline().startswith('NNODES') : continue self.Nnodes = int( file.readline() ) for node in range(0,self.Nnodes) : ID , x, y = file.readline().split(',') self.nodes.append( Node( ID , x, y ) )
Finally, the initialization of the class and the use of the method to read the file:
input = Mesh() input.read_input('input_short.txt')
Here my doubts:
- Is it a good application of the OOP paradigm or I have totally misunderstood the concept?
- Does it have any sense to call the child class with the same name of the parent class? (I did not find any examples in previous questions)
- Is it a good way to structure the code? Maybe other people than me will modify the code in future, and I would like to simplifies this procedure as much as possible.
I have always used procedural languages, such as C and FORTRAN, and I don't have any experience in OOP paradigm.
EDIT I modified the code with suggestions from StackOverflow
- Modification of the class
Mesh, in this way it should be self-contained.
- Child class name different from the parent one.
- Use of dataclass for defining the
from dataclasses import dataclass class Mesh() : 'class defining the property of the problem' def __init__(self , input1) : self.title = input1 name = 'input_short.txt''' with open(name) as file : mesh1 = Mesh( file.readline() ) #let's add a new functionality @dataclass class Node: 'class for defining a node' ID: int x: float y: float class Mesh_nodes(Mesh) : 'Extend Mesh class to account for nodes' def __init__(self , input1, input2, input3) : super().__init__(input1) self.Nnodes = input2 self.nodes = input3 name = 'input_short.txt''' with open(name) as file : while not file.readline().startswith('NNODES') : continue Nnodes = int( file.readline() ) nodes = list() for node in range(0,Nnodes) : ID , x, y = file.readline().split(',') nodes.append( Node( int(ID) , float(x), float(y) ) ) mesh1 = Mesh_nodes(name,Nnodes,nodes)
Anyway, my original questions are still valid:
Is it a good application of the OOP paradigm or I have totally misunderstood the concept?
Is it a good way to structure the code? Maybe other people than me will modify the code in future, and I would like to simplifies this procedure as much as possible.