countr += 0 shows none pi2go - python

I have no idea anymore. I've been struggling for hours now.
I got a pi2golite here with wheel sensors.
the wheelCount() isn't working anyway (or at least I dont know how)
so I've been trying to find another solution.
The 2 motors I've got seem to run on different speed's. I wanted to see that in numbers to change the speed of each motor so they run the same.
import pi2go, time
pi2go.init()
running = True
countL = 0
countR = 0
def counter1():
global countR
countR += 0
speed = 60
try:
pi2go.stepForward(50,10)
time.sleep(2)
print counter1()
print countL
finally:
pi2go.cleanup()
->
When I try to run it, the motor's run fine and turn off after the 10 steps (so it has to be counting)
it outputs this:
for countL -> 0
for counter1() ->None
Why none?

This is expected bahaviour.
If you run code in a Python shell, then when you write an expression, the shell will print the result of the expression.
For a function call, this is what the function returns. In Python every function returns something. In case you do not specify a return statement, then None is returned. Some shells do not print None, but anyway, the result is None of sucht call.
So the function updates countR, then performs return None (implicitly). This is the result of the function call, and so the shell prints this. If you run code without the shell, then nothing is printed (as in no content at all).
You can let the function return the updated value. Furthermore you probably want to increment the value, so += 1:
def counter1():
global countR
countR += 1
return countR

Related

Running a function inside of a loop only once

This kind of follows up on a question I asked prior, but I have a function, we'll call it get_temp(), that needs to be looped in order to gather the data it needs to call for another function, we'll call it notification(), to run if the if statement is satisfied. This all works great, but once it does satisfy the if statement, I need it to only send auxFunction once.
This section of the code works by getting temperature from a thermocouple, and then I'm using an if statement to call for a specific function when the temp == a specific value. The temperature data is looked at every 2 seconds in the loop, which is necessary to see the changes in the data to satisfy the if statement eventually, so I can't just run it outside of the loop.
This is the part of the code that grabs the thermocouple value:
def grab_temp(self):
temp = self.board.temp_sensor
print("Temperature is " + str(round(temp)) + " degrees")
temp=int(temp)
if temp == 200:
self.notification()
This is the concept of the code, but not the exact code. It's written a little differently, but performs as it's written above and the notification function does more than just print. just for the sake of example, I'm just having it print something
And then:
def notification(self):
print("Testing")
Again, this all works, but since the grab_temp function is inside of the loop of the rest of the code, it loops every two seconds, which in turn, prints every two seconds when the value is 200, where I need it to just perform the notification function once, when temp == 200. This is problematic because the code that will be in the notification function will be notifying me of the temperature, so I can't have it notifying me every two seconds while the temperature is 200 degrees.
What would be the best way to go about achieving this, in this instance? I've tried a few other things recommended on similar questions, but none of them worked. All that I tried returned some kind of error, which prevented the rest of the code from functioning properly.
I didn't write the entirety of this of this whole project, I'm just modifying it to do some things I want it to do, and I don't have a ton of experience in coding, but I'm learning more and more as I work through this project, and have enjoyed making these modifications, and am still learning some basics on the side.
Possible solution without explicitly using global.
Add a boolean parameter to grab_temp, we'll call it notify. Set an initial value for notify=True. At the end of grab_temp, return the appropriate boolean to turn on/off the notification. Assign grab_temp to notify within your loop.
This version will disable notifications for consecutive calls, but re-enable notifications when the condition is no longer met. You can modify what's returned from grab_temp if you only want a notification for the very first time the condition is met.
temp_values = [1,200,200,1,200,200,200,1,200]
def notification():
print('notification')
def grab_temp(i, notify=True):
temp = temp_values[i]
print("Temp is", temp)
check_temp = temp == 200
if notify and check_temp:
notification()
return not check_temp
notify = True
for i in range(len(temp_values)):
notify = grab_temp(i, notify)
Example result
Temp is 1
Temp is 200
notification
Temp is 200
Temp is 1
Temp is 200
notification
Temp is 200
Temp is 200
Temp is 1
Temp is 200
notification
Modified grab_temp to only notify for the very first time the condition is met.
def grab_temp(i, notify=True):
temp = temp_values[i]
print("Temp is", temp)
check_temp = temp == 200
if notify and check_temp:
notification()
return False
else:
return notify
Temp is 1
Temp is 200
notification
Temp is 200
Temp is 1
Temp is 200
Temp is 200
Temp is 200
Temp is 1
Temp is 200
I sadly do not have the ability to comment currently due to my lack of reputation on this website. However, I think a solution you could consider is adding a global boolean variable called 'uncalled' that defaults to true and adjust it once you've called the self.notification() portion of your code.
Beginning of Script:
uncalled = True
Printing Warning
global uncalled
if temp == 200 and uncalled:
self.notification()
uncalled = False
Using the keyword 'global' here should change it throughout your entire code and not just within the function. If this doesn't answer your question, would you mind clarifying for me in my comments? Thanks!
Extra Example:
uncalled = True
def function(x):
global uncalled
if x and uncalled:
print('hit')
uncalled = False
for i in range(5):
x = True
function(x)
Returns
hit

