""" 
Necesito código Python para una clase que 
contenga el nombre, apellidos. email y fecha de nacimiento 
de una persona. Toda esta información será accesible 
a través de propiedades de solo lectura. 
Un método str convertirá la información 
en cadena de caracteres. 
Además, la clase Empleado derivada de persona 
contiene la información de la empresa 
para la que trabaja, 
lo publica como propiedad de solo lectura, 
y también provee de un método str que convierte 
toda la información a cadena de caracteres. 
La clase estudiante derivada de persona contiene 
la institución, el nombre del grado y 
el número de curso (1 a 4). 
Toda esta información también se publica 
como propiedades de solo lectura y también ofrece 
un método str que convierte toda la información 
a cadena de caracteres. 
Finalmente, la clase PersonaRepo contiene 
una lista de personas, un método str 
que devuelve toda la información de 
todas las personas (una por línea), 
y una propiedad de solo lectura personas 
que devuelve una lista de personas. 
Además, el método busca admite una lambda 
que permite ejecutar un filtrado 
de las personas almacenadas. 
""" 
 
# AIChat 
 
 
class  Persona:
    # Modificado: init -> __init__ 
    def  __init__ ( self ,  nombre,  apellidos,  email ,  fecha_nacimiento) :
        self ._nombre =  nombre
        self ._apellidos =  apellidos
        self ._email =  email 
        self ._fecha_nacimiento =  fecha_nacimiento
 
    @ property 
    def  nombre( self ) :
        return  self ._nombre
 
    @ property 
    def  apellidos( self ) :
        return  self ._apellidos
 
    @ property 
    def  email ( self ) :
        return  self ._email
 
    @ property 
    def  fecha_nacimiento( self ) :
        return  self ._fecha_nacimiento
 
    def  __str__ ( self ) :
        return  f"{self._nombre} {self._apellidos}, {self._email}, {self._fecha_nacimiento}" 
 
 
class  Empleado( Persona) :
    # Modificado: init -> __init__ 
    def  __init__ ( self ,  nombre,  apellidos,  email ,  fecha_nacimiento,  empresa) :
        # Modificado: init -> __init__ 
        super ( ) .__init__ ( nombre,  apellidos,  email ,  fecha_nacimiento) 
        self ._empresa =  empresa
 
    @ property 
    def  empresa( self ) :
        return  self ._empresa
 
    def  __str__ ( self ) :
        return  f"{self._nombre} {self._apellidos}, {self._email}, {self._fecha_nacimiento}, {self._empresa}" 
 
 
 
class  Estudiante( Persona) :
    # Modificado: init -> __init__ 
    def  __init__ ( self ,  nombre,  apellidos,  email ,  fecha_nacimiento,  institucion,  grado,  curso) :
        # Modificado: init -> __init__ 
        super ( ) .__init__ ( nombre,  apellidos,  email ,  fecha_nacimiento) 
        self ._institucion =  institucion
        self ._grado =  grado
        self ._curso =  curso
 
    @ property 
    def  institucion( self ) :
        return  self ._institucion
 
    @ property 
    def  grado( self ) :
        return  self ._grado
 
    @ property 
    def  curso( self ) :
        return  self ._curso
 
    def  __str__ ( self ) :
        return  f"{self._nombre} {self._apellidos}, {self._email}, {self._fecha_nacimiento}, {self._institucion}, {self._grado}, {self._curso}" 
 
 
class  PersonaRepo:
    # Modificado: init -> __init__ 
    def  __init__ ( self ) :
        self ._personas =  [ ] 
 
    @ property 
    def  personas( self ) :
        return  self ._personas
 
    def  agregar_persona( self ,  persona) :
        self ._personas.append ( persona) 
 
    def  __str__ ( self ) :
        personas_info =  "" 
        for  persona in  self ._personas:
            personas_info +=  str ( persona)  + "\n " 
        return  personas_info
 
    def  buscar( self ,  condicion) :
        return  list ( filter ( condicion,  self ._personas) ) 
 
 
repo =  PersonaRepo( ) 
empleado1 =  Empleado( "Juan" ,  "Perez" ,  "juan@gmail.com" ,  "01-01-1990" ,  "Empresa X" ) 
estudiante1 =  Estudiante( "Maria" ,  "Lopez" ,  "maria@gmail.com" ,  "15-05-1995" ,  "Universidad Y" ,  "Informática" ,  2 ) 
 
