Slots, Abstracts classes en Python 3

¿Se acuerdan del ejemplo anterior usando classes en Python? En este caso hice un par de cambios para aprender más sobre clases abstractas y slots (una manera de ahorrar memoria en Python cuando creamos objetos).

En este caso:

  • Uso un ‘slot’ para guardar sólo 3 atributos que son definidos en el constructor
    Declaro la propiedad ‘party’ como abstracta ya que quiero que el que extienda las clases se vea forzado a implementar un método adecuado que me diga de que partido viene
    También obligo al usuario a declarar el método ‘__bool__’ el cual utilizo para saber si es Democrata u otra clase (si, el ejemplo es forzado :-))
#!/usr/bin/env python3
# A little fun with the candidates for the US presidency for 2016 election year
# Revisited versions with slots, abstract classes
# @author josevnz@kodegeek.com
#
import abc

class Candidate(metaclass=abc.ABCMeta):
    
    __slots__ = ("__name", "__sex", "__age")

    @abc.abstractmethod    
    def __init__(self, name, sex="F", age=21):
        self.__name = name
        self.__sex = "F" if sex not in ["M", "F"] else sex
        self.__age = 21 if not (21 < = age <= 120) else age
    
    @property
    def name(self):
        return self.__name
    
    def get_party(self):
        raise NotImplemented()
    
    party = abc.abstractproperty(get_party)
    
    @property
    def sex(self):
        return self.__sex
    
    @property
    def age(self):
        return self.__age
    
    def __hash__(self):
        return hash(id(self))
    
    def __str__(self):
        return "{}=[name={}, sex={}, age={}]".format(self.__class__.__name__,
                                                            self.__name,
                                                            self.__sex,
                                                            self.__age
                                                            )
    
    def __repr__(self):
        return "{}({}{}{}{})".format(
                                 self.__class__.__name__, 
                                 self.__name, 
                                 self.__sex, 
                                 self.__age
                                )
    
    @abc.abstractmethod
    def __bool__(self):
        raise NotImplemented()
    
    def __lt__(self, other):
        return self.__age < other.__age 

     def __gt__(self, other): 
        return self.__age > other.__age
    
    def __eq__(self, other):
        return (
                self.__age == other.__age and 
                self.__name == other.__name and
                self.__sex == other.__sex
                )

class Republican(Candidate):
    
    def __init__(self, name, sex="F", age=21):
        return super().__init__(name, sex, age)
    
    party = "Republican Party (GOP)"
    
    def __bool__(self):
        return False
            
class Democrat(Candidate):
    
    def __init__(self, name, sex="F", age=21):
        return super().__init__(name, sex, age)
    
    party = "Democratic Party"
    
    def __bool__(self):
        return True
    
if __name__ == "__main__":
        candidates = []
        candidates.append(Democrat("Hillary Clinton", "F", 68))
        candidates.append(Republican("Donald Trump", "M", 70))
        candidates.append(Democrat("Bernie Sanders", "M", 75))
        candidates.append(Republican("Marco Rubio", "M", 45))
        for candidate in sorted(candidates, reverse=True):
            isDemocrat = "yes" if candidate else "no"
            print("Candidate: {}, democrat? {}".format(candidate, isDemocrat))