I have an application that reads bluetooth advertisements from sensors and does stuff.
Currently, I use a dict to manage instances of the sensors and attributes of them. I have a bunch of functions that I call to do stuff based on the details of the bluetooth advertisements.
I am interested in switching from a dict to creating a class called Sensors. Having functions/methods within the class itself will clean up my code a lot (make it more readable) and set me up better for adding new features.
When a new advertisement comes in, the first step I do is to check whether it's from a sensor I've seen before. This is simple with a dict using
newAdvertisement = {"name": "sensor1", "attribute": "value"}
sensor = newAdvertisement['name']
if sensor in sensorDict
...
I am having trouble figuring out how to do something similar with instances of a class. If I read a string value from the advertisement, how can I check if there is an instance of my class with that name?
I've tried to work out a way to use isInstance with something like this:
newAdvertisement = {"name": "sensor1", "attribute": "value"}
sensor = newAdvertisement['name']
if isInstance(sensor, Sensor):
...
But line 2 sets the variable 'sensor' to the string 'sensor1', so this checks if that string is an instance of Sensor (which it is of course, not). What I want is to check if there is an instance of Sensor called sensor1.
I've also tried to create a list of instances like so:
sensor1 = Sensor(name='sensor1', attribute='value')
sensor2 = Sensor(name='sensor2', attribute='value')
sensorList = [sensor1, sensor2]
newAdvertisement = {"name": "sensor1", "attribute": "value"}
sensor = newAdvertisement['name']
if sensor in sensorList:
...
But again, I'm comparing the string 'sensor' to a list of objects, so it's never going to be there.
Does it make sense to do this? Can I do it cleanly? Is it useful to have my own class in this code?
CodePudding user response:
There's nothing that does this automatically.
Your class can maintain a dictionary of all the instances.
import weakref
class Sensor:
sensor_dict = weakref.WeakValueDictionary()
def __init__(self, name, attribute)
self.sensor_dict[name] = self
self.name = name
self.attribute = attribute
Then you can do
if sensor in Sensor.sensor_dict:
I've used a WeakValueDictionary
so the elements will be removed automatically when the Sensor
instances are GC'ed.
CodePudding user response:
There are many ways of achieving this. One would be to perform some list comprehension to your list when checking to see if the sensor is present in the list of sensors.
For example:
sensor1 = Sensor(name='sensor1', attribute='value')
sensor2 = Sensor(name='sensor2', attribute='value')
sensorList = [sensor1, sensor2]
newAdvertisement = {"name": "sensor1", "attribute": "value"}
sensor = newAdvertisement['name']
if sensor in [i.name for i in sensorList]:
...
Another way would be to overwrite the __eq__
method in your sensor class.
For example:
class Sensor:
def __init__(self, name, attribute):
self.name = name
self.attribute = attribute
def __eq__(self, other):
return other == self.name
sensor1 = Sensor(name='sensor1', attribute='value')
sensor2 = Sensor(name='sensor2', attribute='value')
sensorList = [sensor1, sensor2]
if "sensor1" in sensorList:
print("found")
In the example above, "found" is successfully printed because when you use the in
keyword, python checks for equality on all of the elements in the container. Since the __eq__
method is set to compare to the sensor name, once it reaches the sensor with that name it returns True.