 Ok, moi bons dias. Bienvenidos, gràcies por estar a cá. Es para moi un gusto presentar-les a Victor Terrón, quien nos hablará acerca del módulo Eater Tools. Ao final, unha ronda de preguntas de cinco minutos. Xerziómo-lo, por favor, con un aplauso. Xerzió, no, no, no, no. Ui, le ia dá-lo. Se me oye? Muy bien. Creo que hay un doctor Huck que dicen, no propadez. Mira fíjamente, tenemos un montón de material. Se alguien tiene alguno ajeción que levante la mano. Todos sabemos como se tira sobre o elemento de una lista, vamos muy rápido, nos lo enseñan sempre quando empezamos nos dicen, paramos na lista de números, para cada número da lista haza algo con el número. E eso é un buclezor, e a todos nos dicen e insiste en un montón, eso é un mucho, mucho mejor que hacer esta outra cosa, que si venimos de todos os lenguajes de programación podemos estar tentados de hacer, e non, eu vou iterar sobre os índices. Voy a generar toda a lista de índices e entonces para cada índice hacía do elemento e hago lo que quiera con el elemento. Por exemplo, neste caso, vou a imprimir-lo e nos dicen, no, eso non se hace. De hecho, aún, aún, aún peor é quem intenta hacer esto e é que dice, bueno, para que utiliza range eu puedo manipular números por mim mismo e entonces crean su índice e lo van incrementando su valor en cada iteración e van aciriendo os índices, etc. E nos dicen, no, non se hace assim, ese non é o camino de Python. O camino de Python é que digamos simplemente no. É un buclezor, que en outro lenguaje de programación se conoce como for each, e nos dicen, sí, sí, Python, e nosotros asintimos. E realmente sabemos que é mucho, mucho mejor porque tenemos má nivel de acteración. É un código, podríamos argumentar má legible, má claro e sobre todo, nós estamos pensando en índices. Simplemente, nós dizimos para cada cosa en eso, gran precisión, al lo que quiera con esa cosa. De hecho, quizá no tan importante pero tan bien lo é, é que no estamos manipulando los índices e é outra ventaja, no solamente o código má legible, sino que tan bien que podemos equivocarnos. De hecho, eu argumentaria que non pode equivocarte ningún sitio con un bucle for each porque é imposible que me atas la pata. Sin embargo, aquí podría ocorrir que se nos fuere a la mano e nos estamos pasando con el índice e hemos puesto o, no hemos parado en el enm nos 1, hemos parado en el n e como empezamos a contar por cero o código explota, index error. Por supuesto, no solamente funcione con listas aunque é con o que sempre se empieza cuando damos Podemos utilizarlo, por exemplo, con cadenas. De hecho, para cada letra, en esta cadena de vocales, haza algo cola letra e la imprimo. A, E, I, O, U. También, se tenemos un conjunto, podemos iterar sobre o conjunto, aunque sempre sabemos detallar de implementación, de que no tenemos ninguna garantía respecto ao orden. Pero a cosa é que podemos iterar sobre o rolamento do conjunto. O si tenemos un diccionario, por exemplo, utilizando items, podemos decir, muy bien, para cada clave e subador asociado en el diccionario, haza algo con ellos. Una vez más, un bucle 4. De modo que, se tenemos un fichero, abrimos o fichero, o Quijote, e podemos iterar sobre o fichero objeto, SFD de File Descriptor, que sempre utilizamos quando trabajamos con ficheros, e podemos imprimir cada una de las líneas, con o cual é sempre o mesmo, o cual é muy bueno, a estandarización. De hecho, resulta que, se miramos na documentación, o bucle 4 se pode utilizar con cualquier cosa que sea iterable. O cual traslada a la pregunta e que é algo que sea iterable, pues nos podemos ir na documentación, que é un iterable. E resulta que toda a resposta do universo non é tan só na Stack Overflow. Também temos documentación. E na el Glosario, bastante abandonado, non porque non é estén bien mantenidos, xin non porque nadie lo lee, resulta que nos explican que un iterable é un objeto que é capaz de devolver sumiembro, uno a uno, bla, bla, bla. E o importante é que temos que tener implementado un método mágico, o Eater o GetItem. Que bueno, para esta charla, vamos a centrarnos na Eater. É decir, que tenemos que implementar Eater. Muy bien, pues tenemos que volver a consultar na documentación e responder na pergunta e que é Eater. Por resulta que Eater é un método que é al que se llama quando necessitamos un iterador para un objeto contenedor. E nos tiene que devolver un novo iterador. Vale. Demosía o texto en el parfo. Dice, tienes que implementar Eater e tienes que hacer que devolva un iterador. E tu cada vez que utilices la función BuildIn, lexta te lenguaje, Eater se llamará, de forma implícita, a este método mágico. Vale. Eater, de hecho, resulta que é cierto, xin non me creais. Se tenemos una lista de números, un, dos, tres e imprimimos el método mágico Eater, non má pos todos os paréntesis porque non queremos llamar al método, solamente queremos ver que está aí. Nos dice, efectivamente, Eater é un objeto, é un método del objeto lista. Se utilizamos la función Eater sobre nuestra lista de números, nos devuelve un iterador. De hecho, se imprimimos o valor de It, nos dice, é un objeto, iterador de una lista. O sea que é cierto. Vale, muy bien, estamos devolvendo un iterador, pero ahora é outra pregunta e que é un iterador. Por resulta que para ser un iterador tienes que adecuarte a lo que se conoce como o protocolo iterador, también en la documentación. E eso significa que tienes que implementar dos métodos. O primeiro método tiene que ser una vez mágico Eater e tienes que, de hecho, la documentación nos dice, el iterador tiene que implementar el método Eater e que devolverse a sí mismo. Lo cual, de hecho, tiene sentido quando lo piensa un rato, pero a primera vez que nos encontramos con ele, é como, vale, lo que sea. O sea que tenemos que hacer unha cosa un pouco tonta e é esto, porque ahora estamos en nuestro... tenemos el objetivo de implementar nuestra clase iteradora. Entonces vamos a hacer esto, muy bien implemento Eater e devuelvo self. Puedo ser aquí instrucciones. E o segundo e o importante é que tenemos que implementar el método mágico next. E este é o método mágico que cada vez que nosotro trabajando con un iterador, o método e o seguinte elemento será llamado de forma implícita por el lenguaje. De hecho, nosotros tenemos unha función que é next e cada vez que nosotro o utilizamos sobre o objeto, iterador nos devolverá o seguinte elemento. Como o segundo frase, eu tampoco entendo, e este método mágico next con lo guiancitos bajos era o que en Python 2 que ya nadie usa, ni recuerda era .next. Así que lo podemos hacer. Vamos a hacer nuestra propia clase iteradora sobre o elemento de unos elementos que recibe quando se construye. Aí, en init, nos acordamos unha copia de elementos. Hemos hecho esa cosa que nos dijeron que nos entendemos en el fondo de que iter se devuelva a sí mismo e luego implementamos o método mágico next. E next, o que é xe cada vez que se llame, nos va a devolver un elemento. Como o hacemos? Muy bien. Devolvemos o elemento que corresponde ao índice, actualizamos o índice e no momento en el qual já nos hayamos pasado do top de objetos que tenemos vamos a devolver stop iteration porque ésa excepción en la que tenemos un iterador a avançar sempre cuándo no queden elementos. Así que non muy útil, pero hemos implementado o nosso propio iterador. De hecho, podemos ver que é cierto, perdón, voy a ir atrás. Podemos ver que creamos o nosso iterador ahí, decimos, mi iterador, trabajando sobre una lista e llamamos a next tres veces e cada una de las veces nos devuelve o siguiente elemento, un, dos, tres, la quarta vez, como no queden elementos, devolver stop iteration. Por supuesto, e mención obligada, next sólo se pode utilizar sobre o iterador incluso que no esta clase sea iterable, necesitamos un iterador para poder iterar sobre ella. Aquí, se llamamos muy convencido, next sobre a lista no funciona. Tenemos que hacerlo de sempre, tenemos que llamar a iter, iter no devolver un iterador e ya con o iterador podemos llamar next todas as veces que queramos hasta que alcancemos el final, stop iteration. De hecho, exactamente, éso é o que hace entre bastidores o buclefor. O buclefor hace exactamente éso. Ya utiliza iter, obtiene un iterador e entonces, de forma repetidas veces va llamando a next obteniendo o siguiente elemento hasta que finalmente alcanza stop iteration. Se quiséramos re-implementar sin ningún motivo justificable o buclefor e utilizar nuestro buclefor en vez de buclefor de Python podríamos hacerlo así, un while true en el cual vamos estar llamando a next hasta que la excepción nos haga parar e funcionaria. Também outra cosa que quando empezamos a leer surgís la duda, pero se o iterador va a lanzar una excepción como é que nós nos vemos la excepción? Pois porque for está escuchando de forma explícita a esa excepción. Quando for ve stop iteration para porque sabe que é a forma en la que nós señalamos que émos de parar. Pero por supuesto ese stop iteration solamente se considera un motivo de parada quando ocurre en el iterador cuando llamamos a next. Se dentro del cuerpo nosotros lanzaramos una excepción por supuesto que vamos a romper nuestro programa e outro desbio que son los generadores. Los generadores son unos tipos especiales de iteradores porque todos sabemos como todo o mundo sabe como funciona bastante tonto pero como funciona una función normal. Pois nós entramos en la función vamos haciendo ejecutando línea unas detrás de outras no orden muy secuencial e quando alcanzamos o final de la función devolvemos. Se tenemos un return devolvemos algo lo sabíamos pero nunca lo habíamos pensado una función todo o que hace tiene que devolverlo de golpe por exemplo aquí tenemos un único punto de salida entramos en la función ejecutamos a primera línea ejecutamos a segunda línea última línea e salimos o podemos tener múltiples puntos de salida aquí dependiendo del valor de la variable de entrada saldamos por un sitio por el primer retúrum o por el segundo a cosa es que una vez que alcanzamos uno de los retúrum saldamos de la función para nunca regresar en algo entonces esto non implícito nuestra función está devolviendo algo digamos agora que queremos trabajar con números pares queremos hacer una función que nos devuelva todos os números pares hasta un umbral stop pues podriamos decir muy bien puedo hacerlo versión tonto motivado que es creando a lista da mano nosotras o podemos utilizar range e generarlos todos la cosa es que tenemos un problema la lista que generamos la de generamos de golpe con lo cual sin algún momento queremos sumar un montón de números todos esos números pares no hay suficiente modulitos de RAM que podamos comprar para nuestro ordenador con lo cual no funciona esto se lo intentáis tarde o temprano o ordenador dirá memoria e erro si tenéis suerte a que condos utilizan os generadores os generadores son funciones mágicas porque o que pueden hacer é devolver valores de 1 a 1 o que hacemos é utilizar retúrum en vez de retúrum e isso significa que cada vez que llegamos a un yield devolvemos un valor e a función se queda con geladita formalmente un generador una función generadora devolve un generador un iterador un generador iterador un iterador generador pero é la práctica o que decimos que son generadores e bueno e a función generadora no devolve un generador por exemplo aquí este generador simple em vez de utilizar retúrum tiene gel 1, 2, 3 con lo cual podamos ver que quando llamamos a función nos devolve un generador e cada vez que llamamos a next no va devolviendo uno de los valores a primera llamada va a primer gel e a tercera e como todos os iteradores quando terminamos devolve stop iteration con lo cual agora podiamos hacer o que queríamos hacer de que nuestra función generadora devolve todos os números pares o bueno perdón todos os números naturales podiamos hacerlo porque ahora tenemos un while true dentro de nuestra función e pero nos devolve porque no vamos estar sempre aí dentro cada vez que alcancemos un yield nos vamos a quedar con gelados después de devolver ese valor e así podiamos llamar next indefinidamente se lo intentamos que una función normal nos funciona en resumen 10 minutos 56 segundos os iteradores son unos objetos sobre os cuales podiamos llamar next en lo único que nos importa los generadores devuelven alimento uno a uno e todo generador e un iterador pero non a viceversa por suposo también os generadores son un framework que nos simplifica nuestra vida en caso simples todo o que podiamos hacer con un generador podiamos hacerlo con un iterador un clase iteradora fea como lo que hemos visto antes que hiciera una identitlación ya está hecha por nosotras extra como medimos un generador nos podiamos llamar alen porque los generadores van devolviendo elemento uno a uno se lo intentamos nos dice type error entonces podiamos dicir bueno polo voy a convertir a lista lo converto a lista e então ya se pudo llamar alen sobre a lista problema uno es má estamos construyendo una lista temporal se tuvieramos muchos elementos no funcionaria una cosa que sei mucho un guión bajo para indicar que a convención según o estilo de que nos interesa ese valor realmente no estamos haciendo nada con x en el ejemplo de arriba se lo hacemos e o que estamos diciendo vale no me importa simplemente estou sumando 1 por cada cosa e que bien que hay agua e ahora eu quero hablar de números primos me encanta números primos e diría como determinamos os números primos pues en muchas formas porque o número primo que é aquel que só o tínia dos números dos divisores unos e sí mismo vale pues eu vou aprovar todos os demais números que estén entre perdón entre uns todos os números que estén entre dos entre dos e o número menos uno eu vou aprovar todos os posibles números se alguno de ellos divide a minúmerito n é que o número non é primo se non ningún divisor é primo por supuesto podriamos hacerlo así empezando con o nosso divisor desde dos pero hay una forma e funciona podriamos utilizar nossa función unha estimización obligatoria sin entrar en demasiadas matemáticas é que sólamente temos que comprobar os divisores até a raiz quadrada do número esto eu pongo sólamente como excusa para decir que sí podemos apagar a la complejidad de o de n e hay una explicación para humanos que é a única que entendi e con álgebra se pode demostrar que se não era o número primo te entrará um divisor por debajo de raiz e bueno vale então em mi range en vez de ir e já tengo minha superfunción e agora vou utilizar a función para factorizar o número primo é decir quero descomponer-lo em o produto de sus factores por exemplo 8 2x2x2 2 elevado ao cubo e unha vez má hay muchas matemáticas máis pero eu vou fazer por a forma mais simples que é o método de trair o divisor que é que vou ir probando todos os números primos e se um número primo divida o meu número é que é um factor e sigo así até que não me quede nada é decir vou a decir vou a empezar con todos pero bueno não queriam dividir o meu número por o que nós víttamos da raiz ногada então é que vamos começar p'en começar intento 1 quero un método que me se volvera um monte de números primos então vou começar con uma lista vacía e vou calcular números primos és decir dos primos sim vou a añadir a lista 3 primos e a añadir a lista 4 não eu vou ver o seguinte e quando tenho tantos número primos que quero los debo o problema Así que o que voy a hacer é muy bem, pues voy a utilizar un generador, que lo acabamos de apreender e, então, voy a ir doblando os números primos que necesito, uno a uno. Pero, aquí hay casi que dos cosas que podrian salir mal, porque estamos haciendo dos cosas a la vez, estamos llevando a cuenta de cuantos números primos hemos generado e de quál é o siguiente número primo. E en quantas máis cosas tengamos que pensar, é máis peligroso, que o loco le podria decir muy bem, hai un problema. Perdón, no podemos utilizar range porque range necesita saber dónde termina. Entonces, é donde podemos utilizar itertools, que era a excusa por la que venimos a esta charla. Itertools tiene un montón de funciones, unha télase is count, e count é un range sin cielo. Con count, o que hacemos é que le decimos muy bien, vas a empezar a contar a partir de aquí e en saltito de tanto que, por defecto, va a empezar a contar en cero como hay que hacer e va a ir de 1 en 1 e no va a devolver un interador. Cada vez que le demos a next, no va a devolver el siguiente elemento, es decir, range sin tope. Con lo cual podemos simplificar nuestro código un poquito porque o que podemos decir é muy bien, pues é esa lista de candidatos, o que vamos a hacer é por cada número in itertools count, va a ir recorriéndote número candidato e va a ir probando lo cada uno de ellos. Pero de nuevo, estamos haciendo dos cosas. Estamos en un mismo bucle foro bastante feo, estamos haciendo, generando números primos e estamos comprobando cuantos números primos hemos generado hasta la fecha. Vamos a hacer no cosos, vamos a partir nos trozos, vamos a hacer primes, que va a ser unha función generadora que nos va a devolver números primos uno de atrás de outro e ya lo que hagamos con éso valor que nos devuelva é outro tema e é o que hacemos en la segunda función. En la segunda función, o que vamos a hacer é decir, va a ir recorriéndote todos os números primos e va a ir llevando a cuenta de cuantos has devuelto, cuando devuelva lo suficiente, paras. De hecho, podemos simplificar la función de arriba aún má, podríamos utilizar unha función generadora, un generador por comprensión porque podemos decir, simplemente, dame todos os números que me vaya devolviendo eatertools count, pero solamente aquellos que sean primos o quizá incluso, este é uno de esos casos en los quales filter é aún má elegible, porque estamos simplemente filtrando unos valores sin hacer nada con ése, porque ese N for N, sempre un pouco raro, podemos decir muy bien para tamis simplemente aquellas valores que satisfagan esta condición. Con detalle histórico para a gente que esté en arqueología, eatertools filter e a gente que está en átertools pero nao náis recuerda país on dos, con lo cual podemos combinar-lo todo e hacer que nuestra función sea mucho má sencilla, vamos a decir muy bien, tengo unha serie infinita de números primos que é o que obtenemos con filter e... perdón, pero... que llevo quince, no? Eu eran 45? Eu sigo volando. No, é un detalle importante, pero no sé, se yo veis que eran 45 minutos. Vale, sí, vale igual, aquí tengo 17 que llevo 17, vale... espera, má, má, má... me rápido todavia, podemos a decir muy bien e da xou que me dicente que, bueno, tengo esa lista infinita de números primos e o que voy a dicindo con enya é que vou ir llendo a nex asa que eis tenido lo suficiente pero resulta que é xou un patrón habitual, é un patrón de éxte iterable dame tantos elementos e é xou no tenemos que hacer la mano quando é esta hechoo no sotro. unha secuencia normal, unha cadena, porque non sabemos cuánto alamento hay en un generador hasta que llegue o momento, con lo cual se intentamos utilizar nsos corchetitos nos va a decir type error, pero tenemos ice-lice e ice-lice es en el modulo iter-tools una notación de corchetitos, pero para cualquier cosa que sea iterable, incluyendo generadores e, por supuesto, como é moi vaga, lo vai evaluando todo uno a uno conforme va ocurriendo. Por exemplo, aqui le digo moi bien de aquella cosa que me devuelve iter-tools count dá-me solamente os cinco primeros, que é ese cinco que está como segundo argumento e vemos que, aunque iter-tools count non termina nunca el iterador que nos devuelve ice-lice sí termina e, por supuesto, funciona con todas as cosas que sean iterables, no solamente con generadores, por exemplo, aqui podemos obtener las primeras trasletras de una cadena o podemos, e por tua, la lógica habitual de que podemos empezar por outra cosa que no se acero o podemos ir dando saltitos que no sean de uno, como hacemos sempre, con lo cual, se queremos os primeros n números primos, o que podemos hacer, é decir, moi bien, pues, vou já tengo, una vez, de novo, tengo confilter, tengo milíster de números primos e o que voy a decir, moi bien, pues, quiero os 10 primeros, moi bien, ice-lice e dá-me os 10 primeros e funciona, con lo cual, podemos reescribir nuestra función e podemos decidir, moi bien, pues, voy a utilizar ofilter e voy a hacer por cada de esos números que hay en lo que me devuelve ice-lice, voy a hacer un yield de n e esto, pero esto se siente, é un pouco raro porque o que estamos haciendo é iterar sobre algo e, solamente, haciendo un yield e resulta que, para éso, entre outras cosas, se inventou yield-from. yield-from, o que nos permite delegar parte de un, permite que un generador delegue parte de súas operaciones a outro, delega, a outro generador, un sub-generador, é decir, cada vez que nuestro generador que utiliza next-from, escuche un next, o que va a hacer é, a súbez, preguntarle ao outro generador, oye, dá-me tu seguinte e va a devolver-lo directamente, é decir, nos estamos ahorrando ése bucle tonto de for n en algo yield-n, podemos decir simplemente yield-from. En este exemplo, tenemos spam e spam, realmente, não está haciendo nada, o único que está haciendo é delegando todo o trabajo a foo, con lo cual, quando eu llamo next en spam, a súbez spam, llama a, hace un next a foo. Con lo cual, no está, bueno, e, por supuesto, unha vez más funciona con qualquer cosa que é iterable, não só con generadores, con lo cual, se nossa función bocáles hace un yield-from de todas as bocáles, pues, bueno, cada vez que hagamos unha llamadita nos devolverá unha de las bocáles. Con lo cual, podemos reescribir nuestra función, simplemente, en dos líneas, o que antes era máceo, podemos dizer, muy bien, que estou haciendo? Componiendo o nosso trabajo en dos pasos, obtengo unha lista de todos os números primos e cojo os que me hacían falta. Paso 1. Oye, perdona, me podés confirmar que lo terminamos? 15. Vale, sí, sí. E eso seria dejando 5 minutos de preguntas, vale? Simón, te dores. Vamos, muy bien, no sobre tiempo está para 30 transparentes. E ahora, vale, e isto está muy bien, está todo super guai, 20 minutos aquí todavía não hemos hecho nada, porque o que queremos, nós queremos facturizar o número primo e para facturizar o número primo no tenemos que decir, dáme 5 números primos, o que queremos es decir, dáme todos os primos hasta esa raiz cuadrada, con lo cual, lo que tenemos que hacer é generar números primos hasta un umbral, e queramos decir, muy bien, dáme números primos hasta este valor. E, entonces, tenemos que hacerlo no llevando a cuenta de cuantos hemos generado, sino de quale é o valor actual. Con lo cual, tenemos que hacerlo así. Utilizo unha lista de números primos e o que voy haciendo é, muy bien, hemos llegado ya a ese umbral stop que nós habíamos pedido, e, xíno, é o caso continuamos, xíno, no te tenemos. E ese é outro patrón habitual? É decir, estamos iterando sobre algo hasta que unha condición deje de cumplirse. En este caso, por exemplo, que seamos menores ou iguales que esa xí. E eso é take while. Take while é o que hace devolver, unha vez más, como todo un iter tools, devolver un iterador, que é o que hace é que para de recorrer elementos sobre o que é, o que tiene como entrada en el momento en el qual a condición ya no se cumple. Non xíno, solamos operarlo mucho utilizando junto con funciones landa. Por ejemplo, aquí, lo que tenemos é numbers, que é un montón de números, e o que le estamos diciendo é, muy bien, coge números, sempre e cuándo sean menores que 4, landa xíno, xíno menor que 4. Logo, significa que o primeiro é que chamamos a next, que va a ver take while, va a ver 1, e 1 é menor que 4, con lo cual, lo devuelve. Lo mesmo ocurre con 2, con 3, pero talo temprano llegamos a 4 e 4 non é menor que 4, con lo cual, hemos terminado. E como todos os iteradores, no é nada que devolver, e, então, nos devuelve esto apiteraísimo. Por supuesto, as funciones landa non son obligatórias, e tu éramos unha función que hiciera casualmente o que necessitaramos, como por exemplo, aquí, unha función que nos dijera xí un valor é menor que 10, podriamos utilizar-lo e función é igual. Solamente vamos estar en los números que cumplían la condición. Una vez que llegamos ao tope, paramos. Con lo cual, nuestra versión kung fu de lo que queríamos hacer é simplemente 2 cositas, nuestra lista infinita de números primos e nuestro yield from de lo que nos devuelve take while, onde compravamos que nos hemos llegado todavía al valor tope. E por cierto, o que é o opuesto? O opuesto é drop while. Drop while, o que hace é que vai ignorando todos os elementos até que chega a un punto en el qual a condición ya no se cumple. E, en ese momento, a partir de ese momento, o devuelve todo. É decir, o utilizamos para ignorar a parte del comienzo de un iterador potencialmente infinito. Por exemplo, aquí tenemos un montón de números de novo e o que le decimos é muy bien. Vas a ignorar todos os números que son menores que 4. Então, eu digo drop while, es decir, descarta elemento mientras que, e con a función landa, o que estamos viendo se os números son menores que 4. Con lo cual, a primeira é que chamamos a next, que va a ver drop while, va a ver un 1 e, então, como 1 é menor que 4, o va a ignorar. Luego, a lo mismo, con 2, con 3. E, quando llegamos a 4, digo, 4 é menor que 4. Con lo cual, já aquí é a condición, ya no se cumple e já puedo dovar todos os elementos. E já devolverá 4, 5, 6 até infinito. Combinando las 2, podriamos hacer unha cosa, unha maja, que é que podriamos generar todos os números primos dentro de un rango. Por exemplo, cojo drop while para descartar todos os números primos hasta llegar ao comienzo en el que queremos empezar a ver números primos e o iterador que me devuelve se lo passo a take while hasta llegar ao tope e, se tenamos, hubiéramos unas palavras por defecto que fueran 2, que é o primeiro número primo e infinito, podriamos hacer que a nossa función nos diera solamente números primos en un rango que quisieramos. Por supuesto, empezando desde donde quisieramos e terminando donde quisieramos. E ahora, isto que decíslo, é obligatorio. Qual é o algoritmo de factorización de números primos? O que vamos a hacer é que vamos a ir iterando sobre todos os números primos e se en algún momento é divisible o número sobre ese número primo, p é un factor, entonces lo guardamos e, basicamente, iteramos de forma recursiva. O caso base é que no nos quede nada ou o número que nos quede ese primo e, então, é ese outro factor. Não temos que entrar nas detalles, pero, por exemplo, tengo 30, empiezo por o primeiro número primo con o primeiro número primo 2. É 30 divisible entre 2? Sim. Então, 2 é un factor, hago a división e, então, me queda 15. Então, agora e, pero, lo hago de forma recursiva con 15. 2 no divide, pero 3 sí, e, por exemplo, me queda que, efectivamente, tenemos todos os factores dos números primos. Por exemplo, o podriamos hacer elegantemente con nuestra función basada en iter tools de primes until e podriamos hacerlo así. Como estamos utilizando recursividad, o que hacemos é que cada factor que encontramos lo metemos en una listita que encadenamos con a lista que nos va a devolver a llamada recursiva e, así, con toda a llamada recursiva encadenando listas obtendremos a lista con todos os factores e, no sé, para que se poda utilizar, pero é está. O comando Unique, vamos, muy bien de tiempo, o comando Unique é de esas cosas que te encuentras quando, en esta cobre flow, te dicen, se hace así, elimina líneas duplicadas que estén consecutivas en un fichero, o que reciba por entrada. O tipo de como elimino líneas duplicadas de un fichero en Linux te dicen sort menos u o sort e se lo pasas a Unique. É decir, que como a, a, é tan consecutiva e son, básicamente, a la misma línea que se queramos, queramos a hacer ésto. E, por simplificada, vamos a decir, vale, solamente quero acestar cadenas como entrada. Pois, se quiséramos hacerlo, tendríamos que decir, vale, una de las formas hay otras, posibilmente má rapidas, pero una que se pude entender sin morir en el intento seria muy bien. Voy a llevarla cuenta de cuáles son, cuáles son mi resultado para cada nueva letra que veo en la cadena, lo que voy a deciré, voy a ignorar, voy a ignorar la letra se é igual que la última que ya tengo el resultado. Una vez que termino, es como una línea, porque tenemos group by, e group by es lo má difícil de entender estas charlas, porque group by, al principio, en esas cosas que o documentación é completa, non é muy amigable para principiante. Group by, o que hace devolver un iterador que nos da grupos consecutivos de clave e valor, donde un grupo empieza cada vez que el valor de la clave cambia. Lo vamos a entender ahora. A su vez, los grupos objetos que no te vuelve, esos grupos son unos iteradores. Es decir, a, b, c, c e digo, vamos a grupar, vamos a hacer o grupito de esta cadena e imprimo grupos, país nos dice es un group by object. Gracias país. Muy claro de todo. E a la jamonext, jamonext e nos devuelve o primeiro grupo e a primera clave. Qual é a primera clave? A, porque é o que é neste grupo e que é group. O bueno, nos dice que é un objeto grúper, o sea, tampo que me é quedado muy claro, pero sí jamonext, porque sé que é un iterador, veo que tiene nada claro. O que pasa é que cada jamonext está devolviendo dos elementos. A clave é o que o grupo contiene e o grupo é a ocurrencia. Quantas veces é a coisa que a clave aparece? Por exemplo, con b, le digo muy bien, qual é a clave do segundo grupo? Opa, me dice por b, é decir, este grupo tem bs e quantas ocurrencias deve, ai, que é a outra forma de ver-lo, solamente hay una, con o qual grup, mesmo con c, solo que c resulta que tiene 3 c's. Quizá é uma forma má fácil de visualizar-lo, é así, algo utilizo um bucle for e vou ir recorriéndolo e o que digo é muy bien, pues para cada clave e para cada grupo, impriame a clave, impriame o grupo e pode o ver que hai 3 grupos que tienen a, b e c e podamos ver que o grupo tem a ocurrencia do mesmo. É o que parece muy tonto, pero é superpotente, aunque não o parece ao principio. Por exemplo, nesta función kung fu de esta eliminación de duplicados contra o tramo e ignorar a ocurrencia. Que má me da que halla 3 c8 o 15. O único que quero é 1 por cada, solamente quero 1. Así que cojo a clave e las concateno todas con un join e he terminado. Incluso o poderemos hacer en unica línea, se lo preferimos, con una lista por, bueno, utilizándolo para como entrada al join. É toda una pregunta habitual en algunas entrevistas de trabajo. Se encuentran Internet e se o pones. E é, há un algoritmo de 3 as, quero que devuelva a3. E se tengo 1b, quero que devuelva b1. Queremos hacer isto. Como o hacemos? Bueno, pues, unha forma que nos llena de dolor, sufrimiento e lágrimas é hacer un monstruo como éste. Porque é muy feo, pero realmente é que não há outra forma de hacerlo. Porque tengo que llevar en la cuenta de quál é o grupo en el que estou e quantas palabras he visto hasta a fecha e cada vez que veo unha nova ocurrencia tengo que incrementar o contador. O último grupo aí é a línia justo antes do returm e ao final o combina e o devuelva todo. E é isto, como é isto, não se va a ocurrir na entrevista, pues sangre e dolor e lágrimas. Pero quem conoce Itertools hace unha coisa máis sencilla e é que dice máis bien se é que está todo hecho por mim. Solamente tengo que coger a clave e que quantas ocurrencias queres, que me ha dicho que cuente quantas ocurrencias e máis bien. Tengo o grupo, e grabbed o cacate todos e o ázienakre e o logismo functiona. A coisa e sobre shops group third está comparando tel channels porque estamos comparando as coisas como homen… xa é xass em base a outros c tipo e de sínsa e igualdad Xempo, moi bien. Esta é o criterio em base ao qual va a ordenar. Por exemplo, quiero agrupar letras por longitude. Tengo una serie de palabras e quero que azul e gris en inglés estén juntitas, estén emparejadas porque tienen las 2, 4 caracteres. Pois podremos hacerlo e a unha solución moi digna, tengo unha tabla hash, un dicionario en Python e o que vou a hacer é que, bueno, para cada palavra comprobo su longitude, vou a esa clave e añado a palavra allí. Sí, pero tenemos a versión kung fu. La versión kung fu é que le digo moi bien, va a agrupar todas las palabras en base a que criterio, su longitude. E ya está. 2 notas de mención obligada. Primero, tenemos que ordenar a lista antes, sino solamente funcionaria se estamos agrupándolo, se estuvieran contigua, de lo mismo modo que si es un fichero de Linux, hay que hacer short antes de ordenarlo la terminal, de eliminarlo lo duplicado. E tambien que esta solución é cierto que é la complejidad en el logaritmo de n, porque é unha llamada un logaritmo de ordenación, pero yo argumentaria que sí podemos permitirnos lo en mucho más legible, porque de hecho que estamos diciendo en lenguaje casi natural lo que queremos hacer, estamos diciendo agrupa esas palabras en base a un criterio, qual es el criterio, la longitude, a un más chulo, matemáticas. Los que esteis cerca de la porta podeis seris corriendo. Digamos que tenemos esta función que hemos encontrado na internet sin saber o que hace e como não queremos pensar, utilizamos numpy e podemos incluso imprimirla, podemos crear o objeto polinomio e podemos ver que é o que hace. E resulta que a función tiene esta forma en este rango arbitrariamente escogido. E não tenemos ni idea de o que é, pero como é un ejemplo vamos assumir que é tiempo versus algo verdaderamente importante. É algo muy importante que estamos monitorizando e que não podeis salir mal e estamos en el trabajo e queremos que suene un alarma se en algún momento hemos pasado má de tres segundos por debajo de ese valor cero de algo muy importante. Tenemos un compañero que está fazendo esto o outro dia, foi un super ejemplo. A mano é muy fácil porque podemos ver que entre cero e tres básicamente aí estamos má de tres segundos debajo de cero. Pero como hacemos eso em código? Para simplificarlo podemos assumir que solamente vamos evaluar en los enteros. Con lo cual podemos reformular a pregunta. Hemos estado tres o má... Hay tres o má valores seguidos aqui en esta lista de valores que tengan signo negativo. É realmente muy simples. Porque o que podemos decidir é muy bien porque vamos agrupar estos valores en base a un criterio. Qual é o criterio? Não é o valor dos valores per se, sino simplemente seu signo. É decir, se o criterio, ese argumento aqui, é simplemente era negativo o non, que será en cada momento a clave? Pois a clave que aqui hemos llamado é negativo, a clave nos dira verdadeiro o falso. En función de se o valor de la clave para éso elemento é verdadeiro. É decir, como este grupo só o tiene número negativo será verdadeiro, como este grupo o tiene positivo será falso e logo ya en group tendremos os valores por si mesmo. Con lo cual, si tramos podemos decir, muy bien, se en algún momento a clave é negativa e tenamos má de tres valores, pode ser que suene o alarma e funcione. E funcione. Aunque nós, por supuesto, dijemos, boa, esta é un xeta línia de código, pero por lo menos está em Marta e já no hacemos nada. E... Estos estavam na propuesta de charla, así que hai que incluirlo. Como alteramos indefinidamente entre un montón? Tenamos 10 minutos. Vamos super bien. Como alteramos indefinidamente entre os dois valores, menos 1 e 1? Por a versión completamente principiante, de que salpica sangre así a la primera línia de asistente, digo mo, un bucle wild e para cada uno de los valores, pues quando tengo un 1, paso a menos 1 e quando tengo un menos 1, le asigno el outro valor. E, bueno, isto no é buena ideia ejecutar esto. Una versión un poquita menos principiante é que no tenemos que ir asignando manualmente menos 1 e 1, o que podemos decir é, bueno, multiplico por menos 1, porque resulta que así nos iremos directa... iremos cambiando el signo multiplicando por menos 1. Pero sigue siendo mala ideia porque un bucle wild, básicamente allí pega o nosso código. La versión estava prestando atención, con lo cual se qua a la respuesta, é, por supós, utilizar un generador. Podríamos utilizar ese bucle wild orrendo, podamos ponerlo dentro de una función generadora, e entonces ya no tenemos ningún problema, porque no vamos ejecutar o... ese bucle wild no va intentar ejecutarse hasta el infinito. Simplemente se congelará hasta la siguiente llamada next. Con lo cual, no estás llamadas a next, vemos que efectivamente funciona e nos va alternando entre 1 e menos 1. Pero, bueno, que tenemos la versión kung fu. La versión kung fu é unha unha que é a llamada a psycho. Que é o que haces cycle? Psycho é o que haces de devolvernos un iterador... o que nos haces unha em mano, devolve un iterador que... guarda unha copia de todos os valores que hemos visto. E unha vez que nos quedan más valores que devolver, ya o que va haciendo é dar vueltas sin fin sobre o que le dimos. É decir, no é unha noria. Por exemplo, aquí, se estamos dan ciclando sobre las vocales, vamos recorrenos todas las vocales e unha vez que llegamos a la última, vamos empezar outra vez por la primera, ad infinitum. Como é esto o generador infinito para non morir o que hice foi utilizar e slice para solamente imprimir 10. E vemos que efectivamente damos un par de vueltas. Por supuesto, hemos dicho, devolve unha copia. Por exemplo, aquí, aunque estamos haciendo o cycle sobre o generador por comprensión, que, quando llegue ao final, ya no va a tener más valores, vemos que, aunque las llamadas a ese generador no funcionan ya, no dan un stop iteration porque ya no queda nada, cycle aguarda unha copia, con lo cual podemos seguir, no tenemos que preocuparnos porque pasaba con o argumento de entrada que le dimos. E ahora a cosa es como interamos sobre dos o máis iterables. Digamos que estamos jugando a Skerbal Space Program e queremos así hacer unha cuenta muy rara de lanzamiento. Queremos ir hasta 10, perdón, sí queremos ir hasta 10 e luego bajamos, pero luego realmente no llegamos a despegar nunca e volvemos outra vez a 10. Queremos ir de 1 a 10 e de 10 vuelvo a bajar hasta 1 e subo e estamos haciendo ésto. Voy a pasárselo a cycle, por resulta que no funciona porque cycle solamente acepta un iterable. De hecho, por extensión a la pregunta la podemos reformular como iteramos sobre dos iterables. Tenemos que encanenar dos bucles 4. Tengo 1, 2, 3 e todas las bocales. Quero imprimir-lo todo por pantalla. Cómo lo hago? Dos bucles 4. Resulta que tenemos chain. Chain lo que hace de devolver un iterable que nos va devolviendo cositas a cada llamada del primer iterable una vez que no quede nada en el primer iterable se moverá al segundo, etc. Con lo cual estamos efectivamente encadenando todos os iterables e así podemos simplemente con o único que ha llamado un único bucle 4 podemos recorrer-nos-lo todo. Regresando al ejemplo que teníamos se generamos las dos secuencias de número de 1 a 10 e luego es decir, hacia arriba e hacia abajo podemos simplemente encadenarlas e se lo pasamos éso ya sí que a un iterador como argumento a cycle pues funciona e podríamos generar infinitamente éso o número. E ya o último azar se tiramos dos dados de 6 caras cuantas combinaciones aí pues ah, éso é o producto cartesiano me acuerdo do instituto éso é un bucle 4 anidado me recorro para generar son todas las parejas de baile en una fiesta, ¿verdad? un 2 bucle 4 complejidad quadrática me recorrer la primera serie me recorrer la segunda e lo combino todo e éxito te dice muy bien e se son 3 dados e tu dices 3 bucles 4 e resulta que éso generalizar-los é muy feo de éxito en un momento 3 dados que no sabes cuantos van a ser non se hacerlo de hecho se pode hacer con recursividad que o que tenemos que hacer é que para cada elemento tenemos que generar recursivamente todos os subproductos e lo vamos encadenando todo en un monstruo e la versión iterativa é bueno eu me decante por é decir é muy feo implementar éxito é esta é a solución sencilla pero bueno pero ao menos funciona é decir se tiro aí por exemplo aqui tenemos 3 dados e entonces veo que é se tiren dados dados que son 3 listas de 1 e 6 pois funciona pero é que resulta que tenemos product em iter tools podemos é un iterador que não pode valver o producto cartesiano de todos os argumentos de entrada se queremos calcular o produto con nosotros mismos o que hacemos é simplemente utilizar repeat por exemplo aqui 1 e 2 ou en una lista e a b o que hace efectivamente calcular no o producto de as 4 as 4 combinaciones que tenemos 1 a 1 b 2 as a 2 b não temos que repetir o argumento de entrada se son o mesmo se queremos tirar solamente 2 dados pois o que le digo é muito bem pois então eu utilizo repeat 2 e então é efectivamente estamos tirando 2 dados não é que ni xiquera temos que repetir 1 pergunta tonta pero é fácil agora que sabemos un montón de iter tools um 5 sumando todas as suas caras pois vamos tirar primeiro 4 dados utilizando o produto cartesiano e vamos hacer um filter para coger solamente aquellos que cumplen aquellas combinaciones aquellos resultados vamos coger aquellos resultados en los cuales a suma com una función enlanda é exactamente o valor que queremos que é 5 e bueno pois a única combinación que temos a única forma que é de que não salga un 5 e um 3 um 1 e o outro 3 como último exemplo nós estamos trabalhando com pixels temos un montón de pixels na nossa pantalla e queremos hacer algo con éxito quero encapsular o concepto de pixel o que hago pois vou crear o pixel e tenho o construtor em init onde guardo fila e columna e como quero poder imprimir o por pantalla utilizo um wrapper e então já posso ver o por pantalla isto é muito habitual e a coisa que podemos usar de livro em que podemos utilizar um námex tuple do módulo colección um námex tuple porque isto de aqui antes é muito trabajo redundante é muito tonto porque o único que estamos haciendo no construtor é guardar valores é o mesmo nome e x e o guardo en x e o guardo en e e é um pouco aburrido pois podemos simplificar um montón o trabalho já está hecho se utilizamos um námex tuple que podemos utilizar sempre quando serva se que na nossa classe se é mutable podemos despacharlo com um námex tuple porque nos dá init, nos dá wrapper e outras cuantas cosas é decir aqui pudo crear um námex tuple um námex tuple um námex tuple um námex tuple um námex tuple que se chama pixel e que tiene dois atributos dois miembros fila e columna e isso ya não te vuelve pixel o da esquerda que é um objeto que é a nova classe que podemos utilizar para instanciar um novo objeto e o temos já hecho por nós se queremos añadir um método podemos utilizar algo que hemos hecho antes pero en vez de terminar pongo dois puntitos e então pudo añadir mis próprios métodos via herencia por exemplo aqui para calcular a distancia euclidia entre dois puntos e agora o que eu queria hacer con mi muchos píseles era calcular todos os vecinos es decir eu tenho um píssel e quero un método que me vuelva os ocho vecinos porque me podemos ver hacia arriba abajo e en las 4 esquinas então como lo hago o bom e o primeiro intento e isso sí e digo moi bien porque vou crear eu a mano todos os vecinos e isto é um montón de trabajo para tan poquitos para tan poquitas funcionalidades porque o que podemos hacer en vez de pensar en términos de instanciar nosotros manualmente cada uno dos objetos porque não criamos os objetos em um bucle for utilizando desplazamientos en vez de nós pensar en que temos que añadir o que vou fazer calcular o produto cartesiano dos desplazamientos posibles porque en todo momento solamente me voy a oer o menos uno em cada uno dos ejes utilizo mi repeat 2 tenho que tener en cuenta que hay una combinación que é 00 na qual não me estimo viendo e seria de volver o mesmo pixel con o qual ese caso lo ignoro e é moi fácil ventaja añadida se algun dia nos movemos a una pantalla de ordenador tridimensional creo que se não tenio sentido podriamos cambiar simplemente o repeat poner un 3 e podriamos calcular desplazamientos também en z para puntos extra não escribimos a mano porque aquí estamos diciendo creame un novo objeto de la clase pixel quando hacemos o yield isso tem o inconveniente aunque sea pequenito de que estamos escribiendo de novo o nome de la clase con o qual se algun dia renombramos a clase tendríamos que ir allí e cambiá-lo também podriamos utilizar type e se é a primeira línia de la función decimos type de self que é non para de volver é o non para de volver é a clase de... é o non para de volver é a clase que estamos exactamente e podriamos utilizar esa variable cls para instanciar os novos objetos pero isto é para puntos extra simplemente para despedirme queria decir que hemos visto un montón de material un montón pero realmente en el fondo solamente hemos rascado a superfície porque Territools tiene un montón de cosas e podriamos seguir hay una hay una en la documentación hay una parte de recetas e hay infinitos ejemplos nos cuales nos simplifica un montón un montón en la existencia e o último resulta e isso também minha documentación no ningún secreto que todos os bloques que nos da Territools realmente están inspirados en lenguajes como Haskell de hecho todos os ejemplos de las transparencias tienen un paralelismo directo en este caso aquí Haskell con lo cual estávamos aprendiendo Territools estávamos estamos en el EuroPython pero realmente lo que estávamos aprendiendo era programación funcional que é básicamente outro paradigma que estávamos acostumbrado así que a reflexión un pouco tonta é que quizá se não habéis echado un ojo a la programación funcional porque asusta un montón se o meteis la Wikipedia e habis la definición de las monadas la vuelve a leer e acaba cerrando o navegador porque no lo entiendes então é intimida un pouco pero é un é un é algo sí como que abre un momento un poquito ojo que é o que a gente de Haskell eba haciendo a décadas era unha única línea e parece que é mucho má listo de o que era realmente así que quizá me habéis que a la pena e muchas gracias se hai alguna pregunta creo que nos queda un poquito de tiempo ua o que grácia el pictor lamento a la confusión en cuanto ao tiempo a culpa foi minha graces por tu comprensión alguien desea ser una pregunta tenemos un por de minutillos por aí que miedo me da esto ahora sempre nada sólo por curiosidad se se filter o que antes conocíamos como a filter porque slice no es lo que antes conocíamos como a slice perdón a última frase porque a filter a anterior e a filter e estava en el módulo aiter tools e porque slice no es o que o que no existe un o que slice no devolve iteradores en paixón 3 porque a ver porque en la antigüedad filter hacía no era lazy no era pago e devolvava todo de golpe entonces como hacía falta una versión que no hiciera esa cosa então en el módulo aiter tools se añario pero quando a los primigenios hace ya miles de años abandonaron o viejo mundo decidieron que filter ya iba a portarse bien tu toda a tu vida has conocido filter como deve ser pero filter antes era feo então agora a filter funciona de forma igual que zip e porque slice no porque slice sigue abandose a slice vale porque es una buena pregunta que en cuanto baje de aquí se da super tonta das colas respuestas no porque vamos a ver porque slice las slice funcionan con secuencias donde esa outra cosa del glossario las secuencias son todas las cosas que podemos acceder aleatoriamente uno de as un miembro se suporta é o get item es decir se yo puedo decir da mil cuarto elemento en paixón daré una secuencia como un canal de texto o una lista etc. entonces para que funcione tú te refiere a que por que no está funcionando de forma vaga slice perdona a notación con los corchetitos porque no sempre nos sirve porque porque la pega que tiene slice es que no se tú con slice le dices dame el elemento cien mil millones el pobre slice tiene que es decir empieza por aí tú le dices empieza a contar a partir de el cien mil millones el pobre slice tiene que recorrerse uno a uno todos os demás porque no tiene acceso aleatorio tiene acceso secuencial para hacer isso tendría non seria tantanio como cí lo es trabajar agora con os corchetes cuándo queremos por exemplo ocwolitalar tensemos que tenemos que recorrer todos os elementos e temos que armazenar a memoria, coa o cual é o caso que lo digo mucho, pero que non ocurre nunca, que tengas muchos números, e luego dejando de lado o consumo de memoria extra, que poderia ser un problema, está... bueno, hay un detalle secundario que é que se lo convierte da lista, obviamente o generador é un solo uso, é un camino, solamente se pode recorrer unha vez, que é unha pega quando a gente quiere, por exemplo, pasa con en los casos do group buy, que a gente dice, quiero ver cuánto elemento hay en el grupo, e dice, muy bien, pues lo convierto a lista e llamo a len, pero se é xa non lo guarda en unha variable, ya te ha gotado o grupo, porque o grupo, es decir, se va, tenas que hacer algo en ese grupo, se queramos para el número de elemento de un generador e hacemos el truquito de llamo a sum, pierdo los valores, con lo cual tengo que guardar-los se lo necesito. La única pega é que tenas que guardar a memoria, respondiendo a la pregunta. E outra pregunta, el group buy, cuando haces, por ejemplo, a comprensión del string, ganas con group buy o que ganas con una expresión regular. A parte del dolor de escribir la expresión regular. Que sí ganas en... En coste computacional. Uu, no tengo seguramente ni idea, pero me gustan las cosas. No, no, me gustan mucho las... Hay gente que la odia, me gustan mucho las prisiones regulares, pero no sé que seria má rapido. Creo que seria má legible, se lo pode hacer con group buy, porque era a grupa, por longitu, pero no lo sé, no lo sé. Gracias. Hay la última pregunta para dejarme mal. Llevas seis meses pensando, lá. No, pero vamos a averigua. Vale, muchas gracias. OK, gracias, Víctor, por estar. Interesante, ponencia.