How does BGE handle Python class definitions?
There are a couple of ways. Here is a simple one:

Write your class e.g. Character.

Character object knows the game objects of the character.

class Character():
    def __init__(self):
        self.skeleton = None
        self.leftHand = None
        self.rightHand = None
        ...

# builder
character = Character()
character.skeleton = scene.objects["Armature"]
character.leftHand = scene.objects["Hand.L"]
...


The game objects might need to know the Character object too:

character.skeleton["character"] = character
character.leftHand["character"] = character


This way you get a cross reference. When you know one of the game objects you can get the according character:

character = gameObject["character"]


When you know the character instance you do not need to dig through the properties anymore.

You could create a factory that establishes these cross references. This keeps this "management" code away from the character's behavior.

You can dynamically exchange references. E.g. the character grabs a book. So you can assign the book to the right hand. You character eats the apple it holds in right hand, you can remove the link between the apple and the right hand, then you can end the apple.

Be aware the BGE events are always applied to game objects (such as collision, ray ...). As said you can get the python character via property.

myCharacter = owner["character"]
hitObject = sensor.hitObject
hitCharacter = hitObject["character"]