I have the following code in main.py:
import json
from data import message # data.py
from definitions import * # definitions.py
waypoints=[]
stations=[]
genes = []
jsonObj = json.loads(message) # from data.py
for item in jsonObj:
location = Location(id=item["id"], name=item["name"], lat=item["lat"], lon=item["lon"])
if ("is-start" in item) or ("is-end" in item):
location.isWaypoint = True
if "is-start" in item:
start = location
else:
end = location
else:
genes.append(location)
if "is-waypoint" in item:
location.isWaypoint = True
waypoints.append(location)
else:
stations.append(location)
Then, I have the following code in definitions.py:
from haversine import haversine
start = None
end = None
distMatrix = {}
def distBtwn(loc1, loc2):
dist = 0
pair = frozenset((loc1.id, loc2.id))
if pair in distMatrix:
dist = distMatrix[pair]
else:
coords1 = (loc1.lat, loc2.lon)
coords2 = (loc2.lat, loc2.lon)
dist = haversine(coords1, coords2)
distMatrix[pair] = dist
return dist
class Location:
def __init__(self, id, name, lat, lon):
self.id = id
self.name = name
self.lat = lat
self.lon = lon
self.isWaypoint = False
def __repr__(self):
rep = ""
if self.isWaypoint:
rep += "Waypoint "
else:
rep += "Station "
rep += "%d: %s (%f, %f)" % (self.id, self.name, self.lat, self.lon)
return rep
class Fitness:
def __init__(self, route):
self.route = route
self.distance = 0.0
self.fitness = 0.0
def routeDistance(self):
if self.distance = 0.0:
global start
global end
print(start)
print(self.route[0])
print(self.route[-1])
print(end)
pathDistance = distBtwn(start, self.route[0]) + distBtwn(self.route[-1], end)
for i in range(len(self.route) - 1):
pathDistance += distBtwn(self.route[i], self.route[i + 1])
self.distance = pathDistance
return self.distance
I run main.py, then entered the following in the shell, which throws an error:
>>> start
Waypoint 0: startPoint (3.333333, 3.333333)
>>> end
Waypoint 2: endPoint (4.444444, 4.444444)
>>> route = [waypoints[0], stations[15], waypoints[1]]
>>> fitA = Fitness(route)
>>> fitA.routeDistance()
None
Waypoint 1: waypointA (1.111111, 1.111111)
Waypoint 3: waypointC (2.222222, 2.222222)
None
Traceback (most recent call last):
File "<pyshell#78>", line 1, in <module>
fitA.routeDistance()
File "definitions.py", line 54, in routeDistance
pathDistance = distBtwn(start, self.route[0]) + distBtwn(self.route[-1], end)
File "definitions.py", line 10, in distBtwn
pair = frozenset((loc1.id, loc2.id))
AttributeError: 'NoneType' object has no attribute 'id'
>>> start
Waypoint 0: startPoint (3.333333, 3.333333)
>>> end
Waypoint 2: endPoint (4.444444, 4.444444)
Based on the above, routeDistance() is using the original None values of start and end from initialisation, even though they've been declared as global variables. Yet when called from the shell, those two variables have already been updated correctly with Location objects assigned. What is going wrong here?
Global variables are scoped to a module.
For example, in foo.py:
def set_variable(to):
global variable
variable = to
variable = None
And bar.py:
import foo
def get_variable():
global variable # Unnecessary, but to avoid confusion
return variable
variable = 1
print(foo.variable) # None
foo.set_variable(2) # Sets `foo`'s global variable to `2`
print(get_variable()) # 1; `bar`'s global variable is still 1
print(foo.variable) # 2; `foo`'s global variable is now `2`
You need to set definitions.start and definitions.stop.
Related
'int' Object Not Callable Heap Sort Function
Im trying to create a function that return a sorted list but im getting the following error: "new_value = sort_heap.deleteMin() 'int' object is not callable"
This is the code:
class MinHeap:
def __init__(self):
self.heap=[]
def __str__(self):
return f'{self.heap}'
__repr__=__str__
def parent(self,index):
# -- YOUR CODE STARTS HERE
if index>len(self) or index<=1:
return None
else:
return self.heap[index//2-1]
def leftChild(self,index):
# -- YOUR CODE STARTS HERE
if index<1 or 2*index>len(self):
return None
else:
return self.heap[2*index-1]
def rightChild(self,index):
if index<1 or 2*index>len(self):
return None
else:
return self.heap[2*index-1]
def __len__(self):
return len(self.heap)
def insert(self,x):
self.heap.append(x)
current = len(self)
while self.parent(current) is not None and self.parent(current)>x:
self.heap[current-1], self.heap[current//2-1] = self.heap[current//2-1], self.heap[current-1]
current = current//2
#property
def deleteMin(self):
if len(self)==0:
return None
elif len(self)==1:
out=self.heap[0]
self.heap=[]
return out
deleted = self.heap[0]
current = 1
self.heap[0] = self.heap[len(self)-1]
x = self.heap.pop()
moved_value = self.heap[0]
while self.leftChild(current) is not None:
left=self.leftChild(current)
right=self.rightChild(current)
if right is not None:
if left<=right and left<moved_value:
self.heap[current-1], self.heap[current*2] = self.heap[current*2], self.heap[current-1]
current = current *2
elif left>right and right<moved_value:
self.heap[current-1], self.heap[current*2] = self.heap[current*2], self.heap[current-1]
current = (current*2) + 1
else:
break
else:
if left<moved_value:
self.heap[current-1], self.heap[(current*2)-1] = self.heap[(current*2)-1], self.heap[current-1]
current = current*2
else:
break
return deleted
def heapSort(numList):
'''
>>> heapSort([9,7,4,1,2,4,8,7,0,-1])
[-1, 0, 1, 2, 4, 4, 7, 7, 8, 9]
'''
sort_heap = MinHeap()
for i in range (len(numList)):
sort_heap.insert(numList[i])
sortedList= []
lenght=len(numList)
while lenght >0:
new_value = sort_heap.deleteMin()
sortedList.append(new_value)
lenght -= 1
return sortedList
The MinHeap class is a given but I'm allow to modify it. Could Someone please help? Thanks
Seeing your (btw wrong formatted code, please redo the formatting) code I can see, that deleteMin is a #property and not a class method. Therefore you shuld write:
new_value = sort_heap.deleteMin
# ^ You see, no brackets here
I am trying to call a function from within a function, and the former calls more functions etc.
import ROOT as root
import sys, math
class SFs():
def __init__(self):
self.get_EfficiencyData = None
self.get_EfficiencyMC = None
self.get_ScaleFactor = None
self.eff_dataH = None
self.eff_mcH = None
self.get_ScaleFactor = None
self.get_EfficiencyMC = None
def ScaleFactor(self,inputRootFile):
self.eff_dataH = root.std.map("string", root.TGraphAsymmErrors)()
self.eff_mcH = root.std.map("string", root.TGraphAsymmErrors)()
EtaBins=["Lt0p9", "0p9to1p2","1p2to2p1","Gt2p1"]
fileIn = root.TFile(inputRootFile,"read")
HistoBaseName = "Label"
etaBinsH = fileIn.Get("Bins")
# etaLabel, GraphName
nEtaBins = int(etaBinsH.GetNbinsX())
for iBin in range (0, nEtaBins):
etaLabel = EtaBins[iBin]
GraphName = HistoBaseName+etaLabel+"_Data"
print GraphName,etaLabel
self.eff_dataH[etaLabel]=fileIn.Get(str(GraphName))
self.eff_mcH[etaLabel]=fileIn.Get("histo")
print self.eff_mcH[etaLabel].GetXaxis().GetNbins()
print self.eff_mcH[etaLabel].GetX()[5]
self.get_ScaleFactor(46.8,2.0)
def get_ScaleFactor(self,pt, eta):
efficiency_mc = get_EfficiencyMC(pt, eta)
if efficiency_mc != 0.:
SF = 1/float(efficiency_mc)
else:
SF=1.
return SF
def get_EfficiencyMC(self,pt, eta):
label = FindEtaLabel(eta,"mc")
# label= "Lt0p9"
binNumber = etaBinsH.GetXaxis().FindFixBin(eta)
label = etaBinsH.GetXaxis().GetBinLabel(binNumber)
ptbin = FindPtBin(eff_mcH, label, pt)
Eta = math.fabs(eta)
print "eff_mcH ==================",eff_mcH,binNumber,label,ptbin
# ptbin=10
if ptbin == -99: eff =1
else: eff= eff_mcH[label].GetY()[ptbin-1]
if eff > 1.: eff = -1
if eff < 0: eff = 0.
print "inside eff_mc",eff
return eff
sf = SFs()
sf.ScaleFactor("Muon_IsoMu27.root")
I want to call the get_ScaleFactor() which in turn calls the get_EfficiencyMC() etc, but I once trying calling the former, I get TypeError: 'NoneType' object is not callable
in your class init you define:
self.get_EfficiencyMC = None
and later define a function (i.e. class method)
def get_EfficiencyMC(self,pt, eta):
when you create an instance of the class, the init part is executed shadowing the class method. Just either remove it from the init, or change the method name.
I read several post about the nested class, but this mechanism is still not clear for me.
Basically what I want to do is define a class (to solve ordinary differential equation in which I define one class for each order of accuracy )
Here's the class :
class AdamsBashforth(AdamsMethods):
class _2nd(AdamsMethods):
startup = False
def __init__(self, dydt : Rhs, filename :str = None , salve : bool = True ):
self.file = filename
self.save = save
super().__init__(dydt)
def solve(self):
self.time , self.u = self.dydt.createArray()
u[1] = rungekutta.RK2.step(self.dydt.f, time[0], u[0], self.dt)
for i in range(1,len(self.time)-1):
self.u[i+1] = u[i] + self.dt/2*(3*self.dydt.f(self.time[i],self.u[i])-self.dydt.f(self.time[i-1],self.u[i-1]))
AdamsBashforth._2nd.solved = True
if self.file != None:
super().write2file()
if self.save:
return self.time,self.u
def plot(self):
if AdamsBashforth._2nd.solved:
super().plot('Sys ODE solution using Adams-Bashforth 2nd order','time [s]','y(t)')
else:
print("Unsolved problem, call `solve` method before")
#classmethod
def step(cls, func , t : np.float , u : np.float, dt ):
def f(ti,ui):
return np.array([function(ti,ui) for function in func])
if AdamsBashforth._2nd.startup == False:
#print ("AB start-up")
AdamsBashforth.u1 = rungekutta.RK2.step(func,t,u,dt)
AdamsBashforth.startup = True
unext = AdamsBashforth.u1 + dt/2.*(3.*f(t+dt,AdamsBashforth.u1) - f(t,u))
AdamsBashforth.u1 = u
return unext
Here's the way that I would really like to do is to call:
problem = AdamsBashforth._2nd(dydt)
but i receive an error that says that adamsbashforth has no member _2nd
so I've try to doing so .. but still the same message :
class AdamsBashforth(AdamsMethods):
def __init__(self, dydt, filename :str = None , salve : bool = True):
self._2nd = self._2nd(dydt,filename,salve)
def solve(self):
pass
class _2nd(AdamsMethods):
What is the right way in order to obtain a call like the first (problem = AdamsBashforth._2nd(dydt))
and using the class _2nd
EDIT
class AdamsBashforth(AdamsMethods):
def __init__(self, dydt, filename :str = None , save : bool = True):
self._2nd = AdamsBashforth._2nd(dydt,filename,save)
def solve(self):
pass
class _2nd(AdamsMethods):
startup = False
solved = False
def __init__(self, dydt : Rhs, filename :str = None , save : bool = True ):
self.file = filename
self.save = save
super().__init__(dydt)
def solve(self):
self.time , self.u = self.dydt.createArray()
self.u[1] = rungekutta.RK2.step(self.dydt.f, self.time[0], self.u[0], self.dt)
for i in range(1,len(self.time)-1):
self.u[i+1] = u[i] + self.dt/2*(3*self.dydt.f(self.time[i],self.u[i])-self.dydt.f(self.time[i-1],self.u[i-1]))
_2nd.solved = True
if self.file != None:
super().write2file()
if self.save:
return self.time,self.u
def plot(self):
if AdamsBashforth._2nd.solved:
super().plot('Sys ODE solution using Adams-Bashforth 2nd order','time [s]','y(t)')
else:
print("Unsolved problem, call `solve` method before")
#classmethod
def step(cls, func , t : np.float , u : np.float, dt ):
def f(ti,ui):
return np.array([function(ti,ui) for function in func])
if AdamsBashforth._2nd.startup == False:
#print ("AB start-up")
AdamsBashforth.u1 = rungekutta.RK2.step(func,t,u,dt)
AdamsBashforth.startup = True
unext = AdamsBashforth.u1 + dt/2.*(3.*f(t+dt,AdamsBashforth.u1) - f(t,u))
AdamsBashforth.u1 = u
return unext
calling in this way :
ab2_p1 = adamsmethods.AdamsBashforth(problem1, 'ab2_1.dat')
ab2t,ab2u = ab2_p1._2nd.solve()
ab2_p1.plot()
looks that work .. but I don't know why ... and I don't know if is it the correct way !!
but I have still problem in order to call the classmethod for example :
u = adamsmethods.AdamsBashforth._2nd.step(func0,t,u,dt)
doesn't work :
Traceback (most recent call last):
File "drive.py", line 287, in <module>
main()
File "drive.py", line 149, in main
u = adamsmethods.AdamsBashforth._2nd.step(func0,t,u,dt)
AttributeError: type object '_2nd' has no attribute 'step'
------------------------------------------------------------
I have created the following objects in python
It creates an object of class arc and then creates another object network using the object arc
class Arc:
# Creates an object of class arc
def __init__(self, tailNode = 0, headNode = 0, lowerBound = 0, upperBound = 0, cost = 0):
self.tailNode = tailNode
self.headNode = headNode
self.lowerBound = lowerBound
self.upperBound = upperBound
self.cost = cost
def displayArc(self):
print("Tail Node : ", self.tailNode, "\nHead Node : ", self.headNode, "\nLower Bound : ", self.lowerBound, "\nUpper Bound ; ", self.upperBound, "\nCost : ", self.cost, "\n")
class Node:
# Create an object of class node
def __init__(self, nodeName = 0, distLabel = 0, preNode = 0):
self.nodeName = nodeName
self.distLabel = distLabel
self.preNode = preNode
class Network:
# Creates a network from given arcs
def __init__(self, fileName):
global arcNo
arcNo = 0
self.fileName = fileName
f = open(self.fileName)
x = f.readlines()
arcList = [ Arc() for i in range(len(x))]
for i in range(len(x)):
temp = x[i]
temp = temp.split("\n")
temp = ",".join(map(str, temp))
temp = temp.split(",")
arcList[i] = Arc(temp[0], temp[1], temp[2], temp[3], temp[4])
arcNo += 1
print(arcNo)
net = Network("arcList.txt")
print(type(net))
print(net[1])
When the print statement comes says
4
<class '__main__.Network'>
Traceback (most recent call last):
File "Dijkstra.py", line 54, in <module>
print(net[1])
TypeError: 'Network' object does not support indexing
How do I support indexing so that I can call the network object by its index ?
Assuming net[index] returns the arcList variable you can simply override your [] operator as such
class Network:
def __getitem__(self,index):
return arcList[index]
Printing a class needs a method as well. This might help you
How to print a class or objects of class using print()?
In order to support indexing, your Network class should have a __getitem__() method (http://docs.python.org/reference/datamodel.html#object.getitem).
I'm writing a class for a simple game of 4 in a row, but I'm running into a problem calling a method in the same class. Here's the whole class for the sake of completeness:
class Grid:
grid = None
# creates a new empty 10 x 10 grid
def reset():
Grid.grid = [[0] * 10 for i in range(10)]
# places an X or O
def place(player,x,y):
Grid.grid[x][y] = player
# returns the element in the grid
def getAt(x,y):
return Grid.grid[x][y]
# checks for wins in a certain direction
def checkLine(player,v,count,x,y):
x = x+v[0]
y = y+v[1]
if x < 0 or x > 9:
return
if y < 0 or y > 9:
return
if Grid.grid[x][y] == p:
count = count+1
if count == 4:
return True
checkLine(player,v,count,x,y)
return False
# returns the number of the player that won
def check():
i = 'i'
for x in range(0,10):
for y in range(0,10):
if Grid.grid[x][y] > 0:
p = Grid.grid[x][y]
f = checkLine(p,0,array(i,[1,0]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[0,1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[1,1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,0]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[0,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[1,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,1]),x,y)
if f:
return p
return 0
reset = staticmethod(reset)
place = staticmethod(place)
getAt = staticmethod(getAt)
check = staticmethod(check)
checkLine = staticmethod(checkLine)
I'm trying to call checkLine() from check(), but I get the error "NameError: global name 'checkLine' is not defined". When I call Grid.checkLine() instead, I get "TypeError: 'module' object is not callable"
How do I call checkLine()?
EDIT:
#beer_monk
class Grid(object):
grid = None
# creates a new empty 10 x 10 grid
def reset(self):
Grid.grid = [[0] * 10 for i in range(10)]
# places an X or O
def place(self,player,x,y):
Grid.grid[x][y] = player
# returns the element in the grid
def getAt(self,x,y):
return Grid.grid[x][y]
# checks for wins in a certain direction
def checkLine(self,player,v,count,x,y):
x = x+v[0]
y = y+v[1]
if x < 0 or x > 9:
return
if y < 0 or y > 9:
return
if Grid.grid[x][y] == p:
count = count+1
if count == 4:
return True
checkLine(self,player,v,count,x,y)
return False
# returns the number of the player that won
def check(self):
i = 'i'
for x in range(0,10):
for y in range(0,10):
if Grid.grid[x][y] > 0:
p = Grid.grid[x][y]
for vx in range(-1,2):
for vy in range(-1,2):
f = self.checkLine(p,0,array(i,[vx,vy]),x,y)
if f:
return p
return 0
reset = staticmethod(reset)
place = staticmethod(place)
getAt = staticmethod(getAt)
check = staticmethod(check)
checkLine = staticmethod(checkLine)
Get rid of the class. Use plain functions and module level variable for grid.
The class is not helping you in any way.
PS. If you really want to call checkline from within the class, you'd call Grid.checkline. For example:
class Foo:
#staticmethod
def test():
print('Hi')
#staticmethod
def test2():
Foo.test()
Foo.test2()
prints
Hi
Syntax:
class_Name.function_Name(self)
Example:
Turn.checkHoriz(self)
A reworked example (hopefully showing a better use of classes!)
import itertools
try:
rng = xrange # Python 2.x
except NameError:
rng = range # Python 3.x
class Turn(object):
def __init__(self, players):
self.players = itertools.cycle(players)
self.next()
def __call__(self):
return self.now
def next(self):
self.now = self.players.next()
class Grid(object):
EMPTY = ' '
WIDTH = 10
HEIGHT = 10
WINLENGTH = 4
def __init__(self, debug=False):
self.debug = debug
self.grid = [Grid.EMPTY*Grid.WIDTH for i in rng(Grid.HEIGHT)]
self.player = Turn(['X','O'])
def set(self, x, y):
if self.grid[y][x]==Grid.EMPTY:
t = self.grid[y]
self.grid[y] = t[:x] + self.player() + t[x+1:]
self.player.next()
else:
raise ValueError('({0},{1}) is already taken'.format(x,y))
def get(self, x, y):
return self.grid[y][x]
def __str__(self):
corner = '+'
hor = '='
ver = '|'
res = [corner + hor*Grid.WIDTH + corner]
for row in self.grid[::-1]:
res.append(ver + row + ver)
res.append(corner + hor*Grid.WIDTH + corner)
return '\n'.join(res)
def _check(self, s):
if self.debug: print("Check '{0}'".format(s))
# Exercise left to you!
# See if a winning string exists in s
# If so, return winning player char; else False
return False
def _checkVert(self):
if self.debug: print("Check verticals")
for x in rng(Grid.WIDTH):
winner = self._check([self.get(x,y) for y in rng(Grid.HEIGHT)])
if winner:
return winner
return False
def _checkHoriz(self):
if self.debug: print("Check horizontals")
for y in rng(Grid.HEIGHT):
winner = self._check([self.get(x,y) for x in rng(Grid.WIDTH)])
if winner:
return winner
return False
def _checkUpdiag(self):
if self.debug: print("Check up-diagonals")
for y in rng(Grid.HEIGHT-Grid.WINLENGTH+1):
winner = self._check([self.get(d,y+d) for d in rng(min(Grid.HEIGHT-y, Grid.WIDTH))])
if winner:
return winner
for x in rng(1, Grid.WIDTH-Grid.WINLENGTH+1):
winner = self._check([self.get(x+d,d) for d in rng(min(Grid.WIDTH-x, Grid.HEIGHT))])
if winner:
return winner
return False
def _checkDowndiag(self):
if self.debug: print("Check down-diagonals")
for y in rng(Grid.WINLENGTH-1, Grid.HEIGHT):
winner = self._check([self.get(d,y-d) for d in rng(min(y+1, Grid.WIDTH))])
if winner:
return winner
for x in rng(1, Grid.WIDTH-Grid.WINLENGTH+1):
winner = self._check([self.get(x+d,d) for d in rng(min(Grid.WIDTH-x, Grid.HEIGHT))])
if winner:
return winner
return False
def isWin(self):
"Return winning player or False"
return self._checkVert() or self._checkHoriz() or self._checkUpdiag() or self._checkDowndiag()
def test():
g = Grid()
for o in rng(Grid.WIDTH-1):
g.set(0,o)
g.set(Grid.WIDTH-1-o,0)
g.set(Grid.WIDTH-1,Grid.HEIGHT-1-o)
g.set(o,Grid.HEIGHT-1)
print(g)
return g
g = test()
print g.isWin()
Unlike java or c++, in python all class methods must accept the class instance as the first variable. In pretty much every single python code ive seen, the object is referred to as self. For example:
def reset(self):
self.grid = [[0] * 10 for i in range(10)]
See http://docs.python.org/tutorial/classes.html
Note that in other languages, the translation is made automatically
There are multiple problems in your class definition. You have not defined array which you are using in your code. Also in the checkLine call you are sending a int, and in its definition you are trying to subscript it. Leaving those aside, I hope you realize that you are using staticmethods for all your class methods here. In that case, whenever you are caling your methods within your class, you still need to call them via your class's class object. So, within your class, when you are calling checkLine, call it is as Grid.checkLine That should resolve your NameError problem.
Also, it looks like there is some problem with your module imports. You might have imported a Module by name Grid and you have having a class called Grid here too. That Python is thinking that you are calling your imported modules Grid method,which is not callable. (I think,there is not a full-picture available here to see why the TypeError is resulting)
The best way to resolve the problem, use Classes as they are best used, namely create objects and call methods on those objects. Also use proper namespaces. And for all these you may start with some good introductory material, like Python tutorial.
Instead of operating on an object, you are actually modifying the class itself. Python lets you do that, but it's not really what classes are for. So you run into a couple problems
-You will never be able to make multiple Grids this way
the Grid can't refer back to itself and e.g. call checkLine
After your grid definition, try instantiating your grid and calling methods on it like this
aGrid = Grid()
...
aGrid.checkLine()
To do that you, you first need to modify all of the method definitions to take "self" as your first variable and in check, call self.checkLine()
def check(self):
...
self.checkLine()
...
Also, your repeated checking cries out for a FOR loop. You don't need to write out the cases.
Java programmer as well here, here is how I got it to call an internal method:
class Foo:
variable = 0
def test(self):
self.variable = 'Hi'
print(self.variable)
def test2(self):
Foo.test(self)
tmp = Foo()
tmp.test2()