Python module not accessible to function inside class - python-3.x

Code below works as expected. It prints 5 random numbers.
import numpy as np
class test_class():
def __init__(self):
self.rand_nums = self.create_rand_num()
def create_rand_num(self):
numbers = np.random.rand(5)
return numbers
myclass = test_class()
myclass.rand_nums
However, the following does not work. NameError: name 'np' is not defined
import numpy as np
from test.calc import create_rand_num
class test_class():
def __init__(self):
self.rand_nums = create_rand_num()
myclass = test_class()
myclass.rand_nums
# contents of calc.py in test folder:
def create_rand_num():
print(np.random.rand(5))
But, this works:
from test.calc import create_rand_num
class test_class():
def __init__(self):
self.rand_nums = create_rand_num()
myclass = test_class()
myclass.rand_nums
# contents of calc.py in test folder:
import numpy as np
def create_rand_num():
print(np.random.rand(5))
Why must I have 'import numpy as np' inside calc.py? I already have this import before my class definition. I am sure I am misunderstanding something here, but I was trying to follow the general rule to have all the import statements at the top of the main code.
What I find confusing is that when I say "from test.calc import create_rand_num," how does Python know whether "import numpy as np" is included at the top of calc.py or not? It must know somehow, because when I include it, the code works, but when I leave it out, the code does not work.
EDIT: After reading the response from #DeepSpace, I want to ask the following:
Suppose I have the following file.py module with contents listed as shown:
import numpy as np
import pandas as pd
import x as y
def myfunc():
pass
So, if I have another file, file1.py, and in it, I say from file.py import myfunc, do I get access to np, pd, and y? This is exactly what seems to be happening in my third example above.
In my third example, notice that np is NOT defined anywhere in the main file, it is only defined in calc.py file, and I am not importing * from calc.py, I am only importing create_rand_num. Why do I not get the same NameError error?

Python is not like C. Importing a module does not copy-paste its source. It simply adds a reference to it to the locals() "namespace". import numpy as np in one file does not make it magically available in all other files.
You have to import numpy as np in every file you want to use np.
Perhaps a worthwhile reading: https://docs.python.org/3.7/reference/simple_stmts.html#the-import-statement

Related

Having issues with sys.argv()

I'm new to python programming and trying to implement a code using argv(). Please find the below code for your reference. I want to apply filter where Offer_ID = 'O456' with the help of argv().
Code:
-----
import pandas as pd
import numpy as np
import string
import sys
data = pd.DataFrame({'Offer_ID':["O123","O456","O789"],
'Offer_Name':["Prem New Ste","Prem Exit STE","Online Acquisiton Offer"],
'Rule_List':["R1,R2,R4","R6,R2,R3","R10,R11,R12"]})
data.loc[data[sys.argv[1]] == sys.argv[2]] # The problem is here
print(data)
With this statement I'm getting the output -> "print(data.loc[data['Offer_ID'] =='O456'])"
but I want to accomplish it as shown here "data.loc[data[sys.argv[1]] == sys.argv[2]]" .
Below is the command line argument which I'm using.
python argv_demo2.py Offer_ID O456
Kindly assist me with this.
I'm a little confused as to what the issue is, but is this what you're trying to do?
import pandas as pd
import numpy as np
import string
import sys
data = pd.DataFrame({'Offer_ID':["O123","O456","O789"],
'Offer_Name':["Prem New Ste","Prem Exit STE","Online Acquisiton Offer"],
'Rule_List':["R1,R2,R4","R6,R2,R3","R10,R11,R12"]})
select = data.loc[data[sys.argv[1]] == sys.argv[2]] # The problem is here
print(select)

f() missing 1 required positional argument: 't'

I just tried to execute this code. but it shows always this error:'f() missing 1 required positional argument:'t'
please can you tell me what should I change?
import numpy as np
def f(y,z,t):
return np.array([2*y+z-t,z+y])
import matplotlib.pyplot as plt
from scipy.integrate import odeint
t=np.linspace(0,2,1000)
sol=odeint(f,[0,1],t)
y,z=sol[:,0],sol[:,1]
plt.plot(t,y,label='y')
plt.plot(t,z,label='z')
plt.show()
Depending on what you are trying to do, you can get around it two ways. To pass in additional arguments other than y and t you need to include them as a constant in the function parameter.
import numpy as np
def f(t,y,z):
return np.array([2*y+z-t,z+y])
import matplotlib.pyplot as plt
from scipy.integrate import odeint
t=np.linspace(0,2,1000)
z = 10.0
sol=odeint(f,[0,1],t, tfirst=True, args=(z, ))
y,z=sol[:,0],sol[:,1]
plt.plot(t,y,label='y')
plt.plot(t,z,label='z')
plt.show()
This will still cause an error. However, if you are also trying to obtain z as result then you should be able to run:
import numpy as np
def f(t,inp):
y, z = inp
return np.array([2*y+z-t,z+y])
import matplotlib.pyplot as plt
from scipy.integrate import odeint
t=np.linspace(0,2,1000)
sol=odeint(f,[0,1],t, tfirst=True)
y,z=sol[:,0],sol[:,1]
plt.plot(t,y,label='y')
plt.plot(t,z,label='z')
plt.show()
This should run without any errors but you may need to double check that this is the result you are expecting.
(The tfirst argument is just for clarity to make ensure the order of arguments provided is correct, you can remove and re-order if you want as well.)
Documentation for odeint function here: https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html