repo.agregar_persona ( empleado1) 
repo.agregar_persona ( estudiante1) 
 
print ( repo)  # Imprime la información de todas las personas en el repositorio 
# Modificado: es necesario un join. 
print ( str .join ( ", " ,  [ str ( x)  for  x in  repo.buscar ( lambda  persona: persona.nombre .startswith ( "J" ) ) ] ) )  # Ejemplo de búsqueda usando una lambda 
 
 
				IiIiCk5lY2VzaXRvIGPDs2RpZ28gUHl0aG9uIHBhcmEgdW5hIGNsYXNlIHF1ZQpjb250ZW5nYSBlbCBub21icmUsIGFwZWxsaWRvcy4gZW1haWwgeSBmZWNoYSBkZSBuYWNpbWllbnRvCmRlIHVuYSBwZXJzb25hLiBUb2RhIGVzdGEgaW5mb3JtYWNpw7NuIHNlcsOhIGFjY2VzaWJsZQphIHRyYXbDqXMgZGUgcHJvcGllZGFkZXMgZGUgc29sbyBsZWN0dXJhLgpVbiBtw6l0b2RvIHN0ciBjb252ZXJ0aXLDoSBsYSBpbmZvcm1hY2nDs24KZW4gY2FkZW5hIGRlIGNhcmFjdGVyZXMuCkFkZW3DoXMsIGxhIGNsYXNlIEVtcGxlYWRvIGRlcml2YWRhIGRlIHBlcnNvbmEKY29udGllbmUgbGEgaW5mb3JtYWNpw7NuIGRlIGxhIGVtcHJlc2EKcGFyYSBsYSBxdWUgdHJhYmFqYSwKbG8gcHVibGljYSBjb21vIHByb3BpZWRhZCBkZSBzb2xvIGxlY3R1cmEsCnkgdGFtYmnDqW4gcHJvdmVlIGRlIHVuIG3DqXRvZG8gc3RyIHF1ZSBjb252aWVydGUKdG9kYSBsYSBpbmZvcm1hY2nDs24gYSBjYWRlbmEgZGUgY2FyYWN0ZXJlcy4KTGEgY2xhc2UgZXN0dWRpYW50ZSBkZXJpdmFkYSBkZSBwZXJzb25hIGNvbnRpZW5lCmxhIGluc3RpdHVjacOzbiwgZWwgbm9tYnJlIGRlbCBncmFkbyB5CmVsIG7Dum1lcm8gZGUgY3Vyc28gKDEgYSA0KS4KVG9kYSBlc3RhIGluZm9ybWFjacOzbiB0YW1iacOpbiBzZSBwdWJsaWNhCmNvbW8gcHJvcGllZGFkZXMgZGUgc29sbyBsZWN0dXJhIHkgdGFtYmnDqW4gb2ZyZWNlCnVuIG3DqXRvZG8gc3RyIHF1ZSBjb252aWVydGUgdG9kYSBsYSBpbmZvcm1hY2nDs24KYSBjYWRlbmEgZGUgY2FyYWN0ZXJlcy4KRmluYWxtZW50ZSwgbGEgY2xhc2UgUGVyc29uYVJlcG8gY29udGllbmUKdW5hIGxpc3RhIGRlIHBlcnNvbmFzLCB1biBtw6l0b2RvIHN0cgpxdWUgZGV2dWVsdmUgdG9kYSBsYSBpbmZvcm1hY2nDs24gZGUKdG9kYXMgbGFzIHBlcnNvbmFzICh1bmEgcG9yIGzDrW5lYSksCnkgdW5hIHByb3BpZWRhZCBkZSBzb2xvIGxlY3R1cmEgcGVyc29uYXMKcXVlIGRldnVlbHZlIHVuYSBsaXN0YSBkZSBwZXJzb25hcy4KQWRlbcOhcywgZWwgbcOpdG9kbyBidXNjYSBhZG1pdGUgdW5hIGxhbWJkYQpxdWUgcGVybWl0ZSBlamVjdXRhciB1biBmaWx0cmFkbwpkZSBsYXMgcGVyc29uYXMgYWxtYWNlbmFkYXMuCiIiIgoKIyBBSUNoYXQKCgpjbGFzcyBQZXJzb25hOgogICAgIyBNb2RpZmljYWRvOiBpbml0IC0+IF9faW5pdF9fCiAgICBkZWYgX19pbml0X18oc2VsZiwgbm9tYnJlLCBhcGVsbGlkb3MsIGVtYWlsLCBmZWNoYV9uYWNpbWllbnRvKToKICAgICAgICBzZWxmLl9ub21icmUgPSBub21icmUKICAgICAgICBzZWxmLl9hcGVsbGlkb3MgPSBhcGVsbGlkb3MKICAgICAgICBzZWxmLl9lbWFpbCA9IGVtYWlsCiAgICAgICAgc2VsZi5fZmVjaGFfbmFjaW1pZW50byA9IGZlY2hhX25hY2ltaWVudG8KCiAgICBAcHJvcGVydHkKICAgIGRlZiBub21icmUoc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX25vbWJyZQoKICAgIEBwcm9wZXJ0eQogICAgZGVmIGFwZWxsaWRvcyhzZWxmKToKICAgICAgICByZXR1cm4gc2VsZi5fYXBlbGxpZG9zCgogICAgQHByb3BlcnR5CiAgICBkZWYgZW1haWwoc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX2VtYWlsCgogICAgQHByb3BlcnR5CiAgICBkZWYgZmVjaGFfbmFjaW1pZW50byhzZWxmKToKICAgICAgICByZXR1cm4gc2VsZi5fZmVjaGFfbmFjaW1pZW50bwoKICAgIGRlZiBfX3N0cl9fKHNlbGYpOgogICAgICAgIHJldHVybiBmIntzZWxmLl9ub21icmV9IHtzZWxmLl9hcGVsbGlkb3N9LCB7c2VsZi5fZW1haWx9LCB7c2VsZi5fZmVjaGFfbmFjaW1pZW50b30iCgoKY2xhc3MgRW1wbGVhZG8oUGVyc29uYSk6CiAgICAjIE1vZGlmaWNhZG86IGluaXQgLT4gX19pbml0X18KICAgIGRlZiBfX2luaXRfXyhzZWxmLCBub21icmUsIGFwZWxsaWRvcywgZW1haWwsIGZlY2hhX25hY2ltaWVudG8sIGVtcHJlc2EpOgogICAgICAgICMgTW9kaWZpY2FkbzogaW5pdCAtPiBfX2luaXRfXwogICAgICAgIHN1cGVyKCkuX19pbml0X18obm9tYnJlLCBhcGVsbGlkb3MsIGVtYWlsLCBmZWNoYV9uYWNpbWllbnRvKQogICAgICAgIHNlbGYuX2VtcHJlc2EgPSBlbXByZXNhCiAgICAgICAgCiAgICBAcHJvcGVydHkKICAgIGRlZiBlbXByZXNhKHNlbGYpOgogICAgICAgIHJldHVybiBzZWxmLl9lbXByZXNhCgogICAgZGVmIF9fc3RyX18oc2VsZik6CiAgICAgICAgcmV0dXJuIGYie3NlbGYuX25vbWJyZX0ge3NlbGYuX2FwZWxsaWRvc30sIHtzZWxmLl9lbWFpbH0sIHtzZWxmLl9mZWNoYV9uYWNpbWllbnRvfSwge3NlbGYuX2VtcHJlc2F9IgogICAgICAgIAogIAoKY2xhc3MgRXN0dWRpYW50ZShQZXJzb25hKToKICAgICMgTW9kaWZpY2FkbzogaW5pdCAtPiBfX2luaXRfXwogICAgZGVmIF9faW5pdF9fKHNlbGYsIG5vbWJyZSwgYXBlbGxpZG9zLCBlbWFpbCwgZmVjaGFfbmFjaW1pZW50bywgaW5zdGl0dWNpb24sIGdyYWRvLCBjdXJzbyk6CiAgICAgICAgIyBNb2RpZmljYWRvOiBpbml0IC0+IF9faW5pdF9fCiAgICAgICAgc3VwZXIoKS5fX2luaXRfXyhub21icmUsIGFwZWxsaWRvcywgZW1haWwsIGZlY2hhX25hY2ltaWVudG8pCiAgICAgICAgc2VsZi5faW5zdGl0dWNpb24gPSBpbnN0aXR1Y2lvbgogICAgICAgIHNlbGYuX2dyYWRvID0gZ3JhZG8KICAgICAgICBzZWxmLl9jdXJzbyA9IGN1cnNvCgogICAgQHByb3BlcnR5CiAgICBkZWYgaW5zdGl0dWNpb24oc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX2luc3RpdHVjaW9uCgogICAgQHByb3BlcnR5CiAgICBkZWYgZ3JhZG8oc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX2dyYWRvCgogICAgQHByb3BlcnR5CiAgICBkZWYgY3Vyc28oc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX2N1cnNvCgogICAgZGVmIF9fc3RyX18oc2VsZik6CiAgICAgICAgcmV0dXJuIGYie3NlbGYuX25vbWJyZX0ge3NlbGYuX2FwZWxsaWRvc30sIHtzZWxmLl9lbWFpbH0sIHtzZWxmLl9mZWNoYV9uYWNpbWllbnRvfSwge3NlbGYuX2luc3RpdHVjaW9ufSwge3NlbGYuX2dyYWRvfSwge3NlbGYuX2N1cnNvfSIKICAgICAgICAKICAgICAgICAKY2xhc3MgUGVyc29uYVJlcG86CiAgICAjIE1vZGlmaWNhZG86IGluaXQgLT4gX19pbml0X18KICAgIGRlZiBfX2luaXRfXyhzZWxmKToKICAgICAgICBzZWxmLl9wZXJzb25hcyA9IFtdCgogICAgQHByb3BlcnR5CiAgICBkZWYgcGVyc29uYXMoc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX3BlcnNvbmFzCgogICAgZGVmIGFncmVnYXJfcGVyc29uYShzZWxmLCBwZXJzb25hKToKICAgICAgICBzZWxmLl9wZXJzb25hcy5hcHBlbmQocGVyc29uYSkKCiAgICBkZWYgX19zdHJfXyhzZWxmKToKICAgICAgICBwZXJzb25hc19pbmZvID0gIiIKICAgICAgICBmb3IgcGVyc29uYSBpbiBzZWxmLl9wZXJzb25hczoKICAgICAgICAgICAgcGVyc29uYXNfaW5mbyArPSBzdHIocGVyc29uYSkgKyAiXG4iCiAgICAgICAgcmV0dXJuIHBlcnNvbmFzX2luZm8KCiAgICBkZWYgYnVzY2FyKHNlbGYsIGNvbmRpY2lvbik6CiAgICAgICAgcmV0dXJuIGxpc3QoZmlsdGVyKGNvbmRpY2lvbiwgc2VsZi5fcGVyc29uYXMpKQoKCnJlcG8gPSBQZXJzb25hUmVwbygpCmVtcGxlYWRvMSA9IEVtcGxlYWRvKCJKdWFuIiwgIlBlcmV6IiwgImp1YW5AZ21haWwuY29tIiwgIjAxLTAxLTE5OTAiLCAiRW1wcmVzYSBYIikKZXN0dWRpYW50ZTEgPSBFc3R1ZGlhbnRlKCJNYXJpYSIsICJMb3BleiIsICJtYXJpYUBnbWFpbC5jb20iLCAiMTUtMDUtMTk5NSIsICJVbml2ZXJzaWRhZCBZIiwgIkluZm9ybcOhdGljYSIsIDIpCgpyZXBvLmFncmVnYXJfcGVyc29uYShlbXBsZWFkbzEpCnJlcG8uYWdyZWdhcl9wZXJzb25hKGVzdHVkaWFudGUxKQoKcHJpbnQocmVwbykgIyBJbXByaW1lIGxhIGluZm9ybWFjacOzbiBkZSB0b2RhcyBsYXMgcGVyc29uYXMgZW4gZWwgcmVwb3NpdG9yaW8KIyBNb2RpZmljYWRvOiBlcyBuZWNlc2FyaW8gdW4gam9pbi4KcHJpbnQoc3RyLmpvaW4oIiwgIiwgW3N0cih4KSBmb3IgeCBpbiByZXBvLmJ1c2NhcihsYW1iZGEgcGVyc29uYTogcGVyc29uYS5ub21icmUuc3RhcnRzd2l0aCgiSiIpKV0pKSAjIEVqZW1wbG8gZGUgYsO6c3F1ZWRhIHVzYW5kbyB1bmEgbGFtYmRhCg==