vendredi 10 avril 2020

Inherit a random class without overriding on instantiation

I am making a hierarchy of Things (Thing > Inorganic, Organic > Plant, Creature > Dog etc.) to learn about classes and inheritance.

I am trying to implement sex but my current solution is pretty hacky. It's currently just determined within the creature class and then functions are dependent on the result. I want sex to be a more fundamental aspect - helping to determine size, weight, and which methods to have. Why should a male creature have methods for pregnancy and birth? Here is what I currently have (extra attributes have been omitted to make it easier to read):

 class Creature(Organic):

    sex_pool = ('male', 'female')
    weight_range = {'male': (0,0), 'female': (0,0)}

    def __init__(self):
        Creature.population += 1
        super().__init__()
        self._sex = random.choice(self.sex_pool)
        self.weight = self.rand_normal(self.weight_range[self._sex]        [0],self.weight_range[self._sex][1])
        self._pregnant = False if self._sex is 'female' else None

    @property
    def sex(self):
        return self._sex

    @property
    def pregnant(self):
        return self._pregnant

    @pregnant.setter
    def pregnant(self, boolean):
        if self._sex is 'female':
            if type(boolean) is bool:
                self._pregnant = boolean
            else:
                print("pregnancy attribute must be a boolean value")
        else:
            print("only females have a pregnancy attribute")

Instead I would like to make Creatures inherit a Sex class, which randomly picks the Male or Female class. I have a Sex class which becomes Male or Female upon init but of course I can't have my creature class inherit this because it will overwrite the creature class too:

class Male:
    def __init__(self):
        self._sex = 'male'

class Female:
    def __init__(self):
        self._sex = 'female'
        self._pregnant = False

    @property
    def pregnant(self):
        return self._pregnant

    @pregnant.setter
    def pregnant(self, boolean):
        if type(boolean) is bool:
            self._pregnant = boolean
        else:
            print("pregnancy attribute must be a boolean value")
class Sex():
    def __init__(self):
        sex = random.choice((Male, Female))
        self.__class__ = sex

I have also tried this but it ends up making the Sex class either always female or always male (and doesn't inherit Organic properly, but I guess that's another matter that I should be able to work out):

class Sex(random.choice((Male,Female))):
    def __init__(self):
        super().__init__()

class Creature(Sex, Organic):
...

Or, is there a way to instantiate a Sex class on creature init and add the properties/methods to the creature class? But that seems like a rather hacky way to 'fake' inheritance and even still, Male, Female, and Sex class properties would be lost (I think).

I guess I want to return some inheritance instruction rather than a class instance in sex, but I'm not sure if this is really possible.

I have sifted through a thorough and seemingly related SO post but all the examples overwrite the inheriting class, which does not work. python class factory inherit random parent

Aucun commentaire:

Enregistrer un commentaire