I want to implement a simple lookup function into a I2C scanner. Ultimately it should be battery powered and with a small OLED display to test and troubleshoot devices in production.
My I2C scanner outputs a list of found devices as hex adresses, e.g. ['0x3c', '0x48']
My idea was to use a list of tuples knownDevices = [(address1, Description1), (address2, Description2)]
I'm a beginner in python, so I'm a bit stuck. I do know how to look up a single value in a "normal" list with if 'x' in 'list'
, but with more devices this would be very bulky.
I'd like to iterate through my list of devices, and on a match with my "database" it should print out something like 'found <description1> at address <address1>'
-
Does this answer your question? [Python search in lists of lists](https://stackoverflow.com/questions/1156087/python-search-in-lists-of-lists) – Ari Cooper-Davis Jun 10 '20 at 09:43
-
1@AriCooper-Davis I don't think so as the OP is using embeded programming. Unless its it is a device with the OS and much power, like Raspberry Pi or something, otherwise list in list searches are a terrible idea for speed and efficiency. Even if there are only two values and you can do it in O(n), you still need an n number of comparisons until you find the right mapping. dict() is better. – Dalen Jun 10 '20 at 10:00
-
I should have clarified on which flavor of python I use. It's micropython on an ESP8266 and/or ESP32. However I also do have an raspberry pi 3b+ and 4 on my desk. – elschopi Jun 10 '20 at 10:45
-
I extended my answer based on extra info from your comment. Take a look at the edited version to learn some more about possible ways you can utilize power of Python dictionaries. – Dalen Jun 11 '20 at 14:51
1 Answers
Let Python do the job for you and map the addresses to descriptions within a dictionary:
desc = {"0xaa": "Proximity 1", "0xbb": "Motion 1"} # And so on
# If you really want a function that does the job (not necessary) then:
get_description = desc.get # Maximize the access speed to the dict.get() method
# The method get works as follows:
desc.get("0xaa", "Unknown device")
# Or you can call it as:
get_description("0xbb", "Unknown device")
# The method gives you the possibility to return the default value in case the key is not in the dictionary
# See help(dict.get)
# But, what you would usually do is:
desc["0xaa"] # Raises an KeyError() if the key is not found
# If you really need a function that returns a list of addr, desc tuples, then you would do:
def sensors ():
return [(x, get_description(x, "Unknown device") for x in get_addresses()]
# Which is short and efficient for:
def sensors ():
sensors_list = []
for x in get_addresses():
tpl = (x, get_description(x, "Unknown device"))
sensors_list.append(tpl)
return sensors_list
Getting a value from the dictionary is very fast and efficient. You shouldn't have time nor memory problems with it. There are number of different ways you can speed up the thing using indexing instead of the dict(), but believe me, if you are not very much constrained by the memory and/or speed, it is not worth time and coding to get it right. This method would include, for example, making the I2C addresses in a such order that your algorithm can scale them down to the indexes of a tuple() containing corresponding descriptions. That depends on how much control do you have over I2C device's addresses. In short, you would be building a lookup table and using it in a similar manner as the trigonometry functions. A lot of work for a simple task. I took a look at the MPython and the MCU you are using, and you definitely have enough resources to use a standard, Pythonic, way for your task, which is: dictionaries.
Also, I must explain that under the example function get_addresses() I meant an function that detects devices present at the time. So, if you need a list of tuples for some reason, and your devices are always present you can just do:
list(desc.items())
The resulting list will be the same as from my sensors() function, but it will always return all devices, if they are present or not. Also, if you added a new device in the mean time, that is not in a dictionary, it will not appear in the resulting list as the "Unknown device".
What you also should know is that the dict() data type, for the optimization reasons is unordered. That means that list(desc.items()) will not return tuples of your devices in an order you entered them in the dict(). But my sensors() function will return them in an order the imagined get_addresses() function returns the addresses of devices.
If you want to display all possible devices in an alphabetical order of descriptions, for example, you can do:
srtkey = lambda item: item[1]
for address, description in sorted(desc.items(), key=srtkey):
print("'%s' @ address %s" % (description, address))
# Of course, you would use the function and/or the algorithm you use to display the string line
Please, take a look at help(dict.items), help(sorted) and help("lambda") to understand how this code works.

- 4,128
- 1
- 17
- 35