Why does my program run without parameters inside the functions' parenthesis? - python

I am going to ask probably a very silly question. I designed a code that looks like the following:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
def menu():
print("[1]: Favorite color")
print("[2]: Number of cats")
#Option1
def FavColor():
sns.countplot(x= "Color", data = main_data)
plt.show()
#Option2
def NumCats():
sns.countplot(x= "Cats", data = main_data)
plt.show()
#Main Code
try:
main_data = pd.read_csv("DATAFIN.csv")
except IOError:
print("Error while trying to open the file")
else:
menu()
option = int(raw_input())
if option == 1:
FavColor()
elif option == 2:
NumCats()
main_data looks like this:
Color Cats
1 Blue 1
2 Yellow 2
3 Blue 2
4 Red 1
5 Blue 3
Now, the "problem" is that my program runs exactly as it should. I just realized, however, that all of my functions, options(), Option1() and Option2(), do not have parameters inside the parenthesis. This is due to me forgetting to do so, but my understanding was that my functions should not work without me giving them the parameters that needed to be used.
For example, if Option1 had to use a precise dataframe I should have written Option1(dataframe).
Everything that my functions need to you is defined in the main code, which you go through before calling the functions, so maybe that's the reason. But is it wrong not to put the parameters inside? Does it make my program less efficient?

You just happen to be referring to a global variable
Here's a simpler example
def foo():
print(x)
x = 2
foo()
x could be defined before or after the function; the function definition captures the closure of the variable reference, not the variable itself
On the other hand, if you defined a main function with local variables, it wouldn't work
def foo():
print(x)
def main():
x = 2
foo()
main()
In general, global variables should be avoided, and therefore parameters should be used, which are just references and the overhead of the memory space allocated for function parameters is negligible

The empty parentheses indicate that it has no parameters.
Defining a new function does not make the function run.

Related

Code is working fine, but, not working completely when the whole code is put inside a def() function

GITHUB REPO: https://github.com/sunnysinghnitb/color_detector
THE DIFFERENCE: The code inside both files is the same. But, the only difference between color_detection1.py (70 lines) and color_detection2.py (75 lines) is that the whole code inside the second file has been put in the def colo() function. Changes in lines 1, 73, 75 of color_detection2.py.
REQUIRED OUTPUT: Just run the color_detection1.py and double-click on the output image. This will show the RGB values of that particular pixel.
QUESTION: The color_detection1.py file is running fine and producing the desired output (RGB values) on double-click, while the color_detection2.py is not producing the desired output. Why is this happening? Why is color_detection2.py not working the same as color_detection1.py?
EDIT: Suppose the following is some python code (color_detection1.py) which is working fine:
.....
...
..
.....
Now, putting this code inside a function (color_detection2.py):
def colo():
.....
...
..
.....
return
colo()
The problem is both codes are working differently. The code 1 is working as expected, while, code 2 is working partially. Why is this happening?
Your problem is one of scope. You set globals here.
def draw_function(event, x,y,flags,param):
if event == cv2.EVENT_LBUTTONDBLCLK:
global b,g,r,xpos,ypos, clicked
clicked = True
xpos = x
ypos = y
b,g,r = img[y,x]
b = int(b)
g = int(g)
r = int(r)
That's all well and good but once you place the function definition inside another function you are changing the scope that you need to access it in from global to nonlocal.
Changing it to this should work.
def draw_function(event, x,y,flags,param):
if event == cv2.EVENT_LBUTTONDBLCLK:
nonlocal b,g,r,xpos,ypos, clicked
clicked = True
xpos = x
ypos = y
b,g,r = img[y,x]
b = int(b)
g = int(g)
r = int(r)
Your first step of debugging should be determining how far your program progresses. A little bit of logging can go a long way.
Placing a logger inside of if (clicked): would have shown you that clicked is never True even though you try to set is as such inside your function.
Placing one outside of your if statement and inside your function would show you that it is defining it in the function but not outside it.
This lets you narrow down the problem a lot more and you have a reproduceable code snippet you can post.

Controlling dynamic properties in Shady according to video frames not time

