I write some python functions to read/write simple spatial data like points, polygons, triangulated surfaces into/from a simple data structure in Python. I'm aware there are some possibilities to access those data structure from C or C++ like in this post:
Passing Python list to C++ vector using Boost.python
However, I'm not an experienced programmer using templates and I would like to start first with an easy way - if it exist. So if I have a list of point objects (see simple class definition), how would I access this list from a C-Program reading the respective variables.
class point3d():
def __init__(self, objectName, version, id=[], xyz=[], prop=[], unit=[], val=[]):
self.id = id
self.xyz = xyz
self.prop = prop
self.unit = unit
self.val = val
dim = len(self.xyz)
self.objectName = objectName
self.version = version
if dim == 1:
self.x = self.xyz[0]
elif dim == 2:
self.x = self.xyz[0]
self.y = self.xyz[1]
elif dim == 3:
self.x = self.xyz[0]
self.y = self.xyz[1]
self.z = self.xyz[2]
def __del__(self):
pass
def getObjectName(self):
return self.objectName
def getVersion(self):
return self.version
def getXYZ(self):
return self.xyz
def getDim(self):
return self.dim
def getProp(self):
return self.prop
def getUnit(self):
return self.unit
def getVal(self):
return self.val
def getId(self):
return self.id
If you want to call a C/C++ function from your python program, ctypes is the way to go.
Related
I need to overload the addition function so that it takes in the first point and the end point as the left and right side of the equation and outputs the equation. This is what my code looks right now. I'm not sure how to involve the line class?
import math
class Point:
'''Class that creates points. Attributes: Eastings and Northings'''
def __init__(self,x,y):
self.eastings = x
self.northings = y
def getCoords(self):
self.coords = (self.eastings,self.northings)
return self.coords
def setCoords(self,other_x,other_y):
self.eastings = float(other_x)
self.northings = float(other_y)
def __str__(self):
return f"{self.eastings},{self.northings}"
def __add__(self,new_point):
pass
#creates a line (new class)
class Line(Point):
'''Class that creates line object based on two points'''
def __init__(self,start,end):
self.start = start #Type:Point (x1,y1)
self.end = end #Type:Point (x2,y2)
self.latitude = abs(self.end.eastings - self.start.eastings)
self.departure = abs(self.end.northings - self.start.northings)
self.distance = math.sqrt((self.latitude)**2 + (self.departure)**2)
self.azimuth = math.degrees(math.atan2(self.departure,self.latitude))
def __getitem__(self,key):
if key == 0:
ans = self.start
elif key == 1:
ans = self.end
else:
print("invalid index")
return ans
#test code
a = Point(0,0)
b = Point(1,1)
c = Point(1,0.5)
line1 = a+b
print((type(line1))
The test code is supposed to print out the type as class line.
There's nothing that says the __add__() method has to return a the same type as the instance — which means you could this:
class Point:
...
def __add__(self, other):
if isinstance(other, Point):
return Line(self, other) # Line from this Point to the other.
else:
raise TypeError(f"Can't add a non-Point to a Point}")
Be careful doing this however, because the Line class will inherit the method (so you probably need to modify its version of it).
Add a self.getCoords() call to your Point.__init__() method.
Add return Line(self, new_point) to your Point.__add__() method.
Testing:
a = Point(0,0)
b = Point(1,1)
c = Point(1,0.5)
line1 = a+b
print(type(line1)) # I have removed a round bracket on the left
Output: <class '__main__.Line'>
In case you want to run a block of code, where a function/method has not one line in it, you have to add a pass to it. Otherwise you will get an error, because the structure requires it. Or you comment the function declaration out.
This is a big one and I apologize.
I am practicing to make my coding more modular.
We are tasked to create a Shipyard system.
There are Containers in the Shipyard and Packages in the Containers.
There is a LinkedList program provided that can be imported. I added it on the bottom.
IMPORTANT: I CANNOT ALTER THE SORTED LINKED LIST PROGRAM IN ANY WAY HENCE WHY I USE OVERLOADERS
I have another program which is non-modular. It is specifically made for the assignment at hand and it works for the most part.
Python 3.5
from SortedLList import *
class Shipyard:
def __init__(self):
self._container = SortedLList()
def add(self, owner, destination, weight):
"""
This function does:
1. Adds a container for a specific destination if doesn't exist.
2. Adds a package in a container given that the total weight
doesn't exceed 2000 lbs
3. If it does, it creates another container headed in the same
direction and then the package is inserted there instead.
"""
self._container.insert(Self.Container(destination))
class Container:
def __init__(self, destination):
self._package = SortedLList()
self._dest = destination
self._weight = 0
self._max = 2000
def add_pack(self, owner, destination, weight):
"""
This function adds the weight of the package to the total
container weight. And inserts a Package Singly Linked List
object inside the container.
"""
self._weight += weight
self._package.insert(Self.Package(destination))
def __lt__(self, other):
return self._dest < other._dest
def __ge__(self, other):
return self._dest >= other._dest
def __eq__(self, other):
return self._dest == other._dest
class Package:
def __init__(self, owner, destination, weight):
self._owner = owner
self._dest = destination
self._weight = weight
def __lt__(self, other):
return self._weight < other._weight
def __ge__(self, other):
return self._weight >= other._weight
def __eq__(self, other):
return self._weight == other._weight
class SortedLList :
class _Node :
def __init__(self, elem, next) :
self._elem = elem
self._next = next
def __init__(self) :
self._first = None
self._size = 0
def __len__(self) :
return self._size
def isEmpty(self) :
return len(self) == 0
def first(self):
return self._elem._first
def insert(self, val) :
if (self.isEmpty() or val <self._first._elem):
self._size+=1
self._first = self._Node(val,self._first)
tmpRef=self._first
while(tmpRef._next!=None and val>=tmpRef._next._elem):
tmpRef=tmpRef._next
if val==tmpRef._elem:
return
self._size+=1
tmpRef._next=self._Node(val,tmpRef._next)
return
def isPresent(self, elem) :
tmpRef=self._first
while(tmpRef!=None):
if tmpRef._elem==elem:
return True
tmpRef=tmpRef._next
return False
def delete(self, elem) :
if self.isEmpty() :
return
if elem == self._first._elem :
self._size -= 1
self._first = self._first._next
return
tmpRef = self._first
while (tmpRef._next != None and elem > tmpRef._next._elem) :
tmpRef = tmpRef._next
if tmpRef._next == None : return
if tmpRef._next._elem != elem : return
self._size -= 1
tmpRef._next = tmpRef._next._next
return
def traversePrint(self) :
tmpRef = self._first
while tmpRef != None :
print(tmpRef._elem)
tmpRef = tmpRef._next
class Empty(Exception) :
pass
I want to be able to use the methods in the SortedLList program to be able to display information that I have in the main program.
Is there any way around typing:
print(self._cont._first._elem._dest) or print(self._cont._first._elem._package._first._elem._owner) by using traversePrint() without altering the helper code?
You can inherit SortedLList in a new class and overload the methods you want.
class MySortedLList(SortedLList):
def traversePrint(self):
# Your custom implementation
and then using that instead of SortedLLIst, e.g:
class Shipyard:
def __init__(self):
self._container = MySortedLList()
However,, you asked if you can use the SortedLList.traversePrint to print information about your main program, presumable Shipyard. This probably doesn't make sense because you'd break encapsulation. SortedLList knows about its elements and can only know about Shipyard if you give it a reference to Shipyard. So rather let Shipyard tell you about itself.
I am working on creating a module with a class that acts as a container for a list of another created class. Is there a way for the container class to be able to tell if any of the objects it contains has changed?
Here is an example:
class Part:
def __init__(self, size):
self.part_size = size
class Assembly:
def __init__(self, *parts):
self.parts = list(parts) # `parts` are all Part() objects
self.update()
def update(self):
self.assy_size = 0
for each in self.parts:
self.assy_size += each.part_size
def __getitem__(self, key):
return self.parts[key]
This is what I get if I try to change any of the Part properties in the Assembly:
>>>x = Part(1)
>>>y = Part(1)
>>>z = Part(1)
>>>u = Assembly(x, y, z)
>>>u.assy_size
3
>>>u[0].part_size = 4
>>>u.assy_size
3
I know that I can create additional methods that will call the update method if I replace, delete, or add Part objects to the Assembly, but is there any way to have the Assembly notified if any of the contained Part properties have changed?
The answer is in your question. Use a property.
class Part:
_size = 0
assembly = None
#property
def part_size(self):
return self._size
#part_size.setter
def part_size(self, value):
self._size = value
if self.assembly: # only notify if an Assembly is set
self.assembly.update()
def set_assembly(self, assembly):
self.assembly = assembly
def __init__(self, size):
self.part_size = size
class Assembly:
def __init__(self, *parts):
self.parts = list(parts) # `parts` are all Part() objects
for part in self.parts:
part.set_assembly(self) # reference to self needed to notify changes
self.update()
def update(self):
self.assy_size = 0
for each in self.parts:
self.assy_size += each.part_size
In this version of Assembly the constructor sets a reference on the Part to itself. This way it can update the assembly when the part_size changes. Use it as the example in your question.
>>>x = Part(1)
>>>y = Part(1)
>>>z = Part(1)
>>>u = Assembly(x, y, z)
>>>u.assy_size
3
>>>u[0].part_size = 4
>>>u.assy_size
6
If update isn't an expensive operation (in your example it isn't, but maybe in reality you have thousands of parts), you could calculate the size ad-hoc using a property:
class Assembly:
def __init__(self, *parts):
self.parts = list(parts)
#property
def assy_size(self):
result = 0
for each in self.parts:
result += each.part_size
return result
which can be accessed the same way: assembly.assy_size.
The calculation can also be simplified:
#property
def assy_size(self):
return sum(part.part_size for part in self.parts)
I think I'm misusing the concept of subclass. I'm working on a hobby project with Grids and Cells.
What I have, is the implementation of a Cell class, and its subclass HexCell which basically redefines many of the attributes/methods like so:
class Cell:
def __init__(self, row_loc, col_loc):
self.row = row_loc
self.col = col_loc
self.links = set()
self.neighbors = 4*[None]
def __repr__(self):
return f'Cell #({self.row},{self.col})'
def link(self, other, bidir = True):
self.links.add(other)
if bidir: other.links.add(self)
Then I have a subclass that is the HexGrid which follows a similar structure with new parameters.
class HexCell(Cell):
def __init__(self, r_out, th_around):
# I'm indexing Hex cells around a center cell
# instead of by rows and columns; Prefixed hex
# as they follow the hexagon, and not regular polar coordinates.
self.hex_r = r_out
self.hex_th = th_around
self.neighbors = 6*[None]
self.links = set()
def __repr__(self):
return f"HexCell #[{self.hex_r}, {self.hex_th}]"
def bind(self, other, to_dir):
to_dir = to_dir % 6
if (self.neighbors[to_dir] is None):
self.neighbors[to_dir] = other
other.neighbors[to_dir - 3] = self
# Hexagonal grids share neighbors.
other_1 = other.neighbors[to_dir - 2]
if (self.neighbors[to_dir - 1] is None) & (other_1 is not None):
self.bind(other_1, to_dir - 1)
other_5 = other.neighbors[to_dir - 4]
if (self.neighbors[to_dir - 5] is None) & (other_5 is not None):
self.bind(other_5, to_dir - 5)
In this case, the method self.link(other) is shared, but other attributes change from rectangular grid to hexagonal like the locaion from (row, col) to (hex_r, hex_th), or neighbors as a 4-list or 6-list. Thus I'd like these attributes to be dependent on a another cell-type attribute and transferred down to the subclass.
Correct use of subclassing needs to obey the following substitution principle:
If there are some objects x_1 of type T_1 and x_2 of type T_2 such that issubclass(T_2, T_1) == True, then any property that applies to x_1 must also apply for x_2.
In other words, you expect subclassing to implement new behaviours, not to change existing behaviours.
In you example, the change of coordinate system itself is a change of behaviour and thus HexCell should not inherit from Cell.
What you can do is create a base class BaseCell that encapsulates the common behaviour between Cell and HexCell and inherit from it.
class BaseCell:
def __init__(self):
self.links = set()
self.neighbors = []
def add_neighbor(self, other):
self.neighbors.append(other)
def link(self, other, bidirectional=True):
self.links.add(other)
if bidirectional:
other.link(self, bidirectional=False)
class Cell(BaseCell):
def __init__(self, row_loc, col_loc):
self.row = row_loc
self.col = col_loc
super().__init__()
def __repr__(self):
return f'Cell #({self.row},{self.col})'
class HexCell(Cell):
def __init__(self, r_out, th_around):
self.hex_r = r_out
self.hex_th = th_around
super().__init__()
def __repr__(self):
return f"HexCell #[{self.hex_r}, {self.hex_th}]"
def bind(self, other, to_dir):
...
Your Cell class is in fact not an abstract "Cell", but a square cell in two-dimensional space (has exactly 4 neighbours, has "row" and "col" position). Such cell may not be subclassed by a hex cell, because hex cell is just a different type of cell : )
As you noticed, the only common things are link() method and links attribute. If you insist on subclassing, you could create something like:
class LinkedObject():
def __init__(self):
self.links = set()
def link(self, other, bidir = True):
self.links.add(other)
if bidir: other.links.add(self)
class SquareCell(LinkedObject):
# "Cell" class here
class HexCell(LinkedObject):
# HexCell here
I was messing around with classes in python and wrote 2 little ones:
class ClaElement:
start = None
end = None
basesLeft = None
orientation = None
contig = None
size = None
def __init__(self, contig, start, end, orientation, basesLeft=None):
self.contig = contig
self.start = start
self.end = end
self.orientation = orientation
self.basesLeft = basesLeft
self.size = self.end - self.start
def __str__(self):
return "{ClaElement: "+str(self.contig)+"_"+str(self.start)+"_"+str(self.end)+"_"+str(self.orientation)+"}"
def getSize(self):
return self.size
class ClaCluster:
contig = None
clusterElements = []
def __init__(self, contig, firstElement):
self.contig = contig
self.addElement(firstElement)
def addElement(self, claElement):
self.clusterElements.append(claElement)
def getFirst(self):
return self.clusterElements[0]
def getLast(self):
return self.clusterElements[-1]
def getElements(self):
return self.clusterElements
def getContig(self):
return self.contig
def __str__(self):
return "{ClaCluster: "+str(self.contig)+" "+str(len(self.clusterElements))+" elements}"
And my test-main:
from ClaElement import ClaElement
from ClaCluster import ClaCluster
if __name__ == '__main__':
ele = ClaElement("x",1,2,"left")
claDict = dict()
cluster = ClaCluster("x", ele)
claDict["hello"] = cluster
print(claDict)
print(claDict["hello"])
print(ele)
This leads to the following output:
{'hello': <ClaCluster.ClaCluster object at 0x7fe8ee04c5f8>}
{ClaCluster: x 1 elements}
{ClaElement: x_1_2_left}
Now my question is why is the output of my first print the memory address even though I provided a functioning string-method for my class ClaCluster? Is there a way to get the method invoked when I am printing the dictionary or do I have to iterate by hand?
The __str__() method of the built-in dict type uses the __repr__() method of your class, not __str__(). Simply rename your method, and all should work fine.