I'm rather new to Python and programming in general, so I apologise in advance if my terminology is incorrect.
hue_alert_delay = 0
def delays(name, delay):
global hue_alert_delay
if name == 'hue_alert_delay':
for i in range(0, delay):
hue_alert_delay += 1
time.sleep(1)
hue_alert_delay = 0
delays('hue_alert_delay', 60)
What I'm trying to achieve:
I would like the function to convert the 'name' parameter, which is a string input, into a pre-exiting variable, which will negate the need for multiple IF statements.
The above example includes only one IF statement, but for my project there will be a lot more and I would rather keep the function clean and simple.
This won't work, but it's what I'm trying to aim for:
hue_alert_delay = 0
def delays(name, delay):
global name
for i in range(0, delay):
name += 1
time.sleep(1)
hue_alert_delay = 0
delays('hue_alert_delay', 60)
Any assistance would be appreciated.
Use a dict:
values = {
'hue_alert_delay': 0
}
def delays(name, delay):
values[name] += 1
Whenever you feel like using "variable variables", what you most likely really want is a dict storing key-value associations. Yes, there are other ways to do literally what you want, but that soon leads to insane code.
Use a dictionary like so.
vars = {'hue_alert_delay':0}
def delays(name, delay):
for i in range(0, delay):
vars[name] += 1
time.sleep(1)
vars[name] = 0
You can also use globals()[name] but I won't recommend it.
Use a dictionary:
vars = {'hue_alert_delay':0}
def delays(name, delay):
for i in range(delay):
vars[name] += 1
time.sleep(1)
vars[name] = 0
delays('hue_alert_delay', 60)
Related
i'm stuck with this problem, i can't read the variables bpm and spo2 from the function run_sensor (i need these two variables in another script). If someone can help me, thanks.
class HeartRateMonitor(object):
LOOP_TIME = 0.10
def __init__(self, print_raw=False, print_result=False):
self.bpm = 0
if print_raw is True:
print('IR, Red')
self.print_raw = print_raw
self.print_result = print_result
def run_sensor(self):
sensor = MAX30102()
ir_data = []
red_data = []
bpms = []
# run until told to stop
while not self._thread.stopped:
# check if any data is available
num_bytes = sensor.get_data_present()
if num_bytes > 0:
# grab all the data and stash it into arrays
if len(ir_data) == 100:
bpm, valid_bpm, spo2, valid_spo2 = hrcalc.calc_hr_and_spo2(ir_data, red_data) # <-------------- here
if valid_bpm:
bpms.append(bpm)
while len(bpms) > 4:
bpms.pop(0)
self.bpm = np.mean(bpms)
if (np.mean(ir_data) < 50000 and np.mean(red_data) < 50000):
self.bpm = 0
if self.print_result:
print("Finger not detected")
if self.print_result:
print("BPM: {0}, SpO2: {1}".format(round(self.bpm), round(spo2)))
You need to use Global keyword for this issue. Write this -
global bpm
global spo2
under the function you need to use the variables in
You can't access class variables from another function. However, if you were to create an instance of the HeartRateMonitor class, then you can import it and get its bpm and spo2.
instance = HeartRateMonitor()
Then, in your other script:
from heartratemonitor.py import instance
instance.run_sensor() # I assume this is what you want to do
print(instance.bpm)
print(instance.spo2)
I try to stop a .after function i tkinter in python 3.6, but have probems with namspace of variables. I get NameError: "name 'counter' is not defined" when I use this code:
I read this excellent post, from where I got the idea of using two buttons instead of one.
Use start and stop function with same button in Tkinter
def count(ac,rs):
if ac:
global counter
counter += 1
label.config(text=counter)
label.after(1000, count)
if rs:
counter = 0
counter += 1
count()
def start():
ac = True
rs=False
count(ac,rs)
def stop():
ac = False
label.configure(text='0')
rs = True
count(ac,rs)
Since I declare the variable counter in the count() function, I don't understand the NameError.
I'm trying to have a static int inside a class in python. But it doesn't work.
Here's an example of what I've implemented :
class MyDict(dict):
STR_DEPTH = -1
def __init__(self, **kwargs):
super(MyDict, self).__init__(**kwargs)
self.__dict__.update(name = kwargs.get("name", ""))
def __str__(self):
self.STR_DEPTH += 1
res = self.name + '\n'
for k in self.keys():
res += '\t'*self.STR_DEPTH + k + " = " + str(self[k])
res += '\n'
self.STR_DEPTH -= 1
return res
def main():
d1 = MyDict(one=MyDict())
d1["two"] = 2
d1["one"]["one"] = 1
d1["one"]["two"] = MyDict(three=3)
d1["four"] = 4
print d1
if __name__ == "__main__":
main()
and i'm expecting :
four = 4
two = 2
one =
two =
three = 3
one = 1
but it doesn't work that way. If i'm not mistaking, int aren't references and it's not the same "STR_DEPTH" in every instances of my class.
I already know the list-of-length-1 trick and the empty-type trick, but do i really need to resort do clumsy unreadable trick ?
Isn't there a better way since i'm inside a class ?
Where you have:
self.STR_DEPTH += 1
replace that with:
MyDict.STR_DEPTH += 1
and the same where you decrement the value.
Assigning to self.STR_DEPTH will create a new instance variable which hides access to the class variable through self. You can use self.STR_DEPTH to access the class variable provided you don't have an instance variable of the same name, but if you want to rebind the class variable you have to refer to it directly.
Note that self.STR_DEPTH += 1 is really just shorthand for self.STR_DEPTH = self.STR_DEPTH + 1 so even if the right hand self.STR_DEPTH picks up the class variable the assignment still happens back to the instance variable.
I know how to undo a drawing step in python turtle with turtle.undo(). But how can I make a Redo function ?
from tkinter import *
...#Just some other things
def undoStep():
turtle.undo()
def redoStep():
#What to put here
root.mainloop()
To make a redo function, you need to keep track of the each action, in a list actions for example. You will also need a variable i that tells you where you are in that list and each time you call undoStep, decrease i by one. Then redoStep has to perform the action actions[i]. Here is the code:
import turtle
actions = []
i = 0
def doStep(function, *args):
global i
actions.append((function, *args))
i += 1
function(*args)
def undoStep():
global i
if i > 0:
i -= 1
turtle.undo()
def redoStep():
global i
if i >= 0 and i < len(actions):
function, *args = actions[i]
function(*args)
i += 1
I'm using ftplib to create a simple script to push out a file to multiple IP addresses, all set up as FTP servers. I wanted to display progress in the file upload process, but I'm having an issue. I use the callback argument of FTP.storbinary() and it works with something like this:
count = 0
def update(block):
count2 = str(count + 1)
print count2
However, if I try to do any arithmetic outside of a str() call, the program hangs. So the following doesn't work:
count = 0
def update(block):
count += 1
print count
Even wrapping count in a str() call doesn't work. It just hangs on the first call.
If you just try calling update yourself, instead of passing it to FTP.storbinary, you'll see the problem immediately:
>>> update('')
UnboundLocalError: local variable 'count' referenced before assignment
If you want to update a global variable, you have to mark it global explicitly:
def update(block):
global count
count += 1
print count
See the FAQ entry Why am I getting an UnboundLocalError when the variable has a value? and the following question What are the rules for local and global variables in Python?, and the docs on global, for more details.
A better way to solve this would be to write a class:
class FtpHandler(object):
def __init__(self):
self.count = 0
def update(self, block):
self.count += 1
print self.count
Then, to use it, you construct an instance of the class, and pass a bound method instead of a plain function to the FTP code. For example, instead of this:
ftp = ftplib.FTP(...)
# ...
ftp.storbinary(spam, eggs, callback=update)
… do this:
myhandler = FtpHandler()
ftp = ftplib.FTP(...)
# ...
ftp.storbinary(spam, eggs, callback=myhandler.update)
It doesn't just hang, it produces an Exception (specifically an UnboundLocalError). You're trying to modify a global variable inside of a function; to do this the variable must be declared global:
count = 0
def update(block):
global count
count += 1
print count
This is almost always a sign of bad design, in your case it would probably be better to use a class with an attribute:
class MyCallbackHandler(object):
def __init__(self):
self.count = 0
def update(self, block):
self.count += 1
#... etc.