Do you get what is going on with subclasses overriding things from the base class?
Not 100%
Okay, this is worth spending some time to understand.
This is where I think I have trouble. Although I have seen it discussed, the concept of "helper method" is not clear to me yet.
Well, it's one of those terms that is so overused that it only really means something in context.
Let me try to explain some of the basics. You might already know all this, but if not, maybe it will fill some gaps.
Let's say I have a class that looks like this:
class Person(object): def __init__(self, name): self.name = name
def _title(self): return ""
def proper_name(self): return "%s %s" % (self.title(), self.name)
With which I can do this:
p = Person('Dan') p.proper_name()
' Dan'
Then I can inherit from that with something like:
class Female(Person): def _title(self): return 'Ms.'
class Male(Person): def _title(self): return "Mr.'
Since I inherit from the Person class, the above two behave exactly the same as Person, except when and where _title is called, and then they "override" the behavior of the base class. So, I can do this:
d = Male('Bob') d.proper_name()
'Mr. Bob'
t = Female('Alice') t.proper_name()
'Ms. Alice'
So, the proper_name() method on the base class works as we expect, but since we override the _title() method, we get different results if we use the subclass.
These are like what you're trying to do. If proper_name() was a really complicated method (like get_memory() is) then you could share the bulk of code between multiple classes. For any thing that differs between the two, then you can just put that bit of code into a "helper method" and make get_memory() call that helper instead. That way, you can override that one piece in a subclass to get the differing behavior.
So, lets say that everything is completely identical between RadioA and RadioB, except that the calculation of the frequency was different. You might do this:
class BaseRadio(chirp_common.CloneModeRadio): VENDOR = "FOO"
def _get_freq(self, _mem): # Not really used pass
def get_memory(self, number): ... mem.freq = self._get_freq(_mem) ... return mem
@directory.register class RadioA(BaseRadio): MODEL = "RadioA"
def _get_freq(self, _mem): # Totally made up frequency thing return (_mem.freq[0] + _mem.freq[1]) * 2.5
@directory.register class RadioB(BaseRadio): MODEL = "RadioB"
def _get_freq(self, _mem): # Totally made up different thing return (_mem.freq[1] + _mem.freq[0]) * 5.0
So, this creates a BaseRadio class, which has the big complicated get_memory() function, but which calls out to _get_freq() for the frequency calculation bit. We don't register that class, which means it doesn't actually show up to the user. Then we create two subclasses for the two variants, and all they need to do is implement the _get_freq() bit. Note that they also both inherit the VENDOR from the base class, but override the MODEL in the same way as they override the _get_freq() method. So, if we're using RadioA, we'll get all the behaviors of the BaseRadio class, but with just the frequency calculation of the RadioA class overridden. Same for the RadioB class.
I think that if you look at your uv5r.py, you'll see this patter applies to all the stuff there, with the exception that the base class there is actually registered, because it's the main uv5 driver as well. Similarly, the TH9000 driver matches the above case where there is a base class that isn't registered. It's a good example to look at, although I don't think it overrides any methods or functions from the base class, only properties (like MODEL, VENDOR, etc). The KG816 driver in wouxun.py has some examples of overriding some methods, although none quite match the example above where they intentionally break out a piece of something like get_memory() for the subclasses to override.
Hopefully looking at some of the code you're familiar with through the lens of the above information will help crystallize things a little. If any of it doesn't make sense or you have further questions, don't hesitate to ask!
--Dan