Where to do package imports when importing multiple python scripts?

This might have been answered before, but I could not find anything that addresses my issue.
So, I have 2 files.
|
|-- test.py
|-- test1.py
test1.py is as below
def fnc():
return np.ndarray([1,2,3,4])
I'm trying to call test1 from test and calling the function like
from test1 import *
x = fnc()
Now naturally I'm getting NameError: name 'np' is not defined.
I tried to write the import both in test and test1 as
import numpy as np
But still, I'm getting the error. This might be silly, but what exactly I'm missing?
Any help is appreciated. Thanks in advance.
Each Python module has it's own namespace, so if some functions in test1.py depends on numpy, you have to import numpy in test1.py:
# test1.py
import numpy as np
def fnc():
return np.ndarray([1,2,3,4])
If test.py doesn't directly use numpy, you don't have to import it again, ie:
# test.py
# NB: do NOT use 'from xxx import *' in production code, be explicit
# about what you import
from test1 import fnc
if __name__ == "__main__":
result = fnc()
print(result)
Now if test.py also wants to use numpy, it has to import it too - as I say, each module has it's own namespace:
# test.py
# NB: do NOT use 'from xxx import *' in production code, be explicit
# about what you import
import numpy as np
from test1 import fnc
def other():
return np.ndarray([3, 44, 5])
if __name__ == "__main__":
result1 = fnc()
print(result1)
result2 = other()
print(result2)
Note that if you were testing your code in a python shell, just modifying the source and re-importing it in the python shell will not work (modules are only loaded once per process, subsequent imports fetch the already loaded module from the sys.modules cache), so you have to exit the shell and open a new one.
mostly you need to have __init__.py in the directort where you have these files
just try creating init.py file like below in the directory where you .py files are present and see if it helps.
touch __init__.py

python bokeh error with output_file in class

I have a probleme using bokeh in a class.
The following code is runing when i use the object "Graph" in the same file (.py), but not when i'm calling the class from an other file, and i don't know why.
class Graph():
import pandas as pd
from bokeh.models import HoverTool
from bokeh.plotting import figure, show, output_file, ColumnDataSource
def __init__(self, df, indicators=None):
self.df = df
self.output_file("test.html" , title='test')
....
I have the following error:
TypeError: output_file() got multiple values for argument 'title'
Does anybody know how can I fix it?
For information, the following code:
class Graph():
import pandas as pd
from bokeh.models import HoverTool
from bokeh.plotting import figure, show, output_file, ColumnDataSource
def __init__(self, df, indicators=None):
self.df = df
self.output_file("test.html")
....
returns:
Traceback (most recent call last):
File "Documents/Programmation/python/Trade/Indicators.py", line 50, in <module>
a = TradeGraph(df)
File "/Users/Alex/Documents/Programmation/python/Graph.py", line 29, in __init__
self.output_file("test.html")
File "/anaconda3/lib/python3.6/site-packages/bokeh/io/output.py", line 77, in output_file
root_dir=root_dir
File "/anaconda3/lib/python3.6/site-packages/bokeh/io/state.py", line 166, in output_file
if os.path.isfile(filename):
File "/anaconda3/lib/python3.6/genericpath.py", line 30, in isfile
st = os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not Graph
and the following code:
class Graph():
import pandas as pd
from bokeh.models import HoverTool
from bokeh.plotting import figure, show, output_file, ColumnDataSource
def __init__(self, df, indicators=None):
self.df = df
self.output_file()
....
returns the same (last) error.
Thanks
You have evidently defined a method output_file on your own class, and that is where the problem is. (As an aside, please always try to ask questions with complete minimal code). Based on the output above, the most likely explanation is that you have forgotten to add the self parameter that Python methods should always have. That is, you have something like:
class Graph(object):
def output_file(title):
when you need something like:
class Graph(object):
def output_file(self, title):
However, I would question the value of having an output_file method at all. Unless you are doing something out of the ordinary, you should just call Bokeh's output_file function directly. However, please also note that output_file activates a persistent implicit mode. That is useful especially in interactive environments, but may not be in a program that saves lots of things. There is also a save function that just gives you explicit control wherever you want to perform a save.
Thank you for you answer,
I finnaly import each need module in each methode.
I thought i could all import them one time beteween the class definition and the class initialisation, but doesn't work,
Thanks

Python Unittest for big arrays

I am trying to put together a unittest to test whether my function that reads in big data files, produces the correct result in shape of an numpy array. However, these files and arrays are huge and can not be typed in. I believe I need to save input and output files and test using them. This is how my testModule looks like:
import numpy as np
from myFunctions import fun1
import unittest
class TestMyFunctions(unittest.TestCase):
def setUp(self):
self.inputFile1 = "input1.txt"
self.inputFile2 = "input2.txt"
self.outputFile = "output.txt"
def test_fun1(self):
m1 = np.genfromtxt(self.inputFile1)
m2 = np.genfromtxt(self.inputFile2)
R = np.genfromtxt(self.outputFile)
self.assertEqual(fun1(m1,m2),R)
if __name__ =='__main__':
unittest.main(exit=False)
I'm not sure if there is a better/neater way of testing huge results.
Edit:
Also getting an attribute error now:
AttributeError: TestMyFunctions object has no attribute '_testMethodName'
Update - AttributeError Solved - 'def init()' is not allowed. Changed with def setUp()!

Resources