How do I package two functions into a module? - python

I have two functions for newtons method to estimate roots of a number that the user inputs, but I am tasked with "packaging these functions into a module". I admit I am struggling to wrap my head around the concept of modules and can't really find any material that helps me.
Have tried saving the functions separately as two different files and using the import command but can't seem to find any success.
[Edit] Trying to get the previous_x to not display once the final estimation established.
[Edit2] Still "None" appears for previous_x
def newtons_fourth(y):
x=1
N=0
previous_x = None
while N < 50:
x=1/4*(3*(x) + y/(x**3))
N=N+1
print('Iteration number:',N)
print('Estimation:',x)
print('Previous x:',previous_x)
print()
if previous_x is not None:
if abs(x - previous_x) < 0.0001:
final=1
print('Difference negligible')
print('Final Estimation:',x)
break
previous_x = x
if final!=1:
return previous_x

Your idea of "saving the functions separately as two different files and using the import command" is correct. Here's one way to just that:
CubedModule.py:
def newtons_cubed(y):
x=1
N=0
previous_x = None
while N < 50:
x=1/3*(2*(x) + y/(x**2))
N=N+1
print('Iteration number:',N)
print('Estimation:',x)
print('Previous x:',previous_x)
print()
if previous_x is not None:
if abs(x - previous_x) < 0.0001:
print('Difference negligible')
print('Final Estimation:',x)
return
previous_x = x
print(previous_x)
FourthModule.py:
def newtons_fourth(y):
x=1
N=0
previous_x = None
final = None
while N < 50:
x=1/4*(3*(x) + y/(x**3))
N=N+1
print('Iteration number:',N)
print('Estimation:',x)
print('Previous x:',previous_x)
print()
if previous_x is not None:
if abs(x - previous_x) < 0.0001:
final=1
print('Difference negligible')
print('Final Estimation:',x)
return
previous_x = x
if final!=1:
print(previous_x)
Then in your main module, named script.py you would import each module into separate namespaces at the top and reference them individually:
import CubedModule as cm
import FourthModule as fm
y= int(input('Enter value for estimations:'))
print()
print('Cubed root estimation:')
print()
cm.newtons_cubed(y)
print()
print('Fourth root estimation:')
print()
fm.newtons_fourth(y)

So yes this gets confusing when you start, I am with you on that. So let me make it super easy.
Functions def in python are containers with code in it. They run once and complete.
Classes are instances that hold a bunch of functions (called methods) inside that can manipulate the data inside the class until the class is closed, or the program is done with the named instance.
x = Classname() #creates an instance of the class now named x
x.start() # runs the function start inside the class. Can pass variables, or use existing variables under the self. notation.
Modules are files with either functions or classes in them. ALL modules are imported.
import os
from os import getcwd #function or class inside the modeul
Then they can be called like this:
print(os.getcwd())
print(getcwd())
Any .py file can be imported. A directory can be imported if it has a file named __init__.py inside of it. The file can be empty. Then the directory name becomes the module name, and the single files are submodules imported like this:
import myfolder.mymodule
from myfolder import mymodule # the same as above
That's about as easy as I can make it. Any more questions, you need to look at the documentation. But your best bet is to experiment, doing it the wrong way until you do it the right way is the best teacher.

Related

Issue With Math Function Called From Another File

