You have several similar objects, and in such cases it is often better to treat them evenly and use a data-based approach.
So, I would start with your objects ..._meter_address . For me, they sound like a configuration for counters, so I will have a class that looks something like this:
class MeterConfiguration(object): def __init__(self, name, address): self.name = name self.address = address def english_name(self): """A readable form of the name for this meter.""" return ' '.join(x.title() for x in self.name.split('_')) + ' Meter'
Perhaps you have another configuration (currently stored in variables) that could also be here.
Then I will have a summary of all the counters that your program is associated with. I create them statically, but it is possible that you can read all or part of this information from the configuration file. I have no idea what your addresses look like, so I did something :)
ALL_METERS = [ MeterConfiguration('anodization_voltage', 'PORT0001'), MeterConfiguration('anodization_current', 'PORT0002'), MeterConfiguration('sample_thermometer', 'PORT0003'), MeterConfiguration('heater_thermometer', 'PORT0004') ]
Cool, now the whole configuration is in one place, and we can use this to make things the same and simpler.
private.meters = {} any_errors = False for meter in ALL_METERS: try: private.meters[meter.name] = Voltmeter(meter.address) except VisaError: logging.error('%s not found at %s', meter.english_name(), meter.address) any_errors = True if not any_errors: logging.info('All meters initialized.')
You can use, for example, private.meters['anodization_voltage'] to refer to a specific counter or private.meters['anodization_voltage'] over meters if you need to do something for them.