Python combining for each and counting

433 Views Asked by At

I've been going through some tutorials on Python as I'm rather new and I came across a function I would like to use. Namely, 'foreach'. The tutorial script I'm basing myself on looks as follows:

#!/usr/bin/python

for letter in 'Python':     # First Example
   print 'Current Letter :', letter

print "Good bye!"

and

#!/usr/bin/python

for num in range(10,20):  #to iterate between 10 to 20
   for i in range(2,num): #to iterate on the factors of the number
      if num%i == 0:      #to determine the first factor
         j=num/i          #to calculate the second factor
         print '%d equals %d * %d' % (num,i,j)
         break #to move to the next number, the #first FOR
   else:                  # else part of the loop
      print num, 'is a prime number'

I have my own list that I would like a specific action to be applied upon, and that list ranges from relay1 to relay16. Is there a way to make this count from 1 to 16 for me during going through the list?

I was thinking something along the lines of:

GPIO.setmode(GPIO.BCM)
for number in range(1, 17):
        GPIO.setup("relay" + number, GPIO.OUT)
        GPIO.output("relay" + number, GPIO.LOW)
        time.sleep(1)
        GPIO.output("relay" + number, GPIO.HIGH)
GPIO.cleanup()

but it fails:

Traceback (most recent call last):
  File "relay.py", line 25, in <module>
    GPIO.setup("relay" + number, GPIO.OUT)
TypeError: cannot concatenate 'str' and 'int' objects

Thank you for your help!

4

There are 4 best solutions below

3
On BEST ANSWER

The clue is in the error message:

Traceback (most recent call last):
  File "relay.py", line 25, in <module>
    GPIO.setup("relay" + number, GPIO.OUT)
TypeError: cannot concatenate 'str' and 'int' objects

As I mentioned in my comment, you have to change the integer number into a string, and the easiest way is via the str() function:

GPIO.setup("relay" + str(number), GPIO.OUT)
                     ^^^^      ^

And of course, repeat this for the two output() calls.


On the other hand, GPIO.setup() expects an integer, not a string as the first parameter, so an alternative approach is, particularly if relay pin ids are not sequential:

# Or they might be mylib.RELAY1?
relays = [relay1, relay2, ... relay16]

for number in range(1, 17):
    GPIO.setup(relays[number-1], GPIO.OUT)

Or the simpler:

for relay in relays:
    GPIO.setup(relay, GPIO.OUT)

Or even the yet simpler, as the functions appear to accept lists:

GPIO.setup(relays, GPIO.OUT)

On the third hand:

GPIO.setup(globals()["relay" + str(number)], GPIO.OUT)

Might work, but you really don't want to go there.

0
On

Yes, use enumerate. This function returns an iterable of tuples which contain the current index and the element. For example:

for i, e in enumerate(range(10, 20)):
    print(i, e)

Will print out the numbers 0 to 9 for i and 10 to 19 for e.

0
On

Have a look at this entry about your original string formatting problem:

And, as I've noticed that these "strings" are actually variable names, I feel this might be useful:


As to your actual problem, you only need to pass the integer channel numbers to that function.

Example:

GPIO.output(11, GPIO.LOW)

If you want to switch on/off multiple pins at once, you can use a for loop.

Example:

relays = [11, 12]
for i in relays:
    GPIO.output(i, GPIO.LOW)

Or rather pass the numbers as a tuple/list:

relays = [11, 12]
GPIO.output(relays, GPIO.LOW)

It's the same for GPIO.setup().

For reference:


Also, you should have a look into the documentation about the usage and capabilities of the pins you are trying to use:

0
On

Well, first of all you need to fix the concatenation issue.

If you look at this line: GPIO.setup("relay" + number, GPIO.OUT), you see that you are trying to concatenate a STRING "relay" and an INTEGER number together. This won't work. You'll have to change the type of the variable number to string like str(number) in order to handle the error.

Now, as far as counting the list goes, there are a couple ways. If you only need the index numbers of the list, while you can do what you did, you can also do: for index in len(lst):. If you need both the index number AND the list element, then use enumerate(). Refer to @pbreach's answer for examples.