I'm currently working on a unit conversion calculator, and wanted to make it smoother by calling the math functions from a different file. Currently, Celsius -> Fahrenheit (CF) is put in 'func.py', like this:
# This file has all the math functions that get called by main.py when needed.
# Also, VARIABLES!
num = 0
typ = 0
def CF():
tota = (num * 9/5) + 32
print("Answer: " + str(tota) + " degrees Fahrenheit")
And the code to call it in main.py looks like this:
if (typ == str('C-F')):
num = int(input("Enter the temperature in Celcius: "))
num = num
CF()
I figure that I imported something wrong, but I've edited the import function several times now. I'm not looking for some type of complete correction, I wish for somebody to tell me what I did wrong, so that I can fix it. I used repl.it, if it helps. Even if someone can tell me that it's possible, it'll help.
I couldn't find anything on websites like GeeksforGeeks, which is my main source on research.
This is very odd:
def CF():
You're relying on num being defined at module scope within its module.
Much better to spell it this way, so you're passing in an argument:
def cf(num):
Over in main.py you're doing this, which isn't helpful:
num = num
Much better to pass it in:
cf(num)
The big concept you've been missing is you have two different modules,
and each one has a num variable.
They are different.
Changing one won't automatically affect the other.
Use function parameters instead.
You need to work with function parameters and returns (see this for a tutorial).
# func.py
def CF(num):
return (num * 9/5) + 32
# main.py
if (typ == str('C-F')):
num = int(input("Enter the temperature in Celcius: "))
tota = CF(num)
print("Answer: " + str(tota) + " degrees Fahrenheit")

How to import external python file to another python file?

I would like to import one python file into another and then compile the main file. How can I do this?
MWE: Suppose I would like to calculate factorial of a positive integer. It can be done successfully by the following way:
n=5
fact = 1
if n < 0:
print("Sorry, factorial does not exist for negative numbers")
elif n == 0:
print("The factorial of 0 is 1")
else:
for i in range(1,n + 1):
fact = fact*i
print "%d!=%d"%(n,fact)
But I would like to create a secondary file say "auxfile.py" containing:
fact = 1
if n < 0:
print("Sorry, factorial does not exist for negative numbers")
elif n == 0:
print("The factorial of 0 is 1")
else:
for i in range(1,n + 1):
fact = fact*i
print "%d!=%d"%(n,fact)
And another main file say "main.py" containing:
print "Required factorial is given below:"
for n in range(30):
import auxfile.py
How can I do this?
Note: I know defining a function the whole process can be done in a single file. But I have to do a large program where I would like to apply this process.
Simple, just use the import method. To make your life easier simply copy the .py file you would like to import to the same folder that the file you want to import the other code file into is in.
E.g if you wanted to import happy.py to sad.py simply do:
import happy
This would give the following traceback (look at example below):
Hello
Although, this will instantly run everything outside of any def loops in the .py file. Therefore, if you wanted to run a single def loop in the file, then use the following code:
Example contents of happy.py:
print("Hello")
def okay():
print("okay")
If you did:
happy.okay()
This would give you the following traceback:
Hello
okay
TIP FOR YOUR CODE IN MAIN.PY:
You did:
print "Required factorial is given below:"
whereas you forgot the brackets. You should use: print("Required factorial is given below:") This will avoid future errors!
Hope this helps!
you can do it like this:
auxfile.py
def factorial(n):
fact = 1
if n < 0:
print("Sorry, factorial does not exist for negative numbers")
elif n == 0:
print("The factorial of 0 is 1")
else:
for i in range(1,n + 1):
fact = fact*i
print "%d!=%d"%(n,fact)
in your main.py :
from auxfile import factorial
print "Required factorial is given below:"
for n in range(30):
factorial(n)
If you're trying to avoid using a function--maybe you could wrap your entire code in the for loop? If it is not as simple as a for-loop, maybe you could copy your main code into the other file above it.
For example:
Before:
file1: "Your main code that wants to call the code below"
file2: "Your code that is too cumbersome to convert to a function"
After:
file1:
"Your main code that wants to call the code below"
for n in range(30):
"Your code that is too cumbersome to convert to a function"
There's still quite an ugly solution, which is to use the exec built-in function.
First of all, you read the code from your file:
with open("auxiliary.py", 'r') as f:
content = f.readlines()
Then you filter out the lines you don't want, so that content is a string containing your Python code, that is:
# The following evaluates to True
content == 'fact = 1\nif n < 0:\n print("Sorry, factorial does not exist for negative numbers")\nelif n == 0:\n print("The factorial of 0 is 1")\nelse:\n for i in range(1,n + 1):\n fact = fact*i\n print "%d!=%d"%(n,fact)'
Then you can just call the exec function, which will act as if the lines were included in lieu of the call of the function:
exec content # Or exec(content), both seems to work in Python 2.7
See here for a further explanation.
Note that you will have access to fact and every other variables, just as if you had written these lines in your main file.
Be aware that this might get dangerous: if you don't formally identify which lines to execute (like, put a comment as an identifier, or if the auxiliary file never changes), you may end up running some code from your auxiliary file you dont want to.