I am trying to use Shady to present a sequence of image frames. I'm controlling the flow from another machine, so that I first instruct the machine running Shady to present the first frame, and later on to run the rest of the frames.
I create a World instance, and attach to it an animation callback function. Within this callback I listen for communications from the other machine (using UDP).
First I receive a command to load a given sequence (stored as a numpy array), and I do
def loadSequence(self, fname):
yy = np.load(fname)
pages = []
sz = yy.shape[0]
for j in range(yy.shape[1]/yy.shape[0]):
pages.append(yy[:, j*sz:(j+1)*sz])
deltax, deltay = (self.screen_px[0] - sz) / 2, (self.screen_px[1] - sz) / 2
if (self.sequence is None):
self.sequence = self.wind.Stimulus(pages, 'sequence', multipage=True, anchor=Shady.LOCATION.UPPER_LEFT, position=[deltax, deltay], visible=False)
else:
self.sequence.LoadPages(pages, visible=False)
When I receive the command to show the first frame, I then do:
def showFirstFrame(self, pars):
self.sequence.page = 0 if (pars[0] == 0) else (len(self.sequence.pages) - 1)
self.sequence.visible = True
But what do I do now to get the other frames to be be displayed? In the examples I see, s.page is set as a function of time, but I need to show all frames, regardless of time. So I was thinking of doing something along these lines:
def showOtherFrames(self, pars, ackClient):
direction, ack = pars[0], pars[2]
self.sequence.page = range(1, len(self.sequence.pages)) if (direction == 0) else range(len(self.sequence.pages)-2, -1, -1)
But this won't work. Alternatively I thought of defining a function that takes t as argument, but ignores it and uses instead a counter kept in a global variable, but I'd like to understand what is the proper way of doing this.
When you make s.page a dynamic property, the function assigned to it must take one argument (t), but you can still just use any variables in the space when defining that function, and not even use the time argument at all.
So, for example, you could do something as simple as:
w = Shady.World(...)
s = w.Stimulus(...)
s.page = lambda t: w.framesCompleted
which will set the page property to the current frame count. That sounds like it could be useful for your problem.
Your global-variable idea is one perfectly valid way to do this. Or, since it looks like you're defining things as methods of an instance of your own custom class, you could use instance methods as your animation callbacks and/or dynamic property values—then, instead of truly global variables, it makes sense to use attributes of self:
import Shady
class Foo(object):
def __init__(self, stimSources):
self.wind = Shady.World()
self.stim = self.wind.Stimulus(stimSources, multipage=True)
self.stim.page = self.determinePage # dynamic property assignment
def determinePage(self, t):
# Your logic here.
# Ignore `t` if you think that's appropriate.
# Use `self.wind.framesCompleted` if it's helpful.
# And/or use custom attributes of `self` if that's
# helpful (or, similarly, global variables if you must).
# But since this is called once per frame (whenever the
# frame happens to be) it could be as simple as:
return self.stim.page + 1
# ...which is indefinitely sustainable since page lookup
# will wrap around to the number of available pages.
# Let's demo this idea:
foo = Foo(Shady.PackagePath('examples/media/alien1/*.png'))
Shady.AutoFinish(foo.wind)
Equivalent to that simple example, you could have the statement self.stim.page += 1 (and whatever other logic) inside a more-general animation callback.
Another useful tool for frame-by-frame animation is support for python's generator functions, i.e. functions that include a yield statement. Worked examples are included in python -m Shady demo precision and python -m Shady demo dithering.
It can also be done in a StateMachine which is always my preferred answer to such things:
import Shady
class Foo(object):
def __init__(self, stimSources):
self.wind = Shady.World()
self.stim = self.wind.Stimulus(stimSources, multipage=True)
foo = Foo(Shady.PackagePath('examples/media/alien1/*.png'))
sm = Shady.StateMachine()
#sm.AddState
class PresentTenFrames(sm.State):
def ongoing(self): # called on every frame while the state is active
foo.stim.page += 1
if foo.stim.page > 9:
self.ChangeState()
#sm.AddState
class SelfDestruct(sm.State):
onset = foo.wind.Close
foo.wind.SetAnimationCallback(sm)
Shady.AutoFinish(foo.wind)

Python (Alternate two messages)

I have some code, and my goal is to make it so that when left button is clicked it will post text saying "Programming is fun!" and when it is pressed again, it will change that text to "It is fun to program", my idea was to make x = 0 if I wanted the first statement, and x = 1 if I wanted the second statement, but it keeps saying x is not defined, I've tried returning x but it simply won't... I've tried a variety of different methods but I can't figure it out. Thoughts? I'd like an alternative method to this, because I'm not sure that mine will work.
def text():
pf = Label(window2,text="Programming is fun")
pf.pack()
x = 0
def text2():
fp = Label(window2,text="It is fun to program")
fp.pack()
x = 1
def bt(event):
if x == 0:
text()
elif x == 1:
text2()
window2 = Tk()
window2.geometry("500x500")
The problem is that, in the scope of your functions, the variable x is indeed undefined.
An example:
height = 5
def some_function():
# code here can not access height just like that
When you want to access variables in functions, you generally have three options:
1) Put your code in a class instead. This requires some understanding of object oriented programming, and if you're a beginner this might not be the best choice for you
2) Pass the variable as an argument to the function and add it to the function's parameter list, for example like this:
def my_function(height):
# here height can be used
And when calling the function:
height_of_bob = 2
my_function(height_of_bob)
3) Use a global variable. This is usually not necessary, and is considered bad practice in general, but it will solve your problem just fine.
I found a way to do this below, the down low is that it's creating the text through that function, and then it's rebinding the key to do other function and then that function deletes previous text, creates the new text and then rebinds to the previous function, and the cycle continues. Here's the code.
def text(event):
global pf
fp.pack_forget()
pf = Label(window2,text="Programming is fun")
pf.pack()
window2.bind("<Button-1>", text2)
def text2(event):
global fp
pf.pack_forget()
fp = Label(window2,text="It is fun to program")
fp.pack()
window2.bind("<Button-1>", text)
window2 = Tk()
window2.geometry("500x500")
pf = Label(window2,text="Programming is fun")
fp = Label(window2,text="It is fun to program")
window2.bind("<Button-1>", text)

Saving output of a function as a variable and using it in another function

I'm new to programming, so this question might be dumb.
I need to introduce the value of Tr1 into the Bzero1 function. When I run the module I get the result below:
.
The program is not running the Bzero1 function and I'm not sure why. Is it because I am not introducing the Tr1 value correctly or something else? I want Bzero1 to perform the operation 0.083-(0.422/Tr1**1.6), with Tr1 obtained from the result of T/Tc1.
I would appreciate your help a lot.
T = float(input("Introduce system temperature in Kelvin: "))
print("System temperature is: ", T)
Tc1 = float(input("Introduce critical temperature of component 1: "))
print("Critical temperature of component 1 is: ", Tc1)
def Tr1(T, Tc1):
print("Relative temperature 1: ", T/Tc1)
Tr1 = Tr1(T, Tc1)
def Bzero1(Tr1):
print("Bzero 1: ", 0.083-(0.422/Tr1**1.6))
Do not replace Tr1 function value, to avoid such replacement change:
Tr1_value = Tr1(T, Tc1)
Call Bzero1 function with code:
Bzero1(Tr1_value)
Modify Tr1 to return value:
def Tr1(T, Tc1):
result = T/Tc1
print("Relative temperature 1: ", result)
return result
Also, let me suggest you to take a look on python official tutorial - there you can learn a lot about python ...
Good Luck !
def is only defining a function, not calling it. E.g.
def foo(a):
print a * 2
means there is now a function foo that takes argument a. The a in foo(a) is the name of the variable inside the function.
So in your case
def Bzero1(Tr1):
print("Bzero 1: ", 0.083-(0.422/Tr1**1.6))
defines the function Bzero1 as taking argument Tr1, but doesn't call it. You need to call the function, just like you called Tr1:
Bzero1(Tr1)
You can see that this way it becomes confusing quite quickly on which is a variable outside of your function, and which are variables inside functions. Therefore it is better to use different names for variables in your outer program v.s. those inside functions.
Here are a few more best practices that you might find useful:
It is generally better to first define all functions and then execute the program's main code, as opposed to intermixing function definitions and the main program.
Another best practice is to make functions only calculate output from inputs, and handle output somewhere else. This way you get to reuse your functions in other parts of your program while always keeping control of when and what to output to the user.
Finally, you shouldn't generally reassign names, e.g. Tr1 = Tr1(...) means that Tr1 is now no longer the name of the function but the name of the result returned by Tr1. In short, use different names for different things.
Applying these tips, your code might look as follows:
# function definitions first
def Tr1(vt, vtc1):
return vt/vtc1
def Bzero1(vtr1):
return 0.083-(0.422 / vtr1 ** 1.6)
# get user input
T = float(input("Introduce system temperature in Kelvin: "))
print("System temperature is: ", T)
vTc1 = float(input("Introduce critical temperature of component 1: "))
print("Critical temperature of component 1 is: ", vTc1)
# run calculations
vTr1 = Tr1(T, vTc1)
vBz1 = Bzero1(vTr1)
# print output
print("Relative temperature 1: ", vTr1)
print("Bzero 1: ", vBz1)
Note
Since I don't know the semantic meaning of your variables I have just used small letter v as a prefix - in general it is better to use meaningful names like temperature or temp1 and temp2 etc. Programs are not math papers.

Python Turtle: I want to make a function that executes another function depending on what the previously executed function was

I'm drawing my name using turtles and I have a bunch of different functions for each of the letters
like so (for letter r)
def letter_r(t):
def letter_r_top(t):
turtle.lt(90)
turtle.fd(150)
turtle.rt(90)
turtle.circle(-37.5,180)
turtle.lt(130)
def letter_r_leg(t):
csquare = ((75**2) + (37.5**2))
sidec = math.sqrt(csquare)
turtle.fd(sidec)
letter_r_top(rob)
letter_r_leg(rob)
After each letter, i need to move the turtle into the right place to setup for the next letter. Because each of the letters are different sizes I need to make custom movements depending on what the previous letter is but I dont want to make separate functions for each of those movements.
At the end of my code I have the list of functions to be called in the correct order to spell my name
letter_t(rob)
letter_setup(rob)
letter_r(rob)
letter_setup(rob)
.....
Is there a way that I can do something like this so that I will only need 1 setup function.(Not real code, just a conceptualization of what I'm thinking
def letter_setup(t):
if previously executed function A
turtle.fd(75)
if previously executed function B
turtle.fd(75)
turtle.lt(90)
if previously executed function C
turtle.fd(75)
turtle.lt(90)
Why not the movement to the right place for the next letter at the end of the previous letter?
Perhaps there is a better way to do this but you could make a variable last_function_called and in each function you give it a different value then you'll know wich one was the last called :
last_function_called = NONE;
def function1():
last_function_called = FUNCTION1
blablabla
...
if (last_function_called == FUNCTION1):
call another one
and before of course something like :
NONE = 0
FUNCTION1 = 1
FUNCTION2 = 2
ect...

Categories