How to Print Something Every Other Time Something Happens

I'm trying to learn python and while learning I've come across a bit of a problem.
import time
import pyautogui
def SendScript():
time.sleep(2)
with open('script.txt') as f:
lines = f.readlines()
for line in lines:
time.sleep(2)
pyautogui.typewrite(line.strip())
pyautogui.press('enter')
SendScript()
I'm trying to print something to the screen every second time the 'enter' key has been pressed, but I'm an extreme beginner so I really don't know how to do that. Could someone help me accomplish this task?
You could create a new boolean variable to track if the enter key has been pressed before. That way, every time the for loop iterates, the value of pressed switches and only when the value of pressed is True will it print something.
import time
import pyautogui
def SendScript():
pressed = False
time.sleep(2)
with open('script.txt') as f:
lines = f.readlines()
for line in lines:
time.sleep(2)
if pressed:
print("Something")
pressed = not pressed
pyautogui.typewrite(line.strip())
pyautogui.press('enter')
SendScript()
From a more step-back approach, you could do:
events=['event1', 'event2', 'event3', 'event4', 'event5', 'event6', 'event7', 'event8']
counter = 0
for event in events:
counter += 1
if counter % 2 == 0: # ie do stuff when divisible by 2, ie when its even
print('print what you want to be printed every second time')
else:
pass
Of course you are not looping through events like I do in this example. The point is counting the events and only doing stuff when this count is even.
As indicated in another answer already, a simple toggle can be implemented with a bool and then code which toggles it every time something happens:
thing = False
:
if happens(something):
thing = not thing
This is fine for toggling between two states. A more general approach which allows for more states is to use a numeric variable and a modulo operator:
times = 0
maxtimes = 12
:
if happens(something):
times += 1
if times % maxtimes == 1:
print("ding dong")
The modulo could be compared to 0 instead if you want to print on the 12th, 24th etc iterations instead of the first, the 13th, etc, or of course any other offset within the period if that's what you want.
Another useful trick is to flip-flop between zero and some other value.
value = 0
othervalue = 1234
:
if happens(something):
value = othervalue - value
Of course, you can flip-flop between any two values actually; subtract the current value from their sum to get the other one.
Needless to say, just toggling or flip-flopping isn't very useful on its own; you'd probably add some (directly or indirectly) user-visible actions inside the if happens(something): block too.
You could use a generator for this:
def everySecondTime():
while True:
yield "hi"
yield "not hi"
mygen = everySecondTime()
print(next(mygen))
print(next(mygen))
print(next(mygen))
print(next(mygen))
This prints
hi
not hi
hi
not hi
I'm sure it's clear to you how you could adapt this to do some other actions instead.
Whether this approach is better than just using a boolean is highly debatable, but I thought I'd leave it here so you could learn about generators (the yield keyword) if you want to.

Decorator - changing variable name

I am learning the concepts of decorators in Python. While I think I have covered lots of blogs and have got some basic understanding how decorators work and why would we need one.
While doing so, I encountered a tutorial (totally lost the reference to this), where while explaining about decorators, the author wrote the following:
def call_counter(func):
def helper(x):
helper.calls += 1
return func(x)
helper.calls = 0
return helper
def succ(x):
return x + 1
succ = call_counter(succ)
print(succ.calls)
for i in range(10):
succ(i)
print(succ.calls)
Output:
0
10
As I mentioned earlier, I thought I understand how a decorator works and basic Python but suddenly am doubting myself here.
In helper function, the author is incrementing helper.calls variable by 1 (which should be, as per my previous understanding, just an ordinary variable and helper. is only to show this variable is inside helper function), but has only defined helper.calls after using it here , towards the end.
Similarly, towards end, after calling the decorator function, the author has suddenly used succ.calls variable - which is even printing expected result - but without any definition anywhere.
P.S. I have tried doing my research but could not even put this behaviour in proper words to find anything appropriate.
P.P.S. Could not come up with a more precise header as totally unfamiliar with the actual phenomenon happening.
succ = call_counter(succ) # succ.calls = 0 when function is called (succ = helper)
print(succ.calls) # prints 0
for i in range(10):
succ(i) # As succ = helper now, this becomes helper(i) and helper.i is incremented by 1 each iteration, succ(x) is then returned after as func = succ and x + 1 is returned from succ(x)
print(succ.calls) # prints 10 as helper.calls is incremented 10 times within the loop
The same output would have been achieved if succ(x) had returned no value as it was not used anywhere else, you can see your code visualized on http://www.pythontutor.com/visualize.html#mode=edit

Curious about effect of recursion of a method