Unexpected Python behaviour - function fails to terminate after return statement

I wrote a function to traverseMountain(altitude, stepsleft, substring) as helper function to part of a solution to one of the hackerrank problems. I consider it better practice to test functions as I write them, and this is where I am encountering my problem.
#!/bin/python3
import math
import os
import random
import re
import sys
# Complete the countingValleys function below.
def countingValleys(n, s):
altitude = 0
mountiansCount = 0
valleysCount = 0
def tailRecurseSolution(stepsleft, substring):
head, tail = substring[0], substring[1:]
if (head == 'U'):
mountiansCount+=1
traverseMountain(n-1, tail)
if (head == 'D'):
traverseValley(altitude+1, n-1, tail)
# return valleysCount
def traverseMountain(altitude, stepsleft, substring):
head, tail = substring[0], substring[1:]
if (head=="D"):
altitude-=1
if (head=="U"):
altitude+=1
stepsleft-=1
if (altitude<=0 or stepsleft<=0 or (not tail)):
x = stepsleft
return x
elif (altitude>0 and stepsleft>0 and tail):
traverseMountain(altitude, stepsleft,tail)
#def traverseValley(alt, stepsleft, substring):
# return x
if __name__ == '__main__':
altitude = 0
stepsleft = 99
path = "UUUDUDDD"
print(traverseMountain(altitude, stepsleft, path))
You can ignore the countingValleys function as its imcomplete and not being called.
What I was expecting to happen was for the function traverseMountian to meet the if conditional, and would step into the block upon the last recursive call (when altitude variable is 0 or the tail is the empty string) and then exit the function and return the value of the stepsLeft variable.
What I am witnessing is that my debugger steps inside of that if statement, but immediately jumps to inside the elif statement (I do not understand why it would do that) and the variables I receive are reset?
I wanted to make a post here in case it's intended behaviour of the code
I've spent a lot of time today just trying to figure out why Python does not terminate the function after the return statement. I've played out with the conditionals, the placing of the return statement etc. but without success.
You're returning x but in your recursion call you're not doing anything with the return value.
You might want return traverseMountain(altitude, stepsleft,tail) as your last line in traverseMountain?

module does not see my values inside the main code

I'm very new to Python and currently am building a GUI interface in Tkinter and have a fully working code for it. I thought it would be nice to have a button work from keyboard by pressing "Enter" key.
The code line for that is:win.bind('<Return>', testButton.functionName)
Then you just put "event" in function bracket aka functionName(event) And everything works great.
The issue is that now it does not work when you press the button inside the GUI interface what means I need to duplicate and reName one of the functions to have both.
Since it is an identical code, it would make more sense to have it as a module. However, when I import my module it does not seem to see the rest of my code and claims that my variables do not exist.
Here is a simplified example of how I'm doing it.
My module saved as moduleTest:
def test():
sum = a + b
return sum
Main program:
import moduleTest
a = 10
b = 12
moduleTest.test()
print test()
It keeps claiming that a and b are not defined.
I'm clearly misunderstanding how modules work cause in my mind when I import a module it should simply import the whole code and do the same thing as this:
import moduleTest
a = 10
b = 12
def test():
sum = a + b
return sum
print test()
What am I misunderstanding and doing wrong?
Python globals are global to each module, not to the whole program.
The usual way to deal with this is to not use globals.
For your toy example, you can def test(a, b): and then call test(a, b) from your main module, and that's typically the right solution, but it isn't always appropriate.
Other options are:
Use a class, and pass the values in when you create the instance.
Store the globals that need to be shared in a third module, which both main and moduleTest can import thirdmodule and access as thirdmodule.a. This is often appropriate for cases like shared configuration values.
Store the globals as attributes of some other thing both pieces of code already have access to.
As #abarnert points out, globals are global to each module. In order to solve this problem you can use:
def test(a, b):
sum = a + b
return sum
And
import moduleTest
a = 10
b = 12
print(moduleTest.test(a, b))
I would like to point out you should not call your variables sum because this already is an existing function which you're overwriting.
Here are several separate fragments of my code to give you an idea:
item = "SNAKE"
oldString = "-" * (len(item))
blank = "-" * (len(item))
guesses = 10
def gameOn():
global guesses
global oldString
newString = ""
i = 0
x = len(item)
hanged = ""
readString = answerIn.get().upper()
winner = 1
if not readString:
if guesses == 10:
pass
else:
hanged = (HANGMAN[(len(HANGMAN) -1) - guesses])
hangedOutput.config(state=NORMAL)
hangedOutput.delete("1.0",END)
hangedOutput.insert(END,hanged)
hangedOutput.config(state=DISABLED)
error.config(state=NORMAL)
error.delete(0,END)
error.insert(0,"Please enter the value.")
error.config(state=DISABLED)
win = Tk()
answerIn = Entry(win,width = 3, border = 2)
answerIn.focus_set()
answerIn.grid(row=2, column=0, pady = 10, padx = 200, sticky = W)
win.mainloop()
When I turn it into a module it keeps asking not just for item and oldString definitions but also for answerIn, hangedOutput and etc which are part of Tkinter labels.

