fork download
  1. # coding: utf-8
  2. # Solución ALS (c) 2019 Baltasar MIT License <jbgarcia@uvigo.es>
  3.  
  4.  
  5. """
  6. 1. (4pts.) La clase Ciudadano alberga los años más significativos de
  7. un ciudadano de un país dado. Se construye con unos apellidos, un nombre
  8. y una lista de tres números: el año de nacimiento,
  9. el año del primer empleo, el año de jubilación y el de defunción.
  10. Los métodos de esta clase serán
  11. exactamente __init__(), __getattr__() y __str__().
  12. Aún así, será capaz de responder a la petición de varias “propiedades”:
  13. annos devuelve una nueva lista con todos los años, nacimiento
  14. devolverá el año de nacimiento, primer_empleo el del primer empleo,
  15. jubilacion la de jubilación, y defuncion la de defunción.
  16. El “método” calcula_annos_vida() calcula el número de años
  17. entre el nacimiento y la defunción.
  18. El “método” calcula_annos_activos() calcula la diferencia
  19. entre los años del primer empleo y la jubilación.
  20. El método __str__() devolverá la información en el formato
  21. <apellidos>, <nombre>: <nacimiento> - <defuncion>(<primer_empleo> - <jubilacion>),
  22. como por ejemplo: Díaz de Vivar, Rodrigo: 1043-1099(1065-1099).
  23.  
  24. c1 = Ciudadano(“Díaz de Vivar”, “Rodrigo”, [1043, 1065, 1099, 1099])
  25. print(c1.annos[0], c1.primer_empleo, c1.annos[2], c1.defuncion) # 1043 1065 1099 1099
  26. print(c1.calcula_annos_vida()) # 56
  27. print(c1.calcula_annos_activos()) # 34
  28. print(c1) # Díaz de Vivar, Rodrigo: 1043-1099(1065-1099)
  29.  
  30. 2. (1pts.) Cree los métodos to_json(f) y from_json(f).
  31. El primero escribe la codificación JSON del objeto en un archivo f,
  32. la segunda toma un archivo f con contenido en formato JSON
  33. y crea un objeto con dicho contenido.
  34.  
  35. 3. (4pts.) Cree la clase Censo que almacena ciudadanos en una lista.
  36. Esta clase admite un parámetro en el constructor:
  37. un objeto de la clase Ciudadano o una lista con los objetos Ciudadano.
  38. Tendrá también el acceso de solo lectura [i],
  39. que devolverán el ciudadano i-ésimo, y la función len()
  40. el número total de ciudadanos.
  41. El método __str_₍) devolverá toda la
  42. información con cada ciudadano en su propia línea.
  43. El método add(c) permitirá añadir un nuevo ciudadano,
  44. mientras que los métodos calcula_media_vida()
  45. y calcula_media_activos() calcularán la media de los años de vida
  46. y los años activos, respectivamente.
  47.  
  48. 4. (1pts.) Incluya en la clase Censo los métodos
  49. calcula_media_vida() y calcula_media_activos()
  50. que calcularán la media de los años de vida y los años activos,
  51. respectivamente.
  52. Deben hacerlo empleando la función reduce(f,l,i) del paquete estándar functtols.
  53. """
  54.  
  55.  
  56. import io
  57. import unittest
  58. import json
  59. from functools import reduce
  60.  
  61.  
  62. class Ciudadano:
  63. def __init__(self, apellidos, nombre, annos):
  64. self._apellidos = apellidos
  65. self._nombre = nombre
  66. self._annos = annos
  67.  
  68. def __getattr__(self, s):
  69. toret = ""
  70.  
  71. if s == "apellidos":
  72. toret = self._apellidos
  73. elif s == "nombre":
  74. toret = self._nombre
  75. elif s == "annos":
  76. toret = list(self._annos)
  77. elif s == "nacimiento":
  78. toret = self._annos[0]
  79. elif s == "primer_empleo":
  80. toret = self._annos[1]
  81. elif s == "jubilacion":
  82. toret = self._annos[2]
  83. elif s == "defuncion":
  84. toret = self._annos[3]
  85. elif s == "calcula_annos_vida":
  86. toret = lambda: self.annos[3] - self.annos[0]
  87. elif s == "calcula_annos_activos":
  88. toret = lambda: self.annos[2] - self.annos[1]
  89.  
  90. return toret
  91.  
  92. def to_json(self, f):
  93. json.dump(self.__dict__, f)
  94.  
  95. def from_json(self, f):
  96. toret = Ciudadano("", "", [])
  97. toret.__dict__ = json.read(f)
  98.  
  99. return toret
  100.  
  101. def __str__(self):
  102. return str.format("{}, {}: {}-{}({}-{})",
  103. self.apellidos,
  104. self.nombre,
  105. self.nacimiento,
  106. self.defuncion,
  107. self.primer_empleo,
  108. self.jubilacion)
  109.  
  110.  
  111. class Censo:
  112. def __init__(self, l):
  113. if l:
  114. if isinstance(l, list):
  115. self._ciudadanos = l
  116. elif isinstance(l, Ciudadano):
  117. self._ciudadanos = [l]
  118.  
  119. def add(self, c):
  120. self._ciudadanos.append(c)
  121.  
  122. def calcula_media_activos(self):
  123. toret = reduce(
  124. lambda acc, c2: acc + c2.calcula_annos_activos(),
  125. self._ciudadanos,
  126. 0)
  127. return toret / len(self._ciudadanos)
  128.  
  129. def calcula_media_vida(self):
  130. toret = reduce(
  131. lambda acc, c2: acc + c2.calcula_annos_vida(),
  132. self._ciudadanos,
  133. 0)
  134. return toret / len(self._ciudadanos)
  135.  
  136. def __getitem__(self, it):
  137. return self._ciudadanos[it]
  138.  
  139. def __len__(self):
  140. return len(self._ciudadanos)
  141.  
  142. def __str__(self):
  143. toret = ""
  144.  
  145. for c in self._ciudadanos:
  146. toret += str(c) + '\n'
  147.  
  148. return toret
  149.  
  150.  
  151. class TestCiudadano(unittest.TestCase):
  152. def setUp(self):
  153. self.c1 = Ciudadano("Diaz de Vivar", "Rodrigo", [1043, 1065, 1099, 1099])
  154. self.datos_c1 = "{'_apellidos':'Diaz de Vivar','_nombre':'Rodrigo','_annos':[1043,1065,1099,1099]}"
  155.  
  156. def testNombre(self):
  157. self.assertEqual("Rodrigo", self.c1.nombre)
  158.  
  159. def testApellidos(self):
  160. self.assertEqual("Diaz de Vivar", self.c1.apellidos)
  161.  
  162. def testNacimiento(self):
  163. self.assertEqual(1043, self.c1.nacimiento)
  164.  
  165. def testDefuncion(self):
  166. self.assertEqual(1099, self.c1.defuncion)
  167.  
  168. def testJubilacion(self):
  169. self.assertEqual(1099, self.c1.jubilacion)
  170.  
  171. def testPrimerEmpleo(self):
  172. self.assertEqual(1065, self.c1.primer_empleo)
  173.  
  174. def testCiudadano(self):
  175. self.assertEqual("Diaz de Vivar, Rodrigo: 1043-1099(1065-1099)", str(self.c1))
  176.  
  177. def testAnnosVida(self):
  178. self.assertEqual(56, self.c1.calcula_annos_vida())
  179.  
  180. def testAnnosActivos(self):
  181. self.assertEqual(34, self.c1.calcula_annos_activos())
  182.  
  183. def testToJson(self):
  184. with io.StringIO() as f:
  185. self.c1.to_json(f)
  186. self.assertEqual(TestCiudadano.prepara_resultado(self.datos_c1), TestCiudadano.prepara_resultado(f.getvalue().strip()))
  187.  
  188. @staticmethod
  189. def prepara_resultado(s):
  190. return str(s).strip().replace('\'', '"').replace(' ', "")
  191.  
  192.  
  193. class TestCenso(unittest.TestCase):
  194. def setUp(self):
  195. self.c1 = Ciudadano("Diaz de Vivar", "Rodrigo", [1043, 1065, 1099, 1099])
  196. self.c2 = Ciudadano("Kane", "Roger", [1840, 1860, 1880, 1890])
  197. self.censo = Censo([self.c1])
  198.  
  199. def testLen(self):
  200. self.assertEqual(len(self.censo._ciudadanos), len(self.censo))
  201.  
  202. def testStr(self):
  203. expected = "\n".join([str(c) for c in self.censo._ciudadanos])
  204. self.assertEqual(expected, str(self.censo).strip())
  205.  
  206. def testAdd(self):
  207. self.censo.add(self.c2)
  208. self.assertEqual(2, len(self.censo))
  209. self.assertEqual(self.c2, self.censo[1])
  210.  
  211. def testAccess(self):
  212. self.assertEqual(self.c1, self.censo[0])
  213.  
  214. def testCalculaMediaVida(self):
  215. media_vida = 0
  216.  
  217. for c in self.censo._ciudadanos:
  218. media_vida += c.calcula_annos_vida()
  219.  
  220. media_vida /= len(self.censo._ciudadanos)
  221.  
  222. self.assertEqual(media_vida, self.censo.calcula_media_vida())
  223.  
  224. def testCalculaMediaActivos(self):
  225. media_activos = 0
  226.  
  227. for c in self.censo._ciudadanos:
  228. media_activos += c.calcula_annos_activos()
  229.  
  230. media_activos /= len(self.censo._ciudadanos)
  231.  
  232. self.assertEqual(media_activos, self.censo.calcula_media_activos())
  233.  
  234. if __name__ == "__main__":
  235. unittest.main()
  236.  
Success #stdin #stdout #stderr 0.04s 32192KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
................
----------------------------------------------------------------------
Ran 16 tests in 0.001s

OK