On 19Aug2018 15:09, richard lucassen <mailingli...@lucassen.org> wrote:
On Sun, 19 Aug 2018 19:53:04 +1000
Cameron Simpson <c...@cskk.id.au> wrote:
Although I do not understand what zip is doing exactly here (I presume
I switch to use pointers instead of the values),

Someone else has descibed zip tersely: it pairs it the elements of 2 lists. In fact it joins up matching elements of an arbitrary number of iterables. Here is a 3 iterable example:

   >>> zip( (1,2,3), (4,5,6), (7,8,9) )
   <zip object at 0x10aa4ce88>
   >>> list( zip( (1,2,3), (4,5,6), (7,8,9) ) )
   [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

See that is has collected the first element of each tuple, then the second and so forth?

In my sentence above, "iterable" means any object you can iterate over - any object you could use in a for-loop. So, obviously, a list as in your programme. And also a tuple like (1,2,3) as in the example above (a tuple is an unmodifiable list). ANd any number of other things that will yield a sequence of values.

In Python 3 (which you're using) zip returns a lazy object, which does the zipping as you request the values. That is why the example shows a base "zip()" returning a "zip object" - we hand it to list() to get an actual list of all the values. This is fast (instant return of the zip object without doing much work) and cheap in memory (no need to make a huge result if you're zipping big lists) and cheap in time (no need to make the whole result if you're only using the first part of it).

So, to the code using the zip:

 for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):

The inner zip yields (pcf, pcf_value) pairs from zipping list_pcf and list_pcf_value, an iterable of:

 (pcf[0], pcf-value[0]), (pcf[1], pcf_value[1]), ...

and you can write a for loop like this:

 for pcf, pcf_value in zip(list_pcf, list_pcf_value):

to deal with each of those pairs in turn.

However, since you also need the index (device_nr) in order to update list_pcf_value:

 list_pcf_value[device_nr] = output

we then hand the whole thing to enumerate:

 for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):

The enumerate does just what the previous one did, yields pairs of (index, value). Each value is a pair from the zip, so it yields:

 (0, (pcf[0], pcf-value[0])),
 (1, (pcf[1], pcf_value[1])),
 ...

and Python's tuple unpacking syntax is fairly generous, so you want write:

 device_nr, (pcf, pcf_value) = (0, (pcf[0], pcf-value[0]))

and you can stick that in the for loop, getting the syntax you're using in the programme:

 for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):

The code is now as follows:

Much nicer. A few tiny nit picks:

#!/usr/bin/env python3

import sys
from smbus import SMBus
from time import sleep
import RPi.GPIO as GPIO

list_pcf = [0x38, 0x39, 0x3a, 0x3b]
list_pcf_value = []

Just convention: you could call these pcfs and pcf_values and perhaps have more readable code. Using plural names kind of indicates that they're lists (or tuples or some other sequence of values) and reads more like prose.

# initialisation of the input devices:
print ("[INFO] initialisation input devices")

"print" is just a regular function. We tend not to put a space before the "(" with other functions, and print isn't special. You might have this trailing space left over from Python 2 (either your own or some example code), where print _wasn't_ a function. So:

 print("[INFO] initialisation input devices")

for pcf in list_pcf:
 try:
   bus.write_byte(pcf, 0xff) # set device to 0xff
 except IOError as e:
   print ("[ALERT] I/O problem device 0x%x (init): %s" % (pcf, e))
 output = bus.read_byte(pcf)

You presumably also want a try/except around the bus.read_byte. You could use a distinct try/except (rather wordy) or, since they're adjacent and your exception action is the same, just put them both inside the try/except.

The advice to keep things as small as possible within the try/except has to do with knowing exactly what kind of thing threw the exception. But they're both bus operations and handled the same - including both is reasonable.

 list_pcf_value.append(output) # append value to list
 print ("found pcf8574 at 0x%x, input value: 0x%x" % (pcf, output))
 sys.stdout.flush()
# GPIO 23 set up as input. It is pulled up to stop false signals
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
loopcntr = 0 # detects if INT is kept low

while True:
 if GPIO.input(23) == 1: # if still 0, another event has occurred
   GPIO.wait_for_edge(23, GPIO.FALLING)

Can the GPIO ops also raise IOErrors? Just wondering.

Cheers,
Cameron Simpson <c...@cskk.id.au>

Stepwise Refinement n.  A sequence of kludges K, neither distinct or finite,
applied to a program P aimed at transforming it into the target program Q.
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to