python class doesn't work for different variable

dear expert i am trying to write a simulation and in my code i have a class like this:
... (some def are here)
class multipole:
global xxp,yyp,zzp,x,y,z,xp,yp,zp,t,tm,h
xxp,yyp,zzp,x,y,z,xp,yp,zp =xxpyypzzp() # some initial values calling
#staticmethod
def quad(f1, f2,f3):
global t,h,mass,ksimax
while t < ksimax:
rk4_two(t,h,mass, f1, f2, f3, xxp, yyp, zzp) # rk function for new xxp, yyp and zzp
t = t + h
tm.append(t)
xp.append(xxp[1])
x.append(xxp[0])
yp.append(yyp[1])
y.append(yyp[0])
zp.append(zzp[1])
z.append(zzp[0])
return xp, x, yp,y,zp,z,tm
if __name__ == "__main__":
qp=multipole()
quxp, qux, quyp,quy,quzp,quz,qutm=qp.quad(0.,0.,0.)
hxp, hx, hyp,hy,hzp,hz,htm =qp.quad(0.022,0.,0.)
oxp, ox, oyp,oy,ozp,oz,otm =qp.quad(-0.023,-0.032,0.0 )
my question is this code only calculate (quxp, qux, quyp,quy,quzp,quz,qutm), but not others (others will turn same value of quxp, qux, quyp,quy,quzp,quz,qutm) could you please tell me why? i am new in python any comments will be appreciated.
Ignoring the fact that this code is... somewhat flawed. I think that the problem is that you are using t which is apparently global but you don't reset it anywhere - so this loop:
while t < ksimax:
...
Will only run once, unless you reset t somewhere. Some pseudo code to explain why this happens:
counter = 0
def do_something():
global counter
print "Starting at", counter
while counter <= 10:
print counter
counter += 5
print "Done"
do_something()
# Starting at 0
# 0
# 5
# 10
# Done
do_something() # Called again, the counter is at 10 now:
# Starting at 10
# Done
As others have mentioned, your code could benefit from some heavy refactoring. Some starting points:
Naming! What does xxpyypzzp even mean? Even if it's obvious to you today, it must be hard to read even for you and unless you have Rainman-like memory you will not understand this next week. Try using descriptive names and if you find yourself adding prefixes or suffixes to variables because you run out of names - think about encapsulating some of this complexity in a class. It seems like the suffixes xp, x, yp, y, zp, z and tm are used a lot. At least create a named tuple to hold these values.
Global variables is generally considered harmful. They make it hard to reason about code - which is why you got this bug in the first place. If you are sprinkling global statements over your code there is time to redesign it. Think about which part of your code should "own" which parts of the state.
Python has a coding standard, called PEP8 - read it and try to follow it.

Categories

Resources