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 :-))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/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))