Search code examples
pythonfor-loopraspberry-pigpio

Python combining for each and counting


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!


Solution

  • 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.