I have written an instance method which uses recursion to find a certain solution. It works perfectly fine except the time when I'm exiting the if-elif block. I call the function itself inside IF block. Also, I have only one return statement. The output from the method is weird for me to understand. Here is the code and the output:
def create_schedule(self):
"""
Creates the day scedule for the crew based on the crew_dict passed.
"""
sched_output = ScheduleOutput()
assigned_assignements = []
for i in self.crew_list:
assigned_assignements.extend(i.list_of_patients)
rest_of_items = []
for item in self.job.list_of_patients:
if item not in assigned_assignements:
rest_of_items.append(item)
print("Rest of the items are:", len(rest_of_items))
if len(rest_of_items) != 0:
assignment = sorted(rest_of_items, key=lambda x: x.window_open)[0]
# print("\nNext assignment to be taken ", assignment)
output = self.next_task_eligibility(assignment, self.crew_list)
if len(output) != 0:
output_sorted = sorted(output, key=itemgetter(2))
crew_to_assign = output_sorted[0][1]
assignment.eta = output_sorted[0][4]
assignment.etd = int(assignment.eta) + int(assignment.care_duration)
crew = next((x for x in self.crew_list if x.crew_number == crew_to_assign), None)
self.crew_list.remove(crew)
crew.list_of_patients.append(assignment)
crew.time_spent = assignment.etd
self.crew_list.append(crew)
self.create_schedule()
else:
print("*" * 80, "\n", "*" * 80, "\nWe were not able to assign a task so stopped.\n", "*" * 80, "\n", "*" * 80)
sched_output.crew_output = self.crew_list
sched_output.patients_left = len(rest_of_items)
elif not rest_of_items:
print("Fully solved.")
sched_output.crew_output = self.crew_list
sched_output.patients_left = 0
print("After completely solving coming here.")
return sched_output
This was the output:
Rest of the items are: 10
Rest of the items are: 9
Rest of the items are: 8
Rest of the items are: 7
Rest of the items are: 6
Rest of the items are: 5
Rest of the items are: 4
Rest of the items are: 3
Rest of the items are: 2
Rest of the items are: 1
Rest of the items are: 0
Fully solved.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
After completely solving coming here.
What I don't understand is that as soon as my list rest_of_items is empty, I assign data to sched_output and return it. However, print statement is being executed for the same number of time as recursion was done. How can I avoid this?
My output is perfectly fine. All I want to do is understand the cause of this behaviour and how to avoid it.
The reason it's printing out 11 times is that you always call print at the end of the function, and you're calling the function 11 times. (It's really the same reason you get Rest of the items are: … 11 times, which should be a lot more obvious.)
Often, the best solution is to redesign things so instead of doing "side effects" like print inside the function, you just return a value, and the caller can then do whatever side effects it wants with the result. In that case, it doesn't matter that you're calling print 11 times; the print will only happen once, in the caller.
If that isn't possible, you can change this so that you only print something when you're at the top of the stack. But in many recursive functions, there's no obvious way to figure that out without passing down more information:
def create_schedule(self, depth=0):
# etc.
self.create_schedule(depth+1)
# etc.
if not depth:
print('After completely solving come here.')
returns sched_output
The last resort is to just wrap the recursive function, like this:
def _create_schedule(self):
# etc.
self._create_schedule()
# etc.
# don't call print
return sched_output
def create_schedule(self):
result = self._create_schedule()
print('After completely solving come here.')
return result
That's usually only necessary when you need to do some one-time setup for the recursive process, but here you want to do some one-time post-processing instead, which is basically the same problem, so it can be solved the same way.
(Of course this is really just the first solution in disguise, but it's hidden inside the implementation of create_schedule, so you don't need to change the interface that the callers see.)
As you call your create_schedule function within itself before the function finishes, once it has gotten to the end and doesn't need to call itself again, each function ends, and hits the "After completely solving coming here.", at the end of the function.
This means that each function, after calling itself, is still running - just stuck at the line where it calls itself - until they have all completed, which is when the paused functions can finish their task, printing out your statement.
You have print("After completely solving coming here.") at the end of your recursive function. That line will be executed once for each recursion.
Consider this simple example, which recreates your issue:
def foo(x):
print("x = {x}".format(x=x))
if x > 1:
foo(x-1)
print("Done.")
Now call the function:
>>> foo(5)
x = 5
x = 4
x = 3
x = 2
x = 1
Done.
Done.
Done.
Done.
Done.
As you can see, on the final call to foo(x=0), it will print "Done.". At that point, the function will return to the previous call, which will also print "Done." and so on.

while loop in python issue

I started learning python few weeks ago (no prior programming knowledge) and got stuck with following issue I do not understand. Here is the code:
def run():
count = 1
while count<11:
return count
count=count+1
print run()
What confuses me is why does printing this function result in: 1?
Shouldn't it print: 10?
I do not want to make a list of values from 1 to 10 (just to make myself clear), so I do not want to append the values. I just want to increase the value of my count until it reaches 10.
What am I doing wrong?
Thank you.
The first thing that you do in the while loop is return the current value of count, which happens to be 1. The loop never actually runs past the first iteration. Python is indentation sensitive (and all languages that I know of are order-sensitive).
Move your return after the while loop.
def run():
count = 1
while count<11:
count=count+1
return count
Change to:
def run():
count = 1
while count<11:
count=count+1
return count
print run()
so you're returning the value after your loop.
Return ends the function early, prohibiting it from going on to the adding part.

Categories

Resources