Just for reference my code
def makeList (start,end,h):
a=[]
a.append(start)
n=(end-start)/h
while(n!=0):
new=a[-1] +h
a.append(a[-1] +h)
n=n-1
return a
def generateBase(xList,f):
if(len(xList)==0):
return []
elif(xList[0]==0 or len(xList)==1):
return ([(xList[0],0,0)] + generateBase(xList[1:],f))
else:
return ([(xList[0],0,(f(xList[0])))] + generateBase(xList[1:],f))
def getThird(a):
return a[2]
def fdm(alpha,startx,endx,startt,endt,dx,dt,f):
baseSolution=generateBase((makeList(startx,endx,dx)),f)
totalSoltuion= baseSolution + startCalc(alpha,(makeList(startx,endx,dx)),(makeList(startt,endt,dt))[1:],baseSolution,dx,dt,[],[])
def startCalc(alpha,xList,tList,phiSolutions,dx,dt,newPhi,newX):
print newPhi
if(len(tList)==0):
return []
elif (len(xList)==1):
return ([(xList[0],tList[0],0)] + startCalc(alpha,(newX + [xList[0]]),tList[1:],(newPhi + [(xList[0],tList[0],0) ]),dx,dt,[],[]))
elif (xList[0]==0):
return ([(xList[0],tList[0],0)] + startCalc(alpha,(xList[1:]),tList,phiSolutions,dx,dt,(newPhi + [(xList[0],tList[0],0)]),(newX + [xList[0]])))
else:
print getThird(phiSolutions[0])
print getThird(phiSolutions[1])
print getThird(phiSolutions[2])
sol=newPhi(xList[0],tList[0],getThird(phiSolutions[0]),getThird(phiSolutions[1]),getThird(phiSolutions[2]),alpha)
return ([sol] + startCalc(alpha,(xList[1:]),tList,phiSolutions[1:],dx,dt,(newPhi + [sol]),(newX + [xList[0]])))
def newPhi(x,t,phiL,phiC,phiR,dx,dt,alpha):
return (x,t,(phiC + (alpha*(dt/(dx**2)))*(phiR-(2*phiC)+phiL)) )
def showMe(SolutionList):
GraphSolution(SolutionList)
showMe(fdm(1,0,1,0,1,.1,.01,(lambda x:x+1)))
The issue is here
sol=newPhi(xList[0],tList[0],getThird(phiSolutions[0]),getThird(phiSolutions[1]),getThird(phiSolutions[2]),alpha)
I get this issue
TypeError: 'list' object is not callable
The things in these arrays are real numbers, i thought this issue only happens when i try to call a list like a function if i did like phiSolution(0) im not sure thought whats the issue, i print everything out and its a number, if someone could give me some insight that would be great.
Look at your recursive call:
return ([(xList[0],tList[0],0)] + startCalc(alpha,(newX + [xList[0]]),tList[1:],(newPhi + [(xList[0],tList[0],0) ]),dx,dt,[],[]))
In particular, look carefully at your argument list. It breaks down to these arguments:
startCalc(alpha, # arg 1
(newX + [xList[0]]), #arg 2
tList[1:], #arg 3
(newPhi + [(xList[0],tList[0],0) ]), # arg 4
dx, # arg 5
dt, # arg 6
[], # arg 7
[]) # arg 8
According to your definition of startCalc...
startCalc(alpha,xList,tList,phiSolutions,dx,dt,newPhi,newX)
... newPhi is argument #7 by position. Therefore, when you make your tail-recursive call, an empty list is being assigned to newPhi. So newPhi is a list, and sol=newPhi(<anything>) is indeed attempting to call it. If you're trying to index into the list, use brackets:
sol = newPhi[index]
Also, as mentioned in another answer, you're using the identifier newPhi both as a function name and an input argument name to startCalc. You need to change one of these to resolve the conflict.
Because newPhi is a list, and therefore is not callable.
Note that you have defined newPhi twice: Once as a function (at about line 48 in the code, between the definitions of startCalc and showMe), and once as the 7th parameter to the startCalc function at about line 29. The definition in force when the TypeError is raised is the one where it's a startCalc parameter.
startCalc is called by the second line of the fdm function at about line 27:
totalSoltuion= baseSolution + startCalc(alpha,(makeList(startx,endx,dx)),(makeList(startt,endt,dt))[1:],baseSolution,dx,dt,[],[])
And if you'll count 7 parameters in, you'll see that you're passing an empty list ([]).
If you want newPhi to be a function there, move the definition above the definition of startCalc, and rename the current newPhi parameter which is interfering with your newPhi function. You cannot have it be both a list (see lines 34 and 36) and a function (line 42).
Related
I'm relatively new in programming with Python. This code was working perfectly, until I tried turning it into a class.
I'm making a class for my sudoku solver code, to practice classes and dabbling my toes in object oriented programming.
So I have read a whole bunch of questions from users who have a similar problem, most answers were :
-instantiate class first before calling a function from said class
but none of them seem to work for my specific example.
Here is my class:
#assume sudoku is imported as a np.array, white spaces replaced by zeros
class Sudoku():
solution_number = 1
def __init__ (self, sud_arr):
self.sudo = sud_arr
#print(self.sudo)
def possible (self, y, x, num):
for i in range(9):
if self.sudo[y][i] == num:
return False
if self.sudo[i][x] == num:
return False
yy = (y//3)*3
xx = (x//3)*3
for i in range(3):
for j in range(3):
if self.sudo[yy+i][xx+j] == num:
return False
return True
def solve(self):
for i in range(9):
for j in range(9):
if self.sudo[i][j] == 0:
for nr in range(1,10):
if Sudoku.possible(i,j,nr): #line 34
self.sudo[i][j] = nr
Sudoku.solve()
self.sudo[i][j] = 0
return
if Sudoku.solution_number > 1: #if there is more than one solution, include solution number
print("Solution Number {}".format(Sudoku.solution_number))
else: print("Solution Number 1")
print(self.sudo)
Sudoku.add_sol_num()
#classmethod
def add_sol_num(cls):
cls.solution_number += 1
After running:
s = Sudoku(su) #where su is a numpy array sudoku
s.solve() #line 52
I get the error:
File "/Users/georgesvanheerden/Python/Projects/Sudoku/SudokuSolver.py", line 52, in <module>
s.solve()
File "/Users/georgesvanheerden/Python/Projects/Sudoku/SudokuSolver.py", line 34, in solve
if Sudoku.possible(i,j,nr):
TypeError: possible() missing 1 required positional argument: 'num'
[Finished in 1.9s with exit code 1]
Sorry if this is too much code, I didn't know which parts to cut out.
use self.possible when using a method, Sudoku.possible gets you a reference to that method that cant find the instance that you are calling it from.
That also applies to if Sudoku.solution_number > 1, generally the pythonic way is to use the self variable, or the first argument to the method (although you can also pass self to the function: Solution.possible(self, i, j , nr) )
So your code would look like:
def solve(self):
for i in range(9):
for j in range(9):
if self.sudo[i][j] == 0:
for nr in range(1,10):
if self.possible(i,j,nr): #line 34
self.sudo[i][j] = nr
self.solve()
self.sudo[i][j] = 0
return
if self.solution_number > 1: #if there is more than one solution, include solution number
print("Solution Number {}".format(self.solution_number))
else: print("Solution Number 1")
print(self.sudo)
Sudoku.add_sol_num() # add_sol_num is a #classmethod
you can add self as the first argument:
if Sudoku.possible(self, i, j, nr): #line 34
Let us first understand the error that is being given :
TypeError: possible() missing 1 required positional argument: 'num'
This says that there is no value for num argument while calling possible() method.
But you are passing 3 arguments here :
if Sudoku.possible(i,j,nr)
So what went wrong here ???
If you see the definition of your method:
def possible (self, y, x, num):
This says that you will be passing 4 arguments and one of which would be the instance/object of the class (self argument).
1. If we invoke this method using a class object, `self` argument is passed by default. So in this case we can just send 3 arguments apart from `self`.
2. If you want to invoke this method like you have done above, you will have to provide a value for `self` argument explicitally.
So, here is how you can do it (pythonic way and good approach) :
While invoking the method possible, use self keyword.
if self.possible(i,j,nr):
In lines 34 and 36 you call two methods as if they are static methods since you call the methods on the class not on some instance. That also is the reason, why self is not recognized and hence asked for another parameter in the method call.
You want to call the methods of the current instance of Sudoku. Therefore
if self.possible(i,j,nr):
in line 34 and
self.solve()
in line 36 should do the trick.
Here is my code I've tried:
import csv
f = open("nfl.csv", "r")
nfl = list(csv.reader(f))
patriots_wins = 0
for each in nfl:
if each[2] == "New England Patriots":
patriots_wins = patriots_wins + 1
return patriots_wins
print(patriots_wins)
It gives the below error:
SyntaxError: 'return' outside function
return is used to return a value from a function and you have not defined a function.
For instance, you might have created the following function:
def f(x):
"""Adds 5 to any integer x"""
y = x + 5
return y
and put this function in some larger context, such as:
def main():
for i in range(10):
print(f(i))
Here, when main is called, we will call the function f() 10 times and everytime we do so f() will return the answer to "What is i + 5?".
You get a return from a function.
check out this link
The return statement
return may only occur syntactically nested in a function definition, not within a nested class definition.
If an expression list is present, it is evaluated, else None is substituted.
return leaves the current function call with the expression list (or None) as return value.
When return passes control out of a try statement with a finally clause, that finally clause is executed before really leaving the function.
I need to use a function as range but an error appears saying that n was not set:
NameError: name 'n' is not defined
I'm actually learning how to use python and I do not know if the syntax is correct, I just find examples of lists as ranges.
Could someone clear my ideas, give me some suggestions?
[EDIT1] My function z depends on j and f(n).
[EDIT2] I´m usind fibonacci ranges for integrate over a sphere.
The program is something like this:
def f(n):
a, b = 0, 1
for i in range(n):
a, b = b, a+b
return a
def y(n):
return f(n) + some_const
def z(j):
for j in range(0,f(n-1)):
return j*y(n) + j*f(n-1) + j*f(n)
You have
def z(j):
for j in range(0,f(n-1)):
return j*y(n) + j*f(n-1) + j*f(n)
Notice you say this takes something called j while your other functions take n.
Did you mean
def z(n):
for j in range(0,f(n-1)):
return j*y(n) + j*f(n-1) + j*f(n)
When you get an error check the line number it refers to.
Also, consider giving your variables longers names - just single letters get easy to muddle up!
As pointed out by the comment, once this stops giving the error message it might not do what you want.
You first function loops and then returns:
def f(n):
a = something
for i in range(n):
a = a + i
return a
(I presume something is set to, er, something)
Your z function returns as soon as it gets into the loop: perhaps you just want to collect the results and return them?
def z(n):
stuff = []
for j in range(0,f(n-1)):
stuff.append( j*y(n) + j*f(n-1) + j*f(n) )
return stuff
Notice the return is further left - no longer indented inside the for loop.
In fact you could use a list comprehension then:
def z(n):
return [j*y(n) + j*f(n-1) + j*f(n) for j in range(0,f(n-1))]
There are several problems with the snippet that you posted.
It would help if you include the code that calls the functions. It also seems that you should look into local-scope of vars in Python- it does not matter what you call the parameter passed into the function, so you could call the var in the brackets "n" for every function, but it is preferable to give them a meaningful name that indicates what that parameter represents- just useful for others looking at the code, and good practice!
Lastly, using a docstring inside the function makes it very clear what the functions do, and may include a desc. of the params passed (type/class).
def range_sum(n): # instead of f- range_sum seems appropriate
"""
Sums the range of numbers from 0 to n
>>> range_sum(4) # example data
10
"""
# no idea what a is meant to be, unless an accumulator to
# store the total, in which case it must be initialised
accum = 0
for i in range(1, n+1): #iterates from 1 to n
accum = aaccum + i
return a # returns the total
def y(m, const): # use a descriptive func name
"""
Sums the range of numbers from 0 to m and adds const
>>> y(4, 7) # example data
17
"""
return range_sum(m) + const
def z(j, n, m): # pass all the vars you need for the function so they have a value
"""
Something descriptive
>>> z(4, 2, 5) # example data
?
"""
total
for j in range(0,f(n-1)):
total += j*y(m) + j*f(n-1) + j*f(n)
return total
print("First Func, ", range_sum(4))
print("Second Func, ", y(4, 7))
print("Third Func, ", z(4, 2, 5))
Note that the number of arguments passed to each function matches the number expected by the function. It is possible to set defaults, but get the hang of getting this right first.
Not sure what the last function is meant to do, but as mentioned in the comment above, showing some code to illustrate how you call the code can be useful, as in the sample.
I'd like to know how I would go about doing something like this (in python 2):
def myFunction(fn, params):
return ("You called " + fn.__name__ + "(" + str(params) ")" +
" and got " + str(fn(params)))
Say I have a couple functions:
def doSomething(s):
# manipulation
return s
def doAnotherThing(someInt, someOtherInt, someString):
# do something with them
return someValue
I'd like to be able to call myFunction(doSomething, "hello"), and get You called doSomething("hello") and got "something". This approach seems to work for functions that take a single input, but I can't get it to work for functions that take multiple inputs, e.g. calling myFunction(doAnotherThing, (myInt, myOtherInt, myString)). I think I need to do something involving * and ** so that I can take the keywords arbitrarily instead of as a tuple, but I'm not quite sure how to go about doing that.
You're close, all you need to do is add a * in front of the tuple (or ** in front of a dict for keyword arguments) when calling the interior function. This is called argument unpacking.
def wrapper(fn, params, keyword_params):
return fn(*params, **keyword_params)
def myfunc(a, b, c=0):
return (a + b)/c
wrapper(myfunc, (2, 5), {'c': 3})
You can also use arbitrary argument lists to potentially simplify the wrapper function. This will allow you to automatically package additional arguments to feed to interior functions without having to pre-package them in tuples and dictionaries.
def wrapper(fn, *params, **keyword_params): # Note the asterisks
return fn(*params, **keyword_params)
def myfunc(a, b, c=1):
return (a + b)/c
wrapper(myfunc, 2, 5, c=3) # Nicer function call
Note that just using the first method will actually break single-argument implementations, as the * operator expects an iterator to unpack. So you have to either always pre-package the arguments or add some type-checking in the wrapper function.
def wrapper(fn, params):
return fn(*params)
def myfunc(a):
return 2*a
wrapper(myfunc, 2)
# TypeError: myfunc() argument after * must be a sequence, not int
wrapper(myfunc, (2,)) # Package the argument in a single-element tuple
# 4
The second method doesn't have this problem.
Here is one way:
def myFunction(fn, *params):
return ("You called " + fn.__name__ + str(params) +
" and got " + str(fn(*params)))
import math
print myFunction(math.sqrt, 4)
print myFunction(open, '/etc/passwd', 'r')
print myFunction(lambda x: x+1, 41)
Result:
You called sqrt(4,) and got 2.0
You called open('/etc/passwd', 'r') and got <open file '/etc/passwd', mode 'r' at 0x7f20e9cb65d0>
You called <lambda>(41,) and got 42
There is a tutorial at http://pythonprogramming.jottit.com/functional_programming and it gives an example how to use higher order functions to return functions:
def trace(f):
f.indent = 0
def g(x):
print '| ' * f.indent + '|--', f.__name__, x
f.indent += 1
value = f(x)
print '| ' * f.indent + '|--', 'return', repr(value)
f.indent -= 1
return value
return g
and
def memoize(f):
cache = {}
def g(x):
if x not in cache:
cache[x] = f(x)
return cache[x]
return g
but I don't get how it's able to assign two functions on the same variable on the statements:
fib = trace(fib)
fib = memoize(fib)
print fib(4)
both trace and memoize seem to have effect on the last call. Why is that?
What you've written is very similar to
fib2 = memoize(trace(fib))
print fib2(4)
because you have changed which function the variable fib points to after the call to trace, so memoize is applied to the tracing version (and then fib is "overwritten" again).
If you want to have a tracing version and a memoized version separately, you need to assign their results to different variables, e.g.:
fib_trace = trace(fib)
fib_memo = memoize(fib)
print fib_trace(4), fib_memo(4)
Both trace() and memoize() create a new function object and return it to you.
In each case, the new function object "wraps" the old function object, so the original function is not lost.
Using my amazing ASCII art skills, here is a diagram:
f(x) # this is your original function
trace(f(x)) # trace "wraps" it and returns a wrapped object
memoize(trace(f(x))) # memoize "wraps" it and returns a new wrapped function object
We start out with a function object bound to the name fib.
Then we call trace(fib) which creates a new function object. When it is first created, its name is g but we then bind it to the name fib. Try printing fib.__name__.
Then we call memoize(fib) which creates a new function object. Again it's first created with the name of g but then bound to the name fib.
Remember, in Python everything is an object, and objects can exist with no name, with one name, or with many names. In this case, we keep re-using the name fib but we keep re-binding it with different function objects.
It's no different than:
a = a + 2
a = a + 5
print a
Just as a will have increased by 7, fib will have had both decorators applied to it.