1 00:00:00,000 --> 00:00:03,416 [MÚSICA DE FONDO] 2 00:00:03,416 --> 00:00:10,248 3 00:00:10,248 --> 00:00:11,340 DAVID MALAN: Muy bien. 4 00:00:11,340 --> 00:00:15,750 Estamos en CS50 y este es el día previo a nuestra prueba. 5 00:00:15,750 --> 00:00:17,700 Esta es la lección 8, en la cual entraremos 6 00:00:17,700 --> 00:00:20,490 por fin en la transición de C, este lenguaje de bajo nivel 7 00:00:20,490 --> 00:00:22,470 al que dedicamos bastante tiempo. 8 00:00:22,470 --> 00:00:25,470 El objetivo de hoy no es enfocarnos en Python como tal, 9 00:00:25,470 --> 00:00:28,770 honestamente, esperamos que sea uno de los aspectos que más fortalezcan 10 00:00:28,770 --> 00:00:32,720 al curso, es decir, enfatizar que este no ha sido un aprendizaje semestral en C, 11 00:00:32,720 --> 00:00:34,830 sino un semestre en el que aprendimos programación, 12 00:00:34,830 --> 00:00:37,770 un tipo de programación llamado programación imperativa o por procedimientos. 13 00:00:37,770 --> 00:00:40,080 Pero quizás verán más sobre esto en otro curso de programación de alto nivel. 14 00:00:40,080 --> 00:00:42,990 En este curso se trata, básicamente, de enseñarles 15 00:00:42,990 --> 00:00:45,330 a aprender nuevos lenguajes por sí mismos. 16 00:00:45,330 --> 00:00:48,540 De hecho encontrarán, mientras exploramos algunas características 17 00:00:48,540 --> 00:00:50,750 y la sintaxis de Python, que probablemente les parecerá 18 00:00:50,750 --> 00:00:53,876 tan complejo como les parecía C hace algunas semanas. 19 00:00:53,876 --> 00:00:56,250 Pero una vez que comiencen a reconocer los patrones, 20 00:00:56,250 --> 00:01:01,410 como lo hicieron con C, todo será más accesible y más útil 21 00:01:01,410 --> 00:01:03,370 para la resolución de problemas. 22 00:01:03,370 --> 00:01:07,770 No está relacionado, pero al inicio de la semana estaba en Mountain View 23 00:01:07,770 --> 00:01:08,790 con parte del equipo. 24 00:01:08,790 --> 00:01:11,730 Y tal vez recuerden que en la última conferencia en Harvard 25 00:01:11,730 --> 00:01:15,210 les ofrecimos una vista de los primeros racks de servidores 26 00:01:15,210 --> 00:01:16,740 que tenía Google. 27 00:01:16,740 --> 00:01:18,690 Bueno, resulta que se mudaron de edificio 28 00:01:18,690 --> 00:01:21,780 y nosotros nos topamos con toda la exhibición. 29 00:01:21,780 --> 00:01:24,390 Así que esto que les muestro es una foto que tomé con mi propio teléfono 30 00:01:24,390 --> 00:01:26,080 y verlo fue realmente genial. 31 00:01:26,080 --> 00:01:29,552 Pueden ver en el interior los viejos discos duros que utilizaban 32 00:01:29,552 --> 00:01:31,260 y también pudimos observar algunas de las etiquetas. 33 00:01:31,260 --> 00:01:34,120 Y de hecho, los discos duros se fabricaron en 1999, 34 00:01:34,120 --> 00:01:36,540 que es cuando Google comenzó a obtener algo de su impulso. 35 00:01:36,540 --> 00:01:38,290 Aquí pueden ver las tarjetas verdes de circuitos 36 00:01:38,290 --> 00:01:41,190 de lo que probablemente serían los CPU y otras cosas. 37 00:01:41,190 --> 00:01:43,170 Así que si quieren recordar viejos tiempos, 38 00:01:43,170 --> 00:01:46,920 no duden en leer sobre esto en Wikipedia o incluso en los fragmentos que ven aquí. 39 00:01:46,920 --> 00:01:50,480 Y entonces, curiosamente, en la conferencia en la que algunos estábamos 40 00:01:50,480 --> 00:01:54,150 descubrimos esto, quizás sea el mayor pato depurador que se haya creado alguna vez 41 00:01:54,150 --> 00:01:58,410 a partir de depuradores de pato más pequeños, uno de los cuales era nuestro. 42 00:01:58,410 --> 00:02:00,780 Y eso fue lo que vimos la semana pasada. 43 00:02:00,780 --> 00:02:01,440 Muy bien. 44 00:02:01,440 --> 00:02:03,981 Entonces, ¿qué vamos a hacer esta semana y las que vienen? 45 00:02:03,981 --> 00:02:06,660 Recordarán que cuando hicimos la transición de Scratch a C, 46 00:02:06,660 --> 00:02:09,279 hicimos un par de comparaciones entre la sintaxis y las características. 47 00:02:09,279 --> 00:02:11,820 Y pensé que sería útil adoptar aquí la misma perspectiva 48 00:02:11,820 --> 00:02:14,910 para enfatizar que la mayoría de las ideas que hoy exploraremos 49 00:02:14,910 --> 00:02:15,940 no son nuevas en sí, 50 00:02:15,940 --> 00:02:17,850 solo se trata de cómo las expresamos y cómo 51 00:02:17,850 --> 00:02:20,670 escribimos la sintaxis en el lenguaje conocido como Python, 52 00:02:20,670 --> 00:02:23,730 la cual será diferente a la de Scratch o a la de C, 53 00:02:23,730 --> 00:02:25,290 y ahora aquí estamos con Python. 54 00:02:25,290 --> 00:02:30,240 Y si se acuerdan de la semana 0, cuando querían decir algo en Scratch, 55 00:02:30,240 --> 00:02:32,980 utilizaban esa pieza púrpura del rompecabezas para decir hola. 56 00:02:32,980 --> 00:02:35,210 Y la llamamos una función o una declaración. 57 00:02:35,210 --> 00:02:36,681 Era una especie de acción verbal. 58 00:02:36,681 --> 00:02:39,180 Y en C, por supuesto, se parecía un poco a algo como esto. 59 00:02:39,180 --> 00:02:43,180 De ahora en adelante, a partir de hoy, se verá así en Python. 60 00:02:43,180 --> 00:02:45,330 antes y después, 61 00:02:45,330 --> 00:02:47,010 antes y después. 62 00:02:47,010 --> 00:02:49,360 Es bastante fácil diferenciar visualmente estas dos cosas. 63 00:02:49,360 --> 00:02:50,760 Pero, ¿cuáles son las dos diferencias 64 00:02:50,760 --> 00:02:52,350 que de inmediato nos saltan a la vista? 65 00:02:52,350 --> 00:02:54,400 C, Python. 66 00:02:54,400 --> 00:02:57,216 67 00:02:57,216 --> 00:02:59,840 Al parecer, ya no hay \ n en este contexto, 68 00:02:59,840 --> 00:03:02,340 así que es un alivio no tener que escribirlo más. 69 00:03:02,340 --> 00:03:04,440 ¿Qué otra cosa parece diferente? 70 00:03:04,440 --> 00:03:05,590 No más punto y coma, gracias al cielo. 71 00:03:05,590 --> 00:03:06,090 ¿Cierto? 72 00:03:06,090 --> 00:03:07,740 Tal vez sea la fuente de frustración más tonta 73 00:03:07,740 --> 00:03:10,323 que hayamos experimentado al omitir uno de esos. 74 00:03:10,323 --> 00:03:11,778 ¿Alguien más por aquí? 75 00:03:11,778 --> 00:03:15,950 Sí, que printf ahora solo es print, lo cual, de por sí, es bastante razonable. 76 00:03:15,950 --> 00:03:18,180 Son diferencias sumamente pequeñas, 77 00:03:18,180 --> 00:03:20,810 pero son una especie de testamento de los ajustes mentales 78 00:03:20,810 --> 00:03:22,080 que tendremos que hacer. 79 00:03:22,080 --> 00:03:24,630 Por fortuna, hemos visto que podemos dejar estas cosas 80 00:03:24,630 --> 00:03:27,963 y este es el principio básico de Python, ya que uno de sus objetivos es que 81 00:03:27,963 --> 00:03:31,440 sea más fácil de escribir que algunos de sus predecesores, entre ellos C. 82 00:03:31,440 --> 00:03:35,499 Así, podríamos implementar en C este hello, world, en el programa que 83 00:03:35,499 --> 00:03:38,790 se ejecutó al hacer clic en la bandera verde, con un código como el de la derecha. 84 00:03:38,790 --> 00:03:41,730 Y para aquellos que no tenían experiencia en programación, esto significó llegar 85 00:03:41,730 --> 00:03:44,730 a CS50, a lo que probablemente se veía como el idioma griego para ustedes, 86 00:03:44,730 --> 00:03:46,260 hace solo unas semanas 87 00:03:46,260 --> 00:03:48,510 y desciframos lo que todas esas líneas significaban. 88 00:03:48,510 --> 00:03:49,950 Pero en Python, ¿adivinen qué? 89 00:03:49,950 --> 00:03:53,490 Si queremos escribir un programa cuyo propósito en la vida es decir hello, 90 00:03:53,490 --> 00:03:55,440 bueno, solo escribimos def main ( ): 91 00:03:55,440 --> 00:03:56,520 print ( "hello, world" ) 92 00:03:56,520 --> 00:03:58,775 es una estructura algo similar, 93 00:03:58,775 --> 00:04:04,710 de hecho, se parece un poco a la sintaxis esotérica de aquí, 94 00:04:04,710 --> 00:04:07,180 pero pronto veremos lo qué esto significa, 95 00:04:07,180 --> 00:04:09,495 no obstante, es un poco más sencilla que la anterior 96 00:04:09,495 --> 00:04:10,620 y la descifraremos. 97 00:04:10,620 --> 00:04:13,230 El def aquí simplemente significa, define una función para mí, 98 00:04:13,230 --> 00:04:16,140 mientras que en C, siempre especificamos 99 00:04:16,140 --> 00:04:18,420 el formato de la función que debe regresar, 100 00:04:18,420 --> 00:04:20,570 no lo haremos nunca más en Python. 101 00:04:20,570 --> 00:04:22,320 Python todavía tiene tipos de datos, pero no vamos 102 00:04:22,320 --> 00:04:25,107 a mencionar explícitamente los tipos de datos que usaremos. 103 00:04:25,107 --> 00:04:26,940 Ahora bien, aquí está el nombre de la función 104 00:04:26,940 --> 00:04:28,773 y main será una convención, pero no está 105 00:04:28,773 --> 00:04:32,950 incorporada en el lenguaje de la misma manera como está en C, como veremos. 106 00:04:32,950 --> 00:04:35,760 Por otra parte, este tonto maleficio, es solo 107 00:04:35,760 --> 00:04:37,620 una forma de asegurar que la función predeterminada 108 00:04:37,620 --> 00:04:41,340 se ejecutará en un programa de Python que, de hecho, se llamará main, 109 00:04:41,340 --> 00:04:43,710 pero hablaremos más sobre eso cuando empecemos a crearlo. 110 00:04:43,710 --> 00:04:46,260 Aunque, tal vez esta sea la diferencia más sutil pero también la más importante, 111 00:04:46,260 --> 00:04:47,894 al menos desde el principio 112 00:04:47,894 --> 00:04:49,560 y es difícil verla en esta escala. 113 00:04:49,560 --> 00:04:54,201 Pero observen los dos puntos aquí y aquí, que ahora resalté en amarillo 114 00:04:54,201 --> 00:04:55,950 y estos puntos, los cuales no deben escribirse, 115 00:04:55,950 --> 00:04:58,158 pero están destinados a llamar nuestra atención hacia el hecho 116 00:04:58,158 --> 00:05:00,850 de que presioné cuatro veces la barra espaciadora en esos lugares. 117 00:05:00,850 --> 00:05:04,890 Si alguna vez obtuvimos algún comentario de nuestro TA o TF 118 00:05:04,890 --> 00:05:09,030 de que podríamos tener un estilo mejor, más cercano al 5 de 5, debido a la falta 119 00:05:09,030 --> 00:05:11,400 de sangría o de un formato más bonito, los de Python 120 00:05:11,400 --> 00:05:13,020 nos ayudarán con esto. 121 00:05:13,020 --> 00:05:17,970 El código de Python no se ejecutará si no inventamos las cosas correctamente. 122 00:05:17,970 --> 00:05:22,440 Se fueron las llaves que encapsulan a las líneas de código relacionadas 123 00:05:22,440 --> 00:05:24,330 dentro de algún bloque funcional 124 00:05:24,330 --> 00:05:27,780 Y en su lugar, suelen reemplazarse con esta estructura general. 125 00:05:27,780 --> 00:05:30,360 Tenemos dos puntos, luego debajo de eso y con sangría 126 00:05:30,360 --> 00:05:34,020 están todas las líneas que tienen alguna relación, con esa primera línea de código 127 00:05:34,020 --> 00:05:36,070 y las sangrías deben ser consistentes. 128 00:05:36,070 --> 00:05:38,970 Y aunque a simple vista puede que no logremos 129 00:05:38,970 --> 00:05:43,140 distinguir cuatro espacios de tres, el entorno de Python lo hará 130 00:05:43,140 --> 00:05:45,180 y está implícito que esto nos ayudará 131 00:05:45,180 --> 00:05:47,490 a aplicar un mejor estilo, acaso, de lo que podría 132 00:05:47,490 --> 00:05:50,649 haberse hecho fácilmente desde el principio. 133 00:05:50,649 --> 00:05:52,940 En Scratch, evidentemente tuvimos un bloque eterno, 134 00:05:52,940 --> 00:05:55,342 el cual dice para siempre, hello, world y al igual que en C, nosotros 135 00:05:55,342 --> 00:05:56,550 podíamos implementarlo de esta manera. 136 00:05:56,550 --> 00:05:58,799 Ahora, existe un mapeo bastante limpio en Python, 137 00:05:58,799 --> 00:06:01,500 ya sabemos que podemos deshacernos del punto y coma, 138 00:06:01,500 --> 00:06:03,990 ya sabemos que podemos deshacernos de las llaves, 139 00:06:03,990 --> 00:06:05,970 que tendremos que agregar dos puntos, 140 00:06:05,970 --> 00:06:08,370 pero también podemos deshacernos de algunas cosas más. 141 00:06:08,370 --> 00:06:14,460 ¿Qué más falta para esta traducción de hello, world a Python? 142 00:06:14,460 --> 00:06:17,046 Es algo más sutil. 143 00:06:17,046 --> 00:06:18,920 De modo que podemos deshacernos definitivamente de las llaves 144 00:06:18,920 --> 00:06:20,858 y confiar solamente en las sangrías. 145 00:06:20,858 --> 00:06:24,310 146 00:06:24,310 --> 00:06:26,330 OK, así que no hay paréntesis alrededor de while 147 00:06:26,330 --> 00:06:29,470 y esto también pretende ser una característica de Python. 148 00:06:29,470 --> 00:06:33,310 Si no necesitamos paréntesis para cumplir con el orden de las operaciones, 149 00:06:33,310 --> 00:06:36,082 como, por ejemplo, en la aritmética y cosas similares entonces no los usaremos 150 00:06:36,082 --> 00:06:37,540 porque solo son una distracción. 151 00:06:37,540 --> 00:06:38,623 Únicamente son algo más para escribir, 152 00:06:38,623 --> 00:06:41,865 y ahora el código está visualmente más limpio y es más fácil de leer. 153 00:06:41,865 --> 00:06:43,240 Aquí también hay una pequeña diferencia, 154 00:06:43,240 --> 00:06:45,550 True y False iniciarán con letras mayúsculas en Python, 155 00:06:45,550 --> 00:06:47,407 pero eso es un detalle bastante incidental. 156 00:06:47,407 --> 00:06:49,990 Sin embargo, observen que esto captura la esencia de Python, 157 00:06:49,990 --> 00:06:52,299 no es un gran paso ir de uno a otro, 158 00:06:52,299 --> 00:06:54,340 pero comenzamos a deshacernos de un poco 159 00:06:54,340 --> 00:06:57,381 del desorden y de las cosas que nunca le agregaron mucho intelectualmente, 160 00:06:57,381 --> 00:06:59,890 y era algo molesto tener que recordarlo desde el principio. 161 00:06:59,890 --> 00:07:01,480 Aquí está nuestra variable booleana True 162 00:07:01,480 --> 00:07:03,880 y ahora tenemos un número finito de iteraciones, 163 00:07:03,880 --> 00:07:06,130 Tal vez queremos decir hello, world exactamente 50 veces, 164 00:07:06,130 --> 00:07:09,320 en C, era un desastre cuando queriamos hacer esto, 165 00:07:09,320 --> 00:07:11,980 tendríamos que inicializar una variable para llevar la cuenta, 166 00:07:11,980 --> 00:07:14,981 pero sin incluir al 50, además agregar algo en el proceso, entre otras cosas. 167 00:07:14,981 --> 00:07:16,855 En Python, esto será un poco más limpio, 168 00:07:16,855 --> 00:07:19,720 después veremos lo que esto significa exactamente. 169 00:07:19,720 --> 00:07:23,900 Pero si lo leemos de izquierda a derecha de algún modo dice lo que queremos. 170 00:07:23,900 --> 00:07:24,400 ¿Cierto? 171 00:07:24,400 --> 00:07:26,890 For i in the range of 50, 172 00:07:26,890 --> 00:07:29,170 entonces, es probable que i sea una variable. 173 00:07:29,170 --> 00:07:30,970 Noten que no mencionamos su tipo, 174 00:07:30,970 --> 00:07:34,180 el cual estará implícito de acuerdo al contexto, que en este caso 175 00:07:34,180 --> 00:07:36,730 por el 50, aparentemente, tiene que ver con números. 176 00:07:36,730 --> 00:07:39,184 Range por sí mismo, será un tipo de dato 177 00:07:39,184 --> 00:07:40,600 que en ese sentido es un poco raro, 178 00:07:40,600 --> 00:07:41,830 pero se le llama clase. 179 00:07:41,830 --> 00:07:46,600 En esencia, esta es una característica especial de Python que, a diferencia de C, 180 00:07:46,600 --> 00:07:50,380 donde, si queremos iterar un arreglo de valores o en 50 de estos valores, 181 00:07:50,380 --> 00:07:52,840 en realidad tendríamos un arreglo con 50 valores 182 00:07:52,840 --> 00:07:55,490 y lo genial de range es que se queda allí, 183 00:07:55,490 --> 00:07:58,880 y cada vez que iteramos mediante un bucle, nos da el siguiente número 184 00:07:58,880 --> 00:08:02,690 pero solo uno a la vez, por lo tanto usaremos tan poco como la 185 00:08:02,690 --> 00:08:06,270 50ava parte de la memoria porque solo tenemos que mantener un número 186 00:08:06,270 --> 00:08:06,770 al mismo tiempo 187 00:08:06,770 --> 00:08:08,520 o tal vez un poco más que eso. 188 00:08:08,520 --> 00:08:10,780 No es un ahorro tan perfecto, 189 00:08:10,780 --> 00:08:15,670 pero esto solo es para i en el rango 50, lo que 190 00:08:15,670 --> 00:08:19,270 de manera implícita será el contar desde 0 hasta 49. 191 00:08:19,270 --> 00:08:23,020 Mientras tanto, lo que esté debajo será lo que imprimiremos esta vez. 192 00:08:23,020 --> 00:08:26,620 Y aquí estaba uno de los enormes bloques de Scratch que teníamos al principio. 193 00:08:26,620 --> 00:08:30,100 E i tiene una traducción bastante literal en el código en C, 194 00:08:30,100 --> 00:08:32,710 Aún si nunca vimos Python antes, 195 00:08:32,710 --> 00:08:37,059 tal vez podamos adivinar, cómo se vería el código de Python ahora. 196 00:08:37,059 --> 00:08:39,130 Si esto a la derecha es el código en C, ¿cuáles 197 00:08:39,130 --> 00:08:41,840 serán las características sintácticas que estamos a punto de eliminar? 198 00:08:41,840 --> 00:08:42,059 Sí. 199 00:08:42,059 --> 00:08:44,650 AUDIENCIA: Podemos deshacernos de las llaves y los paréntesis. 200 00:08:44,650 --> 00:08:47,275 DAVID: Las llaves y los paréntesis desaparecerán, 201 00:08:47,275 --> 00:08:49,120 ¿Qué otra cosa podría desaparecer? 202 00:08:49,120 --> 00:08:52,550 Los puntos y comas se irán, 203 00:08:52,550 --> 00:08:54,850 al igual que las \n dentro de las declaraciones de impresión. 204 00:08:54,850 --> 00:08:56,500 Genial. 205 00:08:56,500 --> 00:08:59,830 Falta una cosa más, creo. 206 00:08:59,830 --> 00:09:01,450 El if, 207 00:09:01,450 --> 00:09:03,424 Entonces estrictamente no necesitamos los paréntesis, 208 00:09:03,424 --> 00:09:05,590 porque no es como si combinara las cosas de manera lógica, 209 00:09:05,590 --> 00:09:08,050 como esto o eso, o esto y aquello, 210 00:09:08,050 --> 00:09:10,180 y esto debería ser suficiente como para deshacerse de esos dos. 211 00:09:10,180 --> 00:09:12,280 Y aún hay un par de modificaciones que tendremos que hacer aquí, 212 00:09:12,280 --> 00:09:14,960 pero, de hecho, el código será mucho más estricto, por así decirlo. 213 00:09:14,960 --> 00:09:16,960 Esta vez, aquí, solo diremos lo que queramos. 214 00:09:16,960 --> 00:09:18,168 Pero hay una cosa rara 215 00:09:18,168 --> 00:09:20,080 y no es un error tipográfico. 216 00:09:20,080 --> 00:09:23,056 ¿Qué es lo que al parecer tendremos que saber desde ahora? 217 00:09:23,056 --> 00:09:24,470 El elif y lo que sea. 218 00:09:24,470 --> 00:09:26,480 Entonces, elif no es un error tipográfico. 219 00:09:26,480 --> 00:09:29,094 De hecho, es la forma en la que expresamos la idea del else-if. 220 00:09:29,094 --> 00:09:31,010 Pero por lo demás, todo es exactamente lo mismo. 221 00:09:31,010 --> 00:09:31,926 También noten los dos puntos, 222 00:09:31,926 --> 00:09:33,970 Sinceramente, es irónico, que si bien antes 223 00:09:33,970 --> 00:09:36,940 pudo ser molesto que de vez en cuando olvidáramos un punto y coma, 224 00:09:36,940 --> 00:09:38,830 ahora es posible que los dos puntos tomen ese papel, 225 00:09:38,830 --> 00:09:41,980 pero en todo caso, todo lo que esté debajo de ellos debe tener sangría. 226 00:09:41,980 --> 00:09:45,880 Aquí hay una diferencia fundamental, más allá de las ridículas diferencias 227 00:09:45,880 --> 00:09:47,950 sintácticas entre esto y, digamos, otros lenguajes, 228 00:09:47,950 --> 00:09:52,090 el flujo de trabajo que hemos usado hasta ahora, básicamente ha sido esto en C, 229 00:09:52,090 --> 00:09:55,950 escribimos el código fuente en un archivo que, por lo general, termina en .c 230 00:09:55,950 --> 00:10:00,602 ejecutamos un compilador, que para una verificación rápida se llama clang. 231 00:10:00,602 --> 00:10:01,810 Técnicamente ya no es make, 232 00:10:01,810 --> 00:10:04,030 make es solamente esta herramienta de construcción, que 233 00:10:04,030 --> 00:10:05,730 vuelve automático el proceso de llamar a clang. 234 00:10:05,730 --> 00:10:07,960 Así, estrictamente hablando, clang es el compilador, 235 00:10:07,960 --> 00:10:11,470 además, clang genera los ceros y unos, también conocidos como código máquina. 236 00:10:11,470 --> 00:10:15,310 Nuestra computadora Mac, PC o la que sea, tiene un CPU o unidad central 237 00:10:15,310 --> 00:10:18,100 de procesamiento, fabricada por Intel o alguna otra compañía 238 00:10:18,100 --> 00:10:20,590 y ese CPU está programado para comprender 239 00:10:20,590 --> 00:10:25,330 ciertos patrones de bits, los ceros y unos también conocidos como código máquina. 240 00:10:25,330 --> 00:10:27,430 De modo que, este ha sido nuestro mundo en C. 241 00:10:27,430 --> 00:10:31,150 Con Python, umh, entonces el código que hayamos compilado en C, 242 00:10:31,150 --> 00:10:32,860 por ejemplo, podría haber sido este: clang hello.c 243 00:10:32,860 --> 00:10:34,750 el cual, como dijimos, ejecutamos con clang de este modo. 244 00:10:34,750 --> 00:10:37,540 Pero si no especificamos el nombre de un archivo predeterminado como salida, 245 00:10:37,540 --> 00:10:40,480 en su lugar, obtendremos en nuestro archivo todos estos ceros y unos, 246 00:10:40,480 --> 00:10:43,990 los cuales después podrán ejecutarse por medio de ./a.out, 247 00:10:43,990 --> 00:10:47,270 el nombre predeterminado para la salida del ensamblador, aquí. 248 00:10:47,270 --> 00:10:53,200 Sin embargo, en Python, el mundo también se vuelve un poco más simple, 249 00:10:53,200 --> 00:10:56,740 ahora que tenemos un código fuente y un intérprete, 250 00:10:56,740 --> 00:10:59,140 pareciera que no hay un código máquina, 251 00:10:59,140 --> 00:11:00,730 y tampoco un compilador, 252 00:11:00,730 --> 00:11:02,800 además, sinceramente, hay una flecha menos, la cual 253 00:11:02,800 --> 00:11:05,434 me sugiere que el proceso de ejecutar el código Python, por sí mismo, 254 00:11:05,434 --> 00:11:07,100 será un poco más sencillo. 255 00:11:07,100 --> 00:11:09,400 La ejecución del código en C, suele constar de dos pasos, 256 00:11:09,400 --> 00:11:12,490 ejecutamos nuevamente clang, o por medio de make ejecutamos clang, 257 00:11:12,490 --> 00:11:13,617 después ejecutamos el programa. 258 00:11:13,617 --> 00:11:14,200 Y eso está bien, 259 00:11:14,200 --> 00:11:14,950 no es del todo difícil, 260 00:11:14,950 --> 00:11:15,741 pero son dos pasos. 261 00:11:15,741 --> 00:11:18,850 ¿Por qué no reducir los dos pasos, si lo podríamos hacer en uno? 262 00:11:18,850 --> 00:11:20,500 Veremos lo qué eso significa exactamente. 263 00:11:20,500 --> 00:11:22,960 en realidad, se trata de una simplificación excesiva. 264 00:11:22,960 --> 00:11:24,918 En teoría, si queremos 265 00:11:24,918 --> 00:11:29,530 ejecutar un programa como este, que simplemente imprime hello, world, 266 00:11:29,530 --> 00:11:33,370 solo debemos ejecutar python hello.py. 267 00:11:33,370 --> 00:11:36,760 y como resultado veremos hello, world en la pantalla, 268 00:11:36,760 --> 00:11:38,000 como pronto lo comprobaremos. 269 00:11:38,000 --> 00:11:41,150 Pero en el fondo, pasan otras cosas. 270 00:11:41,150 --> 00:11:43,000 Aquí hay una especie de compilador, 271 00:11:43,000 --> 00:11:44,770 pero no hay algo llamado código máquina como tal, 272 00:11:44,770 --> 00:11:45,700 se llama byte code. 273 00:11:45,700 --> 00:11:48,100 Incluso hay algo llamado máquina virtual de Python. 274 00:11:48,100 --> 00:11:51,100 Pero todo esto es un poco abstracto para nosotros, 275 00:11:51,100 --> 00:11:53,440 y sin duda para la conversación de hoy, 276 00:11:53,440 --> 00:11:55,690 y también es así para el mundo real, en general. 277 00:11:55,690 --> 00:11:57,630 Los humanos se han vuelto mejores a lo largo de los años 278 00:11:57,630 --> 00:12:01,450 para escribir el software y las herramientas con las cuales podemos escribirlo, 279 00:12:01,450 --> 00:12:03,760 de modo que, muchos de los procesos más manuales 280 00:12:03,760 --> 00:12:05,770 y muchos de los detalles de bajo nivel en los que nos hemos 281 00:12:05,770 --> 00:12:09,130 enfocado, aunque no sin esfuerzo, comienzan a desaparecer en C. 282 00:12:09,130 --> 00:12:12,820 Al igual que en la semana 0, cuando poníamos una idea después de otra, 283 00:12:12,820 --> 00:12:15,580 los ceros y unos, el ASCII, colores y todas esas cosas, 284 00:12:15,580 --> 00:12:18,970 de modo similar, pero con las herramientas que tenemos, empezaremos a hacer lo mismo. 285 00:12:18,970 --> 00:12:24,460 Entonces, lo que ocurre en realidad es 286 00:12:24,460 --> 00:12:28,090 este proceso de aquí, en el que podemos pensar, 287 00:12:28,090 --> 00:12:30,040 como algo bastante simple. 288 00:12:30,040 --> 00:12:32,860 Ahora, si son curiosos y toman alguna clase de nivel superior 289 00:12:32,860 --> 00:12:36,010 como CS61 o alguna otra, en realidad hablarán 290 00:12:36,010 --> 00:12:38,720 sobre cosas como el byte code, el lenguaje ensamblador y todo eso. 291 00:12:38,720 --> 00:12:40,720 Y vimos un destello de eso último, hace un momento. 292 00:12:40,720 --> 00:12:42,670 Este es un lenguaje intermedio, 293 00:12:42,670 --> 00:12:47,000 que el código fuente de Python convierte antes de ejecutarse por la computadora. 294 00:12:47,000 --> 00:12:51,020 Pero nuevamente ignoraremos esos detalles de bajo nivel. 295 00:12:51,020 --> 00:12:53,500 Aquí en nuestro kit, ahora están algunas de las herramientas. 296 00:12:53,500 --> 00:12:56,380 En Python, hay tipos de datos aunque hasta ahora, no hemos 297 00:12:56,380 --> 00:12:59,849 visto ningún ejemplo en el cual especifique los tipos de valores 298 00:12:59,849 --> 00:13:02,140 que estarán en mis variables, o qué tipos de valores 299 00:13:02,140 --> 00:13:03,610 devolverá una función. 300 00:13:03,610 --> 00:13:05,290 Pero están ahí. 301 00:13:05,290 --> 00:13:07,360 Todo acerca de lo que queremos que sea una variable 302 00:13:07,360 --> 00:13:11,360 está escrito en términos generales, esto solo tomará ese tipo de datos, 303 00:13:11,360 --> 00:13:13,540 así se trate de un entero, una cadena o algo similar, 304 00:13:13,540 --> 00:13:15,400 la cadena no será una palabra completa, 305 00:13:15,400 --> 00:13:17,590 en Python, esto literalmente se llama str. 306 00:13:17,590 --> 00:13:22,340 Pero aquí hay algunos tipos conocidos bool, float, int y otros. 307 00:13:22,340 --> 00:13:26,320 Y entre los demás, como lo veremos pronto, hay funciones como range, 308 00:13:26,320 --> 00:13:30,400 pero antes de eso, noten que también daremos nuestra primera incursión 309 00:13:30,400 --> 00:13:33,020 en Python con algunas funciones conocidas. 310 00:13:33,020 --> 00:13:36,640 Python tiene mecanismos diferentes a C para obtener la entrada del usuario, 311 00:13:36,640 --> 00:13:41,500 recopilamos algunos de estos detalles en una nueva biblioteca de CS50 para Python, 312 00:13:41,500 --> 00:13:44,170 que en realidad solo usaremos algunas veces antes 313 00:13:44,170 --> 00:13:47,645 de que hagamos la transición, pero encontraremos funciones como get_char, 314 00:13:47,645 --> 00:13:50,770 get_float, get_int y get_string que controlarán toda la verificación de errores 315 00:13:50,770 --> 00:13:52,870 que se requiere, al menos para nuestros primeros programas, 316 00:13:52,870 --> 00:13:55,180 podemos comenzar con un auténtico trabajo, y terminarlo 317 00:13:55,180 --> 00:13:58,950 sin sumergirnos en el fondo de esto. 318 00:13:58,950 --> 00:14:01,370 Por último, aquí en nuestro kit hay algunas otras herramientas 319 00:14:01,370 --> 00:14:03,900 Y hoy arañaremos la superficie de algunas de ellas. 320 00:14:03,900 --> 00:14:08,330 Pero lo bueno de Python y más en general, de los lenguajes de alto nivel, 321 00:14:08,330 --> 00:14:11,330 como los lenguajes más modernos que aprendieron lecciones de otros más viejos 322 00:14:11,330 --> 00:14:12,650 como C, 323 00:14:12,650 --> 00:14:16,875 es que obtenemos mucho más gratuitamente, mucho más fuera de la caja, 324 00:14:16,875 --> 00:14:18,500 hay mucho más que un fregadero de cocina, 325 00:14:18,500 --> 00:14:21,860 existen tantas metáforas que podemos usar aquí, las cuales hablan del hecho 326 00:14:21,860 --> 00:14:25,550 de que Python, al igual que Java, tiene más características que C, 327 00:14:25,550 --> 00:14:29,060 si estudiaron principios de la informática o algo más, que C. 328 00:14:29,060 --> 00:14:33,320 Python tiene todo un kit de herramientas para representar números complejos, 329 00:14:33,320 --> 00:14:36,650 diccionarios, que aparte de eso, se implementan como tablas hash 330 00:14:36,650 --> 00:14:39,890 que ahora conocemos como lists, las cuales son sinónimo de un arreglo. 331 00:14:39,890 --> 00:14:43,820 Pero un list es un arreglo que puede crecer y reducirse automáticamente, 332 00:14:43,820 --> 00:14:47,040 no tendremos que saltar entre los aros como en C, a range que vimos brevemente 333 00:14:47,040 --> 00:14:50,330 y el cual nos devuelve un número después de otro en algún rango, idealmente 334 00:14:50,330 --> 00:14:51,262 por iteración, 335 00:14:51,262 --> 00:14:52,970 set es un concepto matemático, donde 336 00:14:52,970 --> 00:14:55,430 si queremos poner montones de cosas en una estructura de datos 337 00:14:55,430 --> 00:14:58,190 y queremos asegurarnos de tener solo uno de cada cosa, 338 00:14:58,190 --> 00:15:00,260 sin duplicados, podemos usar set. 339 00:15:00,260 --> 00:15:02,210 Tuple también es un concepto matemático, 340 00:15:02,210 --> 00:15:06,740 que nos permite combinar cosas que están relacionadas, sin comprometerlas 341 00:15:06,740 --> 00:15:08,030 con las estructuras actuales. 342 00:15:08,030 --> 00:15:11,720 Por ejemplo, x, y es un modelo muy común en muchos programas, gráficos, 343 00:15:11,720 --> 00:15:14,494 videos y sin duda en las matemáticas y en la creación de gráficos en sí. 344 00:15:14,494 --> 00:15:16,910 En realidad no necesitamos de una estructura de datos completa, 345 00:15:16,910 --> 00:15:19,880 tal vez solo queramos decir x, y 346 00:15:19,880 --> 00:15:22,490 y Python nos da ese tipo de expresividad. 347 00:15:22,490 --> 00:15:25,880 Ahora vamos a sumergirnos con un mapeo rápido 348 00:15:25,880 --> 00:15:29,990 de un mundo al otro y nos enfocaremos en lo que podemos hacer con Python, 349 00:15:29,990 --> 00:15:32,150 de modo que aquí estoy, en el conocido IDE de CS50, 350 00:15:32,150 --> 00:15:34,270 al igual que tenemos preinstalado a clang, 351 00:15:34,270 --> 00:15:38,240 así como make y otras herramientas, también instalamos un programa. 352 00:15:38,240 --> 00:15:41,720 Ese programa se llama Python el cual, a primera vista es un poco confuso 353 00:15:41,720 --> 00:15:44,510 porque al parecer, Python es el nombre del lenguaje, 354 00:15:44,510 --> 00:15:46,250 pero también es el nombre del programa. 355 00:15:46,250 --> 00:15:47,930 Y aquí es donde Python es diferente. 356 00:15:47,930 --> 00:15:50,600 Mientras que en C se compila nuevamente y usamos algo 357 00:15:50,600 --> 00:15:52,502 como clang para convertirlo a código máquina, 358 00:15:52,502 --> 00:15:55,460 Python es tanto el nombre del lenguaje como el nombre del programa que 359 00:15:55,460 --> 00:15:58,160 usamos para interpretar el lenguaje. 360 00:15:58,160 --> 00:16:01,010 De modo que lo preinstalamos en el IDE de CS50 y sinceramente fue en estos días, 361 00:16:01,010 --> 00:16:04,220 y probablemente también en nuestras Mac o PC, incluso si no lo sabíamos, 362 00:16:04,220 --> 00:16:08,240 hay un programa llamado Python que si le dimos su código fuente como entrada 363 00:16:08,240 --> 00:16:10,100 hará lo que el código diga. 364 00:16:10,100 --> 00:16:12,750 Continuemos y probemos algo como eso. 365 00:16:12,750 --> 00:16:16,310 Permítanme seguir y guardaré un archivo a manera preventiva como hello.py 366 00:16:16,310 --> 00:16:19,880 entonces .py será la nueva convención en lugar de .c 367 00:16:19,880 --> 00:16:22,560 Para continuar, mantendré esto bastante simple. 368 00:16:22,560 --> 00:16:24,268 Solo imprimiré la primera cosa mmm oh.. 369 00:16:24,268 --> 00:16:24,870 ¡vamos memoria! 370 00:16:24,870 --> 00:16:26,430 ya no es más printf, 371 00:16:26,430 --> 00:16:28,730 es solo print ("hello, world") 372 00:16:28,730 --> 00:16:30,380 Save, listo. 373 00:16:30,380 --> 00:16:32,570 Este será mi primer programa en Python. 374 00:16:32,570 --> 00:16:33,070 ¿Por qué? 375 00:16:33,070 --> 00:16:34,490 Esta es una línea de código 376 00:16:34,490 --> 00:16:38,780 y es consistente con las características que he dicho que tiene Python. 377 00:16:38,780 --> 00:16:40,370 Pero, ¿cómo lo ejecuto? 378 00:16:40,370 --> 00:16:43,970 Bueno, en C, habríamos hecho algo como, make hello 379 00:16:43,970 --> 00:16:47,440 pero make no sabe nada sobre esto, porque, por lo general, make se usa en C, 380 00:16:47,440 --> 00:16:49,640 al menos en este contexto. 381 00:16:49,640 --> 00:16:53,990 Entonces tal vez sea algo como ./hello.py. 382 00:16:53,990 --> 00:16:54,530 No. 383 00:16:54,530 --> 00:16:56,450 Parece que no tengo permiso allí, 384 00:16:56,450 --> 00:17:00,990 pero hay un paso que adelanté antes en la diapositiva separada. 385 00:17:00,990 --> 00:17:04,212 ¿Qué hago para ejecutar un programa, dije? 386 00:17:04,212 --> 00:17:05,329 PÚBLICO: Con Python hello.py. 387 00:17:05,329 --> 00:17:06,079 DAVID: ¡Sí! 388 00:17:06,079 --> 00:17:07,578 Debo ser un poco más explícito, 389 00:17:07,578 --> 00:17:10,760 entonces python, que es el nombre del intérprete que entiende Python 390 00:17:10,760 --> 00:17:12,349 y ahora necesito proporcionarle alguna entrada, 391 00:17:12,349 --> 00:17:14,526 por el tiempo que llevamos en C, sabemos que los programas 392 00:17:14,526 --> 00:17:15,859 pueden aceptar los argumentos de la línea de comandos 393 00:17:15,859 --> 00:17:17,750 y de hecho, este programa lo hace por sí mismo, Python. 394 00:17:17,750 --> 00:17:20,150 Solo le damos el nombre de un programa para que lo ejecute. 395 00:17:20,150 --> 00:17:23,329 Y aquí lo tenemos, nuestro primer programa. 396 00:17:23,329 --> 00:17:24,755 Así que todo eso está bien. 397 00:17:24,755 --> 00:17:27,380 Pero ¿y si quisiera hacer algo un poco más interesante, 398 00:17:27,380 --> 00:17:29,340 como obtener una cadena del usuario? 399 00:17:29,340 --> 00:17:32,810 Bueno, en Python y especialmente en el IDE de CS50, 400 00:17:32,810 --> 00:17:38,370 puedo hacer algo como esto: s = get_string( ) 401 00:17:38,370 --> 00:17:41,840 y puedo preguntarle a alguien por su nombre, así: s = get_string("name: ") 402 00:17:41,840 --> 00:17:44,330 Ahora, el IDE de CS50 me está gritando 403 00:17:44,330 --> 00:17:46,850 Undefined variable 'get_string' 404 00:17:46,850 --> 00:17:50,310 veamos si tal vez solo tiene errores. 405 00:17:50,310 --> 00:17:50,810 No. 406 00:17:50,810 --> 00:17:53,710 Esto es un poco más esotérico que de costumbre, 407 00:17:53,710 --> 00:17:56,600 Pero tenemos Traceback (most recent call last) : 408 00:17:56,600 --> 00:17:59,510 File "hello.py," line 2, in cualquier cosa que esto sea, 409 00:17:59,510 --> 00:18:01,160 Ahora, veo una línea de código en la línea 2, que dice 410 00:18:01,160 --> 00:18:03,530 NameError: name 'get_string' is not defined 411 00:18:03,530 --> 00:18:06,240 Esto no es el mismo lenguaje que vimos antes, 412 00:18:06,240 --> 00:18:09,810 pero, ¿qué nos hace recordar? 413 00:18:09,810 --> 00:18:13,080 Sí, como en el pasado, cuando nos olvidamos de cs50.h, 414 00:18:13,080 --> 00:18:16,271 tuvimos algo sobre un identificador no declarado, 415 00:18:16,271 --> 00:18:16,770 o algo como eso, 416 00:18:16,770 --> 00:18:20,190 Esto simplemente no entendía algo relacionado con la biblioteca de CS50. 417 00:18:20,190 --> 00:18:23,790 En C habríamos hecho #include 418 00:18:23,790 --> 00:18:26,370 lo cual ya no es relevante porque ahora estamos en Python, 419 00:18:26,370 --> 00:18:28,080 pero en esencia es algo similar. 420 00:18:28,080 --> 00:18:35,130 Ahora diré from cs50 import get_string y lo guardaré, 421 00:18:35,130 --> 00:18:38,650 con suerte desaparecerán temporalmente los errores cuando el IDE se dé cuenta, 422 00:18:38,650 --> 00:18:41,340 ¡oh, ahora importaron la biblioteca de CS50! 423 00:18:41,340 --> 00:18:44,874 específicamente un método o función, más bien dentro de ella, llamada get_string 424 00:18:44,874 --> 00:18:47,040 también tiene una sintaxis diferente, pero dice 425 00:18:47,040 --> 00:18:49,710 lo que significa, de cs50, que al parecer es el nombre de la biblioteca, 426 00:18:49,710 --> 00:18:51,660 importa una función llamada get_string. 427 00:18:51,660 --> 00:18:54,810 Proseguiré y ejecutaré nuevamente python hello.py, 428 00:18:54,810 --> 00:18:57,130 puedo seguir y escribiré en name: María 429 00:18:57,130 --> 00:19:01,590 e ignorarla por completo porque necesito hacer una corrección aquí. 430 00:19:01,590 --> 00:19:03,120 ¿Cuál es el error obvio, 431 00:19:03,120 --> 00:19:05,746 obvio ahora para mí, en el programa? 432 00:19:05,746 --> 00:19:08,200 PÚBLICO: Necesitamos incluir la variable para s. 433 00:19:08,200 --> 00:19:08,950 DAVID: Sí. 434 00:19:08,950 --> 00:19:12,670 Así que necesito incluir a s, la cual tengo en la línea 3, 435 00:19:12,670 --> 00:19:15,140 pero después ya no la usé de ninguna manera. 436 00:19:15,140 --> 00:19:18,730 desde luego que esto va a salir mal, porque literalmente 437 00:19:18,730 --> 00:19:20,290 dirá hello s. 438 00:19:20,290 --> 00:19:22,946 Así es como solíamos hacer esto 439 00:19:22,946 --> 00:19:24,070 y después pondríamos una s. 440 00:19:24,070 --> 00:19:25,270 Pero este no es printf, 441 00:19:25,270 --> 00:19:25,940 es print, 442 00:19:25,940 --> 00:19:27,400 entonces la sintaxis es un poco diferente. 443 00:19:27,400 --> 00:19:30,280 parece que podemos hacer esto en por lo menos dos maneras diferentes. 444 00:19:30,280 --> 00:19:34,120 Tal vez la más fácil, si no es que la más obvia 445 00:19:34,120 --> 00:19:41,110 sería algo como esto, donde simplemente podría decir print( "hello, 446 00:19:41,110 --> 00:19:44,020 abrir y cerrar las llaves, ("hello, { }") 447 00:19:44,020 --> 00:19:47,230 y dentro de eso, simplemente especificar el nombre de la variable {s} 448 00:19:47,230 --> 00:19:48,370 que quiero introducir. 449 00:19:48,370 --> 00:19:50,170 Pero eso no es lo único que debemos hacer allí, 450 00:19:50,170 --> 00:19:52,520 lo ejecutaré una vez más. 451 00:19:52,520 --> 00:19:54,460 Si escribo en name: María, oh, 452 00:19:54,460 --> 00:19:55,960 aún no es del todo correcto. 453 00:19:55,960 --> 00:19:59,560 Debo decirle a Python que se trata de un tipo especial de cadena, 454 00:19:59,560 --> 00:20:03,250 es una cadena con un formato similar al que esperaba printf. 455 00:20:03,250 --> 00:20:06,160 y la manera de hacerlo, aunque es un poco diferente de C, 456 00:20:06,160 --> 00:20:07,930 es decir f: print(f"hello, {s}") 457 00:20:07,930 --> 00:20:08,830 esta es una cadena f, 458 00:20:08,830 --> 00:20:11,710 Antes de las comillas, escribimos la letra f. 459 00:20:11,710 --> 00:20:14,230 Y si se ejecuta este programa, 460 00:20:14,230 --> 00:20:18,130 se verá el nombre María como: hello, María. 461 00:20:18,130 --> 00:20:19,807 Más tarde, me ocuparé de esa X roja. 462 00:20:19,807 --> 00:20:20,890 Esa es una cadena de formato, 463 00:20:20,890 --> 00:20:21,973 pero se puede hacer de otra manera, 464 00:20:21,973 --> 00:20:26,050 aunque podría decir que no es tan obvia. 465 00:20:26,050 --> 00:20:29,420 En la documentación en línea también podemos ver algo como esto. 466 00:20:29,420 --> 00:20:31,630 Separémonos de esto por un segundo. 467 00:20:31,630 --> 00:20:34,270 Lo que resalté en verde en Python 468 00:20:34,270 --> 00:20:37,750 se conoce como cadena, y de otra manera como str. 469 00:20:37,750 --> 00:20:40,030 str es el nombre de este tipo de datos. 470 00:20:40,030 --> 00:20:44,350 A diferencia de C, donde una cadena es una mentira piadosa, donde 471 00:20:44,350 --> 00:20:46,810 a fin de cuentas solo era un puntero, en Python 472 00:20:46,810 --> 00:20:50,320 una cadena es un objeto first-class, lo que significa que 473 00:20:50,320 --> 00:20:52,420 no solo son una secuencia de caracteres, 474 00:20:52,420 --> 00:20:56,170 tienen funcionalidad incorporada, funciones incorporadas. 475 00:20:56,170 --> 00:21:00,190 Al igual que las estructuras en C, que tenían muchas cosas dentro de ellas, 476 00:21:00,190 --> 00:21:04,270 una cadena en Python tiene varias cosas dentro de ella, 477 00:21:04,270 --> 00:21:09,350 no solo la secuencia de caracteres, sino funciones que pueden hacer cosas. 478 00:21:09,350 --> 00:21:12,550 Accedemos a esas funciones por medio del mismo punto 479 00:21:12,550 --> 00:21:14,920 operador como en C. Solo al conocer la documentación 480 00:21:14,920 --> 00:21:18,670 o los ejemplos de las funciones que hay en las clases, los cuales estén dentro de 481 00:21:18,670 --> 00:21:19,810 los objetos de la cadena. 482 00:21:19,810 --> 00:21:21,340 Uno de ellos es el formato, 483 00:21:21,340 --> 00:21:23,673 que es solo una función que se adapta a un argumento. ¿Qué 484 00:21:23,673 --> 00:21:26,260 queremos insertar en una cadena a la izquierda del punto? 485 00:21:26,260 --> 00:21:29,500 Pues con simplemente especificarle, oye, Python, 486 00:21:29,500 --> 00:21:32,800 aquí hay una cadena con un marcador de posición, 487 00:21:32,800 --> 00:21:36,010 dentro de esta cadena hay una funcionalidad incorporada, también conocida 488 00:21:36,010 --> 00:21:39,380 como un método, cuando una función está dentro de algún objeto o estructura 489 00:21:39,380 --> 00:21:41,020 pasa el valor s. 490 00:21:41,020 --> 00:21:45,580 Pero si vuelvo a ejecutarlo después de guardar mis cambios, 491 00:21:45,580 --> 00:21:49,479 debería ver que el nombre de María todavía está insertado. 492 00:21:49,479 --> 00:21:50,020 ¡Y eso es todo! 493 00:21:50,020 --> 00:21:53,020 Pero es una idea sencilla de que ahora incluso las cadenas tienen 494 00:21:53,020 --> 00:21:55,180 cosas adentro de ellas además de caracteres individuales 495 00:21:55,180 --> 00:21:57,310 a las cuales podemos acceder por medio de los puntos. 496 00:21:57,310 --> 00:22:01,400 Ahora nos extenderemos con un ejemplo que conocemos desde hace 497 00:22:01,400 --> 00:22:01,900 tiempo. 498 00:22:01,900 --> 00:22:05,140 De modo que abriré dos ventanas, una al lado de la otra 499 00:22:05,140 --> 00:22:07,370 y veré si nos permite trasladar una hacia la otra 500 00:22:07,370 --> 00:22:12,730 abriré, por ejemplo, el int.c de antes 501 00:22:12,730 --> 00:22:17,200 recordemos a este programa int.c, cuyo único propósito 502 00:22:17,200 --> 00:22:20,950 era obtener un número entero del usuario e insertarlo en printf 503 00:22:20,950 --> 00:22:22,090 para después imprimirlo. 504 00:22:22,090 --> 00:22:24,790 ¿Qué será diferente en Python? 505 00:22:24,790 --> 00:22:28,960 Bien, en Python, si implemento esto como, digamos, int.py, 506 00:22:28,960 --> 00:22:31,250 luego haré lo siguiente, 507 00:22:31,250 --> 00:22:33,820 me desplazaré hacia abajo para alinear un poco las cosas, 508 00:22:33,820 --> 00:22:39,520 escribiré def ¡ups! main, como lo vimos en las diapositivas anteriores 509 00:22:39,520 --> 00:22:44,770 y luego por aquí, hago i = get_int abro y cierro las comillas, integer, 510 00:22:44,770 --> 00:22:48,920 aquí abajo, no diré printf ahora es print, abro y cierro las comillas, 511 00:22:48,920 --> 00:22:52,400 "hello" y después el marcador de posición, 512 00:22:52,400 --> 00:22:56,020 según nuestro ejemplo anterior, ¿cuál es la forma más sencilla de hacer esto? 513 00:22:56,020 --> 00:22:58,810 con las llaves e i. 514 00:22:58,810 --> 00:23:02,560 Ahora, quiero ser muy claro en que esta es una cadena f especial, o una cadena 515 00:23:02,560 --> 00:23:04,420 de formato, en la cual podemos insertar los valores. 516 00:23:04,420 --> 00:23:06,490 Guardaré eso. 517 00:23:06,490 --> 00:23:08,950 Ya que tengo la mayor parte de las piezas juntas, y si por ahora 518 00:23:08,950 --> 00:23:13,840 ignoramos la X roja, ¿qué otra cosa tenemos pendiente? 519 00:23:13,840 --> 00:23:17,510 Cometí el mismo error que antes. 520 00:23:17,510 --> 00:23:21,250 Sí, el get_int, de modo que aquí arriba es el que tenemos en la línea 3, 521 00:23:21,250 --> 00:23:26,440 esta vez sería: from cs50 import get_int 522 00:23:26,440 --> 00:23:27,160 Lo guardamos. 523 00:23:27,160 --> 00:23:32,977 Y si en mi ventana de terminal ejecuto python de int.py 524 00:23:32,977 --> 00:23:35,720 ¡hum! 525 00:23:35,720 --> 00:23:38,960 eso se ve extraño, 526 00:23:38,960 --> 00:23:42,200 no es un error por una salida incorrecta, 527 00:23:42,200 --> 00:23:43,620 simplemente no pasó nada. 528 00:23:43,620 --> 00:23:47,109 ¿Por qué ocurrió esto? 529 00:23:47,109 --> 00:23:50,150 ¿Cómo lo podemos solucionar, incluso si sabemos muy poco de 530 00:23:50,150 --> 00:23:52,300 Python? 531 00:23:52,300 --> 00:23:53,470 ¿Eso fue una mano, o no? 532 00:23:53,470 --> 00:23:54,130 ¿No? 533 00:23:54,130 --> 00:23:55,210 OK. 534 00:23:55,210 --> 00:23:55,790 ¿Sí? 535 00:23:55,790 --> 00:23:57,272 PÚBLICO: ¿Hay un salto de línea? 536 00:23:57,272 --> 00:23:58,730 DAVID: ¿Hay un salto de línea? 537 00:23:58,730 --> 00:23:59,450 Eso está bien. 538 00:23:59,450 --> 00:24:01,520 Solo trataba de que todo estuviera alineado, 539 00:24:01,520 --> 00:24:02,395 pero ese no es el problema, 540 00:24:02,395 --> 00:24:06,110 todas las sangrías son correctas, lo cual es importante para la estética. 541 00:24:06,110 --> 00:24:06,807 Sí. 542 00:24:06,807 --> 00:24:08,390 PÚBLICO: No llamamos a la función. 543 00:24:08,390 --> 00:24:09,590 DAVID: No llamamos a la función. 544 00:24:09,590 --> 00:24:12,590 Y aquí es donde Python es un poco diferente de C, pues recordemos que en C 545 00:24:12,590 --> 00:24:14,540 main se llama de manera automática para nosotros. 546 00:24:14,540 --> 00:24:17,630 Hace muchos años, los humanos decidieron que ese sería el nombre de una función. 547 00:24:17,630 --> 00:24:21,410 Sobre la línea 6, en Python, el llamar de algún modo a main solo es una convención 548 00:24:21,410 --> 00:24:24,260 pues podría haberla llamado foo, bar o con cualquier otra palabra 549 00:24:24,260 --> 00:24:25,760 ya que no tiene ningún significado en específico. 550 00:24:25,760 --> 00:24:28,010 Si queremos llamar a main en Python 551 00:24:28,010 --> 00:24:29,760 tenemos que hacer algo como eso. 552 00:24:29,760 --> 00:24:32,720 Creo que desde el principio es una de las distracciones más tontas. 553 00:24:32,720 --> 00:24:34,340 Pero tenemos que decir esto: 554 00:24:34,340 --> 00:24:40,270 if __name__ == "__main__": 555 00:24:40,270 --> 00:24:43,640 main( ) 556 00:24:43,640 --> 00:24:47,750 Para resumir, cuando ejecutamos el intérprete de Python en un archivo, 557 00:24:47,750 --> 00:24:52,610 como lo hicimos con Python, espacio, int.py o hello.py, 558 00:24:52,610 --> 00:24:57,320 hay una variable global especial que nuestro programa puede llamar: 559 00:24:57,320 --> 00:25:00,290 __name__. 560 00:25:00,290 --> 00:25:04,730 Si ese nombre predeterminado pasa a ser __main__, 561 00:25:04,730 --> 00:25:10,860 por ende, sabemos que podemos llamar a cualquier función que deseemos 562 00:25:10,860 --> 00:25:11,700 de manera predeterminada. 563 00:25:11,700 --> 00:25:13,850 Así que, de la misma manera como lo hicimos en la primera semana, 564 00:25:13,850 --> 00:25:17,290 donde pasamos por alto ciertos detalles que no era tan interesantes. 565 00:25:17,290 --> 00:25:20,510 Las líneas 11 y 12, por ahora, no las consideraremos interesantes, 566 00:25:20,510 --> 00:25:22,970 pero, así iniciaremos estos programas. 567 00:25:22,970 --> 00:25:27,800 Ahora, si ejecuto: python int.py, y escribo un gran número 568 00:25:27,800 --> 00:25:30,005 obtengo: hello, 42. 569 00:25:30,005 --> 00:25:32,870 Ese es el sentido de la vida, el universo, y de todo. 570 00:25:32,870 --> 00:25:35,495 Hagamos algo más poderoso 571 00:25:35,495 --> 00:25:37,370 que obtener un único entero del usuario. 572 00:25:37,370 --> 00:25:40,610 Para continuar, cerraré este y cerraré este otro 573 00:25:40,610 --> 00:25:47,430 y abriré ints.c, después dividiré mi pantalla en dos ventanas, 574 00:25:47,430 --> 00:25:48,950 y abramos ints.c. 575 00:25:48,950 --> 00:25:53,720 Este fue un poco diferente porque hicimos algo de aritmética, 576 00:25:53,720 --> 00:25:57,260 aquí habrá otra diferencia con Python. 577 00:25:57,260 --> 00:26:00,410 Esto es lo que hicimos en C, ¿qué fue lo curioso o lo que vale la pena 578 00:26:00,410 --> 00:26:03,747 mencionar de las matemáticas en C? 579 00:26:03,747 --> 00:26:06,830 ¿Cuál de estos no se comportó como esperaríamos en el mundo real? 580 00:26:06,830 --> 00:26:10,030 581 00:26:10,030 --> 00:26:10,830 ¿La división? 582 00:26:10,830 --> 00:26:11,330 Sí, ¿por qué? 583 00:26:11,330 --> 00:26:14,465 ¿Qué hizo la división? 584 00:26:14,465 --> 00:26:16,390 Si, disminuyó, redondeó, 585 00:26:16,390 --> 00:26:19,910 o eliminó el valor al desaparecer todo después del punto decimal. 586 00:26:19,910 --> 00:26:23,410 De modo que, en la línea 18, donde tal y tal, está dividida por tal y tal, 587 00:26:23,410 --> 00:26:24,680 es tal y tal. 588 00:26:24,680 --> 00:26:27,040 Y solo dijimos x dividido por y. 589 00:26:27,040 --> 00:26:31,180 Si por ejemplo, en la primaria dividimos 1 entre 2, con suerte, 590 00:26:31,180 --> 00:26:34,120 nos daría el valor de 1/2 o 0.5. 591 00:26:34,120 --> 00:26:35,620 En vez de eso, ¿qué valor se calcula en C? 592 00:26:35,620 --> 00:26:36,370 PÚBLICO: El cero. 593 00:26:36,370 --> 00:26:37,120 DAVID: El cero. 594 00:26:37,120 --> 00:26:40,290 En C se calcula truncado a un entero, al entero más cercano 595 00:26:40,290 --> 00:26:43,990 sin el punto decimal que sería 0, porque 0.5 realmente es 0.5, 596 00:26:43,990 --> 00:26:45,760 es por eso que tuvimos ese efecto. 597 00:26:45,760 --> 00:26:48,950 En Python, las cosas serán similares 598 00:26:48,950 --> 00:26:53,800 como un tipo de función o un error que se arregló. 599 00:26:53,800 --> 00:26:56,920 En Python, a continuación, abriré un ejemplo 600 00:26:56,920 --> 00:27:01,000 Escribí ints.py, por adelantado, que es 601 00:27:01,000 --> 00:27:02,810 algo que lucirá así. 602 00:27:02,810 --> 00:27:07,330 El equivalente de Python, que está más o menos alineado, 603 00:27:07,330 --> 00:27:08,809 luce un poco diferente. 604 00:27:08,809 --> 00:27:11,600 Hay algunas distracciones porque están todas esas cadenas f 605 00:27:11,600 --> 00:27:12,640 en el camino. 606 00:27:12,640 --> 00:27:15,100 Prestemos atención a como se insertan las x y las y. 607 00:27:15,100 --> 00:27:19,580 ¿Aparentemente es una nueva función aritmética en Python? 608 00:27:19,580 --> 00:27:20,940 Se eliminó la división. 609 00:27:20,940 --> 00:27:24,500 Este era el término más apropiado para lo que C hizo todo este tiempo. 610 00:27:24,500 --> 00:27:29,180 Cuando usamos la diagonal en C, dividimos un número entre otro, 611 00:27:29,180 --> 00:27:32,210 se divide y luego se redondea al entero más cercano. 612 00:27:32,210 --> 00:27:34,910 Si queremos la misma función de la vieja escuela en Python 613 00:27:34,910 --> 00:27:38,280 usaremos el símbolo //, que no se debe confundir con el comentario en C. 614 00:27:38,280 --> 00:27:42,570 Si queremos que una división funcione como en la primaria, 615 00:27:42,570 --> 00:27:44,660 se usará solo la diagonal. 616 00:27:44,660 --> 00:27:47,520 Son cuestiones de menor importancia, pero que debemos tener en cuenta. 617 00:27:47,520 --> 00:27:51,920 Si ejecutamos esto en Python, iremos a source 8, 618 00:27:51,920 --> 00:27:57,590 después al directorio de las semanas, a la week/1 y ejecutamos: python ints.py, 619 00:27:57,590 --> 00:28:00,230 ahora veremos x: 1 y y: 2. 620 00:28:00,230 --> 00:28:05,240 Aquí están todos los valores que esperaríamos ver. 621 00:28:05,240 --> 00:28:05,870 Muy bien. 622 00:28:05,870 --> 00:28:10,280 No nos detendremos mucho y avanzaremos hacia algo 623 00:28:10,280 --> 00:28:12,450 más poderoso como las condiciones. 624 00:28:12,450 --> 00:28:15,950 Si queremos hacer algo solo de manera condicional en Python, 625 00:28:15,950 --> 00:28:21,020 se expondrá en mi navegador como esto. Para continuar, diré: 626 00:28:21,020 --> 00:28:23,720 conditions.py. 627 00:28:23,720 --> 00:28:28,890 Lo siento, conditions.c que alguna vez lució así. 628 00:28:28,890 --> 00:28:32,900 En este ejemplo, consideren que tenemos 629 00:28:32,900 --> 00:28:35,510 un programa que obtiene dos enteros del usuario, 630 00:28:35,510 --> 00:28:38,720 después compara dos veces a x y y, y al final 631 00:28:38,720 --> 00:28:41,840 imprime si son mayores, menores o iguales que. 632 00:28:41,840 --> 00:28:44,610 Aquí en la derecha, haremos esto desde cero. 633 00:28:44,610 --> 00:28:47,400 A continuación, guardaré esto como conditions.py. 634 00:28:47,400 --> 00:28:49,400 En la parte superior, ¿qué es lo que aparentemente 635 00:28:49,400 --> 00:28:52,595 necesito primero? 636 00:28:52,595 --> 00:28:54,080 Sí, la biblioteca de CS50. 637 00:28:54,080 --> 00:28:58,430 Lo que queremos esta vez es: from cs50 import get_int. 638 00:28:58,430 --> 00:29:01,730 Ahora, ¿cómo obtengo un entero? 639 00:29:01,730 --> 00:29:04,389 O, ¿cuál sería la traducción de la línea 9 desde el lado izquierdo 640 00:29:04,389 --> 00:29:05,930 al derecho de la pantalla? 641 00:29:05,930 --> 00:29:11,290 642 00:29:11,290 --> 00:29:14,385 x = get_int("x: ") 643 00:29:14,385 --> 00:29:17,000 644 00:29:17,000 --> 00:29:19,730 OK, ¿qué sigue después, si lo alineo más o menos aquí? 645 00:29:19,730 --> 00:29:23,060 y = get_int("y: ") 646 00:29:23,060 --> 00:29:26,120 ¿Y que hay aquí abajo? 647 00:29:26,120 --> 00:29:26,870 La condición 648 00:29:26,870 --> 00:29:30,302 Pero, ¿si x es menor que y? 649 00:29:30,302 --> 00:29:31,510 No son necesarios los paréntesis, 650 00:29:31,510 --> 00:29:33,551 no está mal ponerlos pero es innecesario, 651 00:29:33,551 --> 00:29:36,810 y ahora introduce una palabra en nuestra terminología 652 00:29:36,810 --> 00:29:38,505 que no es de Python, por así decirlo. 653 00:29:38,505 --> 00:29:40,130 Si no los necesitamos, no los pondremos. 654 00:29:40,130 --> 00:29:42,750 Si x es, de hecho, menor que y, ¿qué queremos hacer? 655 00:29:42,750 --> 00:29:47,760 Queremos imprimir x es menor que y, print("x is less tan y \ n"), ¿sí? 656 00:29:47,760 --> 00:29:48,410 No. 657 00:29:48,410 --> 00:29:48,944 OK. 658 00:29:48,944 --> 00:29:49,610 Muy bien, bien. 659 00:29:49,610 --> 00:29:53,000 Entonces, else if x > y: 660 00:29:53,000 --> 00:29:54,170 OK, bien. 661 00:29:54,170 --> 00:29:54,670 Cierto. 662 00:29:54,670 --> 00:30:02,900 Parece tonto el elif, luego imprimamos print('x is greater than y'). 663 00:30:02,900 --> 00:30:05,090 Y como nota aparte, eso lo hice accidentalmente, 664 00:30:05,090 --> 00:30:09,800 pero en Python podemos usar comillas dobles o también comillas simples, 665 00:30:09,800 --> 00:30:13,242 ambas están bien, pero en C, las comillas simples tienen un significado específico, 666 00:30:13,242 --> 00:30:13,950 ¿qué significan? 667 00:30:13,950 --> 00:30:14,870 PÚBLICO: Un carácter. 668 00:30:14,870 --> 00:30:15,620 DAVID: Un carácter. 669 00:30:15,620 --> 00:30:16,970 Son para caracteres individuales 670 00:30:16,970 --> 00:30:19,130 y las comillas dobles significan cadenas, secuencias 671 00:30:19,130 --> 00:30:23,300 de caracteres, lo cual implica a cero o más caracteres seguidos por \ 0. 672 00:30:23,300 --> 00:30:24,747 En Python, todo eso se ha ido, 673 00:30:24,747 --> 00:30:26,705 las comillas simples y las dobles son equivalentes. 674 00:30:26,705 --> 00:30:30,140 Casi siempre uso comillas dobles por consistencia, como deberían hacerlo, 675 00:30:30,140 --> 00:30:32,810 para mantener la consistencia dentro de sus propios archivos, 676 00:30:32,810 --> 00:30:36,050 pero algunas veces es útil usar uno u otro tipo si anidamos, 677 00:30:36,050 --> 00:30:39,210 por ejemplo, comillas, como tú podría tener de vez hace algún tiempo en C 678 00:30:39,210 --> 00:30:39,710 OK. 679 00:30:39,710 --> 00:30:45,140 Por último, else: print("x is equal to y") 680 00:30:45,140 --> 00:30:46,884 De este modo queda más limpio 681 00:30:46,884 --> 00:30:48,800 y en realidad no necesito todo este espacio en blanco, 682 00:30:48,800 --> 00:30:51,410 así que reduzcámoslo un poco más 683 00:30:51,410 --> 00:30:56,330 y así tendremos 11 líneas, cuando antes teníamos casi 27. 684 00:30:56,330 --> 00:30:59,180 Pero para ser sinceros, omití algo. 685 00:30:59,180 --> 00:31:01,149 ¿Qué fue lo que omití? 686 00:31:01,149 --> 00:31:03,440 Sí, no hice todo eso de llamar a la función 687 00:31:03,440 --> 00:31:04,564 y tampoco mencioné a main, 688 00:31:04,564 --> 00:31:07,790 aunque en Python esto no es estrictamente necesario. 689 00:31:07,790 --> 00:31:11,210 Si vamos a interpretar un archivo que contiene un código de Python 690 00:31:11,210 --> 00:31:15,320 y es un programa tan simple que no requiere que factoricemos el código 691 00:31:15,320 --> 00:31:18,440 y lo organicemos en funciones separadas, entonces no lo haremos 692 00:31:18,440 --> 00:31:21,290 Si esto sería lo que llamamos un script de la línea de comandos, 693 00:31:21,290 --> 00:31:25,250 un programa que tiene líneas de código que solo podemos ejecutar 694 00:31:25,250 --> 00:31:25,910 desde esa línea, 695 00:31:25,910 --> 00:31:30,320 por ello, si voy a este directorio y ejecuto python conditions.py, Enter. 696 00:31:30,320 --> 00:31:32,240 x será 1, y será 2 697 00:31:32,240 --> 00:31:33,560 escribimos que: x is less than y 698 00:31:33,560 --> 00:31:34,340 y eso es todo, 699 00:31:34,340 --> 00:31:38,450 como lo dije antes, no necesito molestarme en hacer todo esto, 700 00:31:38,450 --> 00:31:41,304 escribo, def main( ): y luego podría ir aquí, 701 00:31:41,304 --> 00:31:43,470 pero si no sabían de esto y lo útil que es, 702 00:31:43,470 --> 00:31:45,803 especialmente, para Python, podemos resaltar las líneas 703 00:31:45,803 --> 00:31:46,880 y tabularlas todas a la vez. 704 00:31:46,880 --> 00:31:49,760 Podría hacerlo así, pero necesitaría esto, lo cual probablemente 705 00:31:49,760 --> 00:31:53,990 tendríamos que buscar cómo recordarlo si es la primera vez, 706 00:31:53,990 --> 00:31:57,230 En este caso, no hay ningún valor para hacerlo, 707 00:31:57,230 --> 00:32:00,685 pero puede estar allí, en caso de que se necesite. 708 00:32:00,685 --> 00:32:02,060 A continuación, borraré eso 709 00:32:02,060 --> 00:32:04,830 y volveremos a importar de uno al otro. 710 00:32:04,830 --> 00:32:05,330 Muy bien, 711 00:32:05,330 --> 00:32:07,130 de modo que esas podrían ser las condiciones 712 00:32:07,130 --> 00:32:09,540 y veamos si no podemos... 713 00:32:09,540 --> 00:32:10,740 ah, el noswitch allí. 714 00:32:10,740 --> 00:32:11,990 Echémosle un vistazo a este, 715 00:32:11,990 --> 00:32:15,050 déjenme abrirlo y en vez de compararlos a todos lado a lado, 716 00:32:15,050 --> 00:32:18,780 ahora abriré esto que se llama noswitch.py, 717 00:32:18,780 --> 00:32:23,642 el cual nos recordará a un programa que ejecutamos hace poco, el noswitch.c 718 00:32:23,642 --> 00:32:28,490 Y tal vez podamos deducir lo que hace esto a partir de los comentarios. 719 00:32:28,490 --> 00:32:31,160 ¿Qué es lo que hace este programa en Inglés? 720 00:32:31,160 --> 00:32:33,875 Porque el #Logical operators en la parte superior, no es tan explícito. 721 00:32:33,875 --> 00:32:36,760 722 00:32:36,760 --> 00:32:37,341 ¿Qué es eso? 723 00:32:37,341 --> 00:32:41,260 724 00:32:41,260 --> 00:32:41,760 Sí. 725 00:32:41,760 --> 00:32:44,790 Si alguna vez interactuamos con un programa que nos solicitó una línea 726 00:32:44,790 --> 00:32:47,520 de tipo sí o no, aquí hay un código con el cual podríamos implementarlo 727 00:32:47,520 --> 00:32:50,290 y lo podríamos hacer en C. Aquí solo comparamos los caracteres, 728 00:32:50,290 --> 00:32:52,290 Pero existen algunas diferencias si pensamos 729 00:32:52,290 --> 00:32:54,660 en cómo podríamos implementar esto en C, 730 00:32:54,660 --> 00:32:56,730 incluso si no recordamos este programa en específico. 731 00:32:56,730 --> 00:32:59,450 De este modo, importo mi biblioteca justo aquí 732 00:32:59,450 --> 00:33:01,740 y esta vez llamo a get_char, la cual 733 00:33:01,740 --> 00:33:03,832 también se encuentra en la biblioteca de CS50 para Python. 734 00:33:03,832 --> 00:33:05,790 Luego observen que solo hay un par de cosas 735 00:33:05,790 --> 00:33:07,860 sintácticamente diferentes aquí abajo, 736 00:33:07,860 --> 00:33:11,550 además de los dos puntos, la sangría y demás, ¿qué otra cosa notamos? 737 00:33:11,550 --> 00:33:13,790 Sí. 738 00:33:13,790 --> 00:33:14,870 Sí. 739 00:33:14,870 --> 00:33:17,270 Gracias al cielo, ahora podemos decir lo que queremos, 740 00:33:17,270 --> 00:33:20,660 si queremos hacer una cosa u otra, literalmente decimos "or" 741 00:33:20,660 --> 00:33:22,340 y si en lugar de eso tratáramos, 742 00:33:22,340 --> 00:33:26,000 aunque aquí no tenga sentido, de hacer la conjunción entre dos cosas, 743 00:33:26,000 --> 00:33:28,250 esto y eso, literalmente podríamos decir "and", 744 00:33:28,250 --> 00:33:30,800 en lugar de las dos barras verticales o los dos símbolos ampersand, 745 00:33:30,800 --> 00:33:33,410 esta es otra leve diferencia con Python. 746 00:33:33,410 --> 00:33:37,220 Ahora veamos otro ejemplo que nos recuerda a los anteriores, 747 00:33:37,220 --> 00:33:39,950 este se llama return.py 748 00:33:39,950 --> 00:33:42,260 Este es un ejemplo, más 749 00:33:42,260 --> 00:33:45,272 compatible para tener una función main, porque ahora 750 00:33:45,272 --> 00:33:47,980 comenzaré por organizar mi código en diferentes funciones. 751 00:33:47,980 --> 00:33:52,850 Así que aquí estamos importando la función get_int desde la biblioteca CS50. 752 00:33:52,850 --> 00:33:56,600 Aquí tengo mi función principal que simplemente dice x = get_int 753 00:33:56,600 --> 00:33:58,317 y luego imprime el cuadrado de x. 754 00:33:58,317 --> 00:34:00,650 ¿Cómo van a definir su propia función personalizada 755 00:34:00,650 --> 00:34:02,270 en Python que no sea solo main? 756 00:34:02,270 --> 00:34:07,100 En la línea 11 es cómo se definiría una función llamada square, 757 00:34:07,100 --> 00:34:09,409 que aparentemente toma un argumento llamado n, 758 00:34:09,409 --> 00:34:14,989 podría llamarlo de cualquier manera, luego dos puntos, return n**2. 759 00:34:14,989 --> 00:34:16,400 Aquí tenemos algunas características nuevas. 760 00:34:16,400 --> 00:34:19,400 Pero no es la gran cosa, una vez que miran estas características 761 00:34:19,400 --> 00:34:21,500 en un manual o en un curso. 762 00:34:21,500 --> 00:34:24,369 ¿Qué está haciendo ** probablemente? 763 00:34:24,369 --> 00:34:25,286 PÚBLICO: Raíz cuadrada. 764 00:34:25,286 --> 00:34:26,493 DAVID: No, no es una raíz cuadrada. 765 00:34:26,493 --> 00:34:27,449 La potencia de... sí. 766 00:34:27,449 --> 00:34:30,370 Así que n**2 es solo n elevado a la potencia de 2. 767 00:34:30,370 --> 00:34:34,449 Esa no es una característica que tuviéramos en C. Pero que sí tenemos en Python. 768 00:34:34,449 --> 00:34:40,080 ¿y qué es esta línea 12 en verde que usa esas raras comillas dobles? 769 00:34:40,080 --> 00:34:41,350 Sí, es un comentario. 770 00:34:41,350 --> 00:34:43,308 Y es un tipo de comentario distinto de los que hemos 771 00:34:43,308 --> 00:34:46,420 visto antes porque en mi ejemplo anterior, tuve algunos comentarios. 772 00:34:46,420 --> 00:34:49,659 Recuerden que hace un momento, en conditions.py, 773 00:34:49,659 --> 00:34:52,179 teníamos muchos comentarios. 774 00:34:52,179 --> 00:34:53,380 Pide al usuario una x. 775 00:34:53,380 --> 00:34:54,310 Pide al usuario una y. 776 00:34:54,310 --> 00:34:55,420 Compara x y y. 777 00:34:55,420 --> 00:34:57,650 Mientras que en C usábamos la diagonal doble, 778 00:34:57,650 --> 00:35:01,160 Python, desafortunadamente la usa para la división de piso, por así decirlo. 779 00:35:01,160 --> 00:35:04,060 Así que en su lugar solo usamos el hashtag o el signo de libra 780 00:35:04,060 --> 00:35:09,370 para especificar una línea que debería ser vista como un comentario. 781 00:35:09,370 --> 00:35:11,080 Pero aquí hay algo un poco diferente 782 00:35:11,080 --> 00:35:12,913 Y no pensaremos mucho en ello por el momento. 783 00:35:12,913 --> 00:35:15,730 Python tiene diferentes tipos de comentarios, uno de los cuales es este. 784 00:35:15,730 --> 00:35:18,820 Técnicamente se le llama docstring o cadena de documentación. 785 00:35:18,820 --> 00:35:23,200 Y lo bueno de Python, al igual que en lenguajes como Java y otros, 786 00:35:23,200 --> 00:35:25,720 es que pueden poner comentarios en su código 787 00:35:25,720 --> 00:35:30,910 que los programas especiales pueden leer y luego generan documentación para uno. 788 00:35:30,910 --> 00:35:34,030 Si alguna vez estudiaron AP CS y vieron un Javadoc, 789 00:35:34,030 --> 00:35:36,040 esta era una forma de comentar sus métodos 790 00:35:36,040 --> 00:35:39,380 y su código en Java utilizaba signos raros como @ y otra sintaxis, 791 00:35:39,380 --> 00:35:42,730 así, si ejecutaban un comando especial, generaba un manual de usuario para todas 792 00:35:42,730 --> 00:35:45,997 sus funciones y le decía a sus colegas, amigos o profesores 793 00:35:45,997 --> 00:35:48,580 exactamente cuáles eran todas sus funciones, cuáles eran sus argumentos, 794 00:35:48,580 --> 00:35:50,570 cuáles eran sus valores de retorno y todo eso. 795 00:35:50,570 --> 00:35:54,880 Del mismo modo, en Python pueden usar esas extrañas comillas, comillas, comillas, 796 00:35:54,880 --> 00:35:57,340 docstrings para documentar su función. 797 00:35:57,340 --> 00:36:00,820 Mientras que en C, nuestro estilo ha sido poner comillas arriba de las funciones, 798 00:36:00,820 --> 00:36:04,360 en Python las ponemos como la primera línea que está adentro 799 00:36:04,360 --> 00:36:07,530 y con sangría al interior de la función. 800 00:36:07,530 --> 00:36:08,090 Muy bien. 801 00:36:08,090 --> 00:36:12,440 Vamos a tratar de importar otra vez un programa desde el código, 802 00:36:12,440 --> 00:36:19,650 recordando la primera semana en C cuando vimos este programa. 803 00:36:19,650 --> 00:36:21,160 Así que hay bastante... 804 00:36:21,160 --> 00:36:21,969 Uy, un spoiler. 805 00:36:21,969 --> 00:36:22,760 No miren eso. 806 00:36:22,760 --> 00:36:25,410 807 00:36:25,410 --> 00:36:27,230 Afortunadamente no lo arruinó. 808 00:36:27,230 --> 00:36:32,260 Este programa en C, lo vimos en la primera semana, get_positive_int. 809 00:36:32,260 --> 00:36:34,520 Y su propósito era escribir un programa que 810 00:36:34,520 --> 00:36:36,839 obtuviera en sí mismo un entero positivo del usuario, 811 00:36:36,839 --> 00:36:37,880 no era tan interesante. 812 00:36:37,880 --> 00:36:40,410 Pero fue una oportunidad para presentar algunas cosas. 813 00:36:40,410 --> 00:36:43,610 Primero presentamos esta línea 6 hace varias semanas, 814 00:36:43,610 --> 00:36:44,900 la cual se conoce como prototipo. 815 00:36:44,900 --> 00:36:48,890 ¿Y cuál era el propósito de tener ese prototipo de función allá arriba? 816 00:36:48,890 --> 00:36:51,080 Sí, declaran la función, pero, ¿por qué? 817 00:36:51,080 --> 00:36:53,960 Porque ya está implementado aquí abajo en la línea 15. 818 00:36:53,960 --> 00:36:57,631 PÚBLICO: la forma en que se ejecuta el programa tiene que estar en orden 819 00:36:57,631 --> 00:36:58,130 o algo así. 820 00:36:58,130 --> 00:36:58,700 DAVID: Sí. 821 00:36:58,700 --> 00:37:00,741 Por la forma en que se ejecuta el programa y, francamente, 822 00:37:00,741 --> 00:37:04,460 debido a qué tipo de cosa ingenua o tonta que el clang es por diseño, 823 00:37:04,460 --> 00:37:08,460 no sabe que una función existe hasta que realmente la ve. 824 00:37:08,460 --> 00:37:11,810 El problema es que si en C tenemos main, dentro del cual 825 00:37:11,810 --> 00:37:13,940 debe funcionar como get_positive_int, 826 00:37:13,940 --> 00:37:16,434 pero no se implementa hasta algunas líneas después, 827 00:37:16,434 --> 00:37:19,100 clang será muy tonto y simplemente no sabrá que existe. 828 00:37:19,100 --> 00:37:20,766 Y no va a compilar su código. 829 00:37:20,766 --> 00:37:24,309 Así, este prototipo, como lo llamamos, es una especie de señuelo, una pista que 830 00:37:24,309 --> 00:37:25,850 no implementa toda la función. 831 00:37:25,850 --> 00:37:29,480 Simplemente muestra el compilador con su tipo de retorno, sus tipos 832 00:37:29,480 --> 00:37:32,450 y el orden de los parámetros, de modo que haya suficiente información 833 00:37:32,450 --> 00:37:36,200 para luego solo confiar en que si simplemente compilo main a ciegas, 834 00:37:36,200 --> 00:37:39,480 eventualmente veré la implementación de la función. 835 00:37:39,480 --> 00:37:41,670 Entonces puedo compilar sus bits también. 836 00:37:41,670 --> 00:37:44,479 Por ello, en C llamamos a get_positive_int, 837 00:37:44,479 --> 00:37:45,770 lo pusimos en una línea, 838 00:37:45,770 --> 00:37:48,954 lo almacenamos en una variable llamada i y luego lo imprimimos. 839 00:37:48,954 --> 00:37:51,620 Y luego, para implementarlo usamos una construcción familiar 840 00:37:51,620 --> 00:37:53,090 que ya hemos usado en otros programas. 841 00:37:53,090 --> 00:37:56,092 Cada vez que quieran pedirle una entrada al usuario 842 00:37:56,092 --> 00:37:57,800 y quieran seguir molestándolo 843 00:37:57,800 --> 00:38:00,890 hasta que coopere con las condiciones que ustedes pongan, 844 00:38:00,890 --> 00:38:03,200 usen el bucle llamado do-while. 845 00:38:03,200 --> 00:38:07,442 Y recuerden, ¿por qué el ciclo do-while, es distinto del ciclo while? 846 00:38:07,442 --> 00:38:09,150 PÚBLICO: Porque se ejecuta al menos una vez. 847 00:38:09,150 --> 00:38:10,260 PÚBLICO: se ejecuta al menos una vez, lo cual 848 00:38:10,260 --> 00:38:11,968 parece tener un sentido intuitivo si 849 00:38:11,968 --> 00:38:13,600 queremos pedirle algo al usuario. 850 00:38:13,600 --> 00:38:15,930 Y después, si el usuario no coopera, solo entonces 851 00:38:15,930 --> 00:38:17,370 le volverán a hacer la solicitud. 852 00:38:17,370 --> 00:38:20,430 En contraste con un ciclo while, esto va a suceder una y otra 853 00:38:20,430 --> 00:38:22,920 y otra vez, sin importar qué, desde el primer momento. 854 00:38:22,920 --> 00:38:26,280 Ahora veamos si no podemos convertirlo o importarlo, 855 00:38:26,280 --> 00:38:28,500 por decirlo así, a Python. 856 00:38:28,500 --> 00:38:33,580 A continuación guardaré un nuevo archivo llamado positive.py 857 00:38:33,580 --> 00:38:39,560 y luego haré lo mismo que hice antes en main, 858 00:38:39,560 --> 00:38:44,430 entonces pondré, digamos, from cs50 import get_int, 859 00:38:44,430 --> 00:38:46,000 porque lo necesito. 860 00:38:46,000 --> 00:38:48,550 Luego voy a aplicar mi método main aquí 861 00:38:48,550 --> 00:38:51,900 Y luego dentro de main, al igual que en el lado izquierdo, 862 00:38:51,900 --> 00:38:55,830 Voy a escribir i = get_positive_int... 863 00:38:55,830 --> 00:38:58,200 ("positive integer, please: "); 864 00:38:58,200 --> 00:38:59,700 Se va a salir un poco del recuadro, 865 00:38:59,700 --> 00:39:00,570 está bien. 866 00:39:00,570 --> 00:39:03,111 A continuación imprimiré, recuerden, 867 00:39:03,111 --> 00:39:07,430 tan solo una cadena f donde el marcador de posición sea i, 868 00:39:07,430 --> 00:39:09,180 aunque, francamente, es un poco tonto 869 00:39:09,180 --> 00:39:13,140 crear una cadena que no tenga otra cosa que el valor que queremos imprimir. 870 00:39:13,140 --> 00:39:15,430 En Python es bastante bueno, solo impriman lo que quieran 871 00:39:15,430 --> 00:39:17,380 y eso simplifica el argumento. 872 00:39:17,380 --> 00:39:22,720 Ahora nos falta implementar, def get_positive_int(prompt) 873 00:39:22,720 --> 00:39:25,160 el cual tomará una solicitud como su entrada. 874 00:39:25,160 --> 00:39:29,850 Y no estoy especificando el tipo de datos de la solicitud, que es una cadena, 875 00:39:29,850 --> 00:39:32,250 tampoco estoy especificando el tipo de retorno de esta función, 876 00:39:32,250 --> 00:39:34,920 pero ambos existen por debajo del agua. 877 00:39:34,920 --> 00:39:38,130 Antes, para obtener una variable ponía algo como esto, 878 00:39:38,130 --> 00:39:39,780 int n; con punto y coma. 879 00:39:39,780 --> 00:39:41,910 pero sé que no necesito el punto y coma. 880 00:39:41,910 --> 00:39:43,560 Sé que no necesito el tipo de datos. 881 00:39:43,560 --> 00:39:47,490 Y se ve algo tonto poner una variable para necesitarla. 882 00:39:47,490 --> 00:39:49,050 En Python no se necesita hacer esto, 883 00:39:49,050 --> 00:39:52,050 Si desean usar una variable, simplemente úsenla. 884 00:39:52,050 --> 00:39:55,470 Desafortunadamente, mientras cualquier otra función que hayamos visto en Python 885 00:39:55,470 --> 00:40:01,200 hasta ahora, se mapean directamente a una función en C, 886 00:40:01,200 --> 00:40:04,500 Python no tiene un do-while. 887 00:40:04,500 --> 00:40:08,430 Tiene el for-in y a while 888 00:40:08,430 --> 00:40:10,770 y tal vez tiene otras cosas que no les he contado, 889 00:40:10,770 --> 00:40:12,600 pero no tiene un do-while. 890 00:40:12,600 --> 00:40:16,020 Sabiendo eso y lo que presentamos hasta ahora, 891 00:40:16,020 --> 00:40:20,190 ¿cómo podemos obtener un int del usuario, 892 00:40:20,190 --> 00:40:23,931 asegurarnos de que sea positivo y pedirle uno sí y solo si 893 00:40:23,931 --> 00:40:24,430 no lo es? 894 00:40:24,430 --> 00:40:27,710 895 00:40:27,710 --> 00:40:31,240 Dicho de otro modo, ¿cómo haríamos esto en C si quitamos 896 00:40:31,240 --> 00:40:32,530 la construcción do-while? 897 00:40:32,530 --> 00:40:36,720 898 00:40:36,720 --> 00:40:37,630 ¿Signos de admiración? 899 00:40:37,630 --> 00:40:38,130 OK. 900 00:40:38,130 --> 00:40:41,756 Tal vez podríamos invertir algo usándolo lógicamente. 901 00:40:41,756 --> 00:40:43,380 PÚBLICO: Puedes utilizar un bucle while. 902 00:40:43,380 --> 00:40:44,370 DAVID: Podríamos utilizar un bucle while. 903 00:40:44,370 --> 00:40:44,870 ¿Cómo? 904 00:40:44,870 --> 00:40:50,916 PÚBLICO: Pondrías, while prompt es menor que 1. 905 00:40:50,916 --> 00:40:52,290 DAVID: while prompt es... 906 00:40:52,290 --> 00:40:57,160 OK, entonces el prompt es la cadena que vamos a mostrarle al usuario. 907 00:40:57,160 --> 00:40:59,520 Entonces no sería prompt, creo. 908 00:40:59,520 --> 00:41:04,062 Tal vez i o n, para ser consistentes con el otro lado. 909 00:41:04,062 --> 00:41:04,770 ¿Saben qué? 910 00:41:04,770 --> 00:41:06,324 ¿Por qué no... qué pasa con esto? 911 00:41:06,324 --> 00:41:07,740 ¿Qué pasa si... saben qué? 912 00:41:07,740 --> 00:41:09,266 Sé que necesito un bucle. 913 00:41:09,266 --> 00:41:11,640 Esta es, por mucho, la forma más fácil de obtener un bucle, ¿cierto? 914 00:41:11,640 --> 00:41:13,350 Es infinito, lo cual no es bueno, 915 00:41:13,350 --> 00:41:15,480 pero recuerden que puedo romper los bucles. 916 00:41:15,480 --> 00:41:17,800 ¿Qué pasa si hago algo como esto? 917 00:41:17,800 --> 00:41:22,830 ¿Qué pasa si pongo n = get_ get_int(prompt)? 918 00:41:22,830 --> 00:41:25,200 Y luego, ¿qué quiero hacer? 919 00:41:25,200 --> 00:41:26,680 Estoy dentro de un bucle infinito. 920 00:41:26,680 --> 00:41:29,763 Así que esto va a seguir sucediendo, y sucediendo, y sucediendo hasta... 921 00:41:29,763 --> 00:41:34,060 922 00:41:34,060 --> 00:41:35,390 ¿Es positivo? 923 00:41:35,390 --> 00:41:37,280 Python no es tan fácil de usar. 924 00:41:37,280 --> 00:41:39,100 No podemos decir solo eso. 925 00:41:39,100 --> 00:41:40,876 ¿Pero qué podemos decir? 926 00:41:40,876 --> 00:41:42,280 PÚBLICO: Mayor que 1. 927 00:41:42,280 --> 00:41:43,840 DAVID: Mayor que... 928 00:41:43,840 --> 00:41:44,700 Cerca. 929 00:41:44,700 --> 00:41:45,840 PÚBLICO: Igual a. 930 00:41:45,840 --> 00:41:47,048 DAVID: OK, está bien. 931 00:41:47,048 --> 00:41:48,580 Mayor que o igual a uno. 932 00:41:48,580 --> 00:41:49,780 Y luego, ¿qué quiero hacer? 933 00:41:49,780 --> 00:41:50,860 Salir. 934 00:41:50,860 --> 00:41:53,620 Pero no es tan genial como un bucle do-while, 935 00:41:53,620 --> 00:41:55,630 el cual nos da todos estas características, aunque francamente, 936 00:41:55,630 --> 00:41:56,800 nunca fue tan bonito, ¿verdad? 937 00:41:56,800 --> 00:41:59,080 En especial por el hecho de que tuvieron que lidiar con el problema del alcance 938 00:41:59,080 --> 00:42:00,650 poniendo la variable afuera. 939 00:42:00,650 --> 00:42:03,580 En Python, la forma correcta de hacerlo sería algo como esto. 940 00:42:03,580 --> 00:42:07,150 Induzcan un bucle infinito, pero asegúrense de romperlo lógicamente 941 00:42:07,150 --> 00:42:09,220 cuando sea apropiado hacerlo. 942 00:42:09,220 --> 00:42:13,630 Y ahora, si agrego lo último que sigo necesitando. 943 00:42:13,630 --> 00:42:20,110 Entonces, if --name-- == "__main__": y siempre halla algo para copiar y pegar, 944 00:42:20,110 --> 00:42:21,130 llama a main (). 945 00:42:21,130 --> 00:42:27,160 Ahora, en mi ventana de terminal voy a ejecutar python positive.py 946 00:42:27,160 --> 00:42:29,630 y le pondré un 5 negativo. 947 00:42:29,630 --> 00:42:31,210 ¿Y qué tal un 1 negativo? 948 00:42:31,210 --> 00:42:32,330 ¿Y qué tal 0? 949 00:42:32,330 --> 00:42:32,925 ¡Ups! 950 00:42:32,925 --> 00:42:33,550 ¿Qué tal eso? 951 00:42:33,550 --> 00:42:34,420 ¿Qué tal 0? 952 00:42:34,420 --> 00:42:34,972 ¿1? 953 00:42:34,972 --> 00:42:35,471 Hum. 954 00:42:35,471 --> 00:42:38,630 955 00:42:38,630 --> 00:42:40,580 Lo eché a perder. 956 00:42:40,580 --> 00:42:41,600 Obtener nada es interesante. 957 00:42:41,600 --> 00:42:43,590 Es algo así como nuestro nuevo nulo, por así decirlo. 958 00:42:43,590 --> 00:42:46,730 Pero mientras en C el nulo puede, si se usa de manera incorrecta, 959 00:42:46,730 --> 00:42:50,570 bloquear su programa, Python podría, al parecer, imprimirlo. 960 00:42:50,570 --> 00:42:52,766 ¿Dónde me equivoqué? 961 00:42:52,766 --> 00:42:55,272 Sí, no hice que devolviera un valor real. 962 00:42:55,272 --> 00:42:57,980 Y mientras clang podría haber notado algo como esto, Python, 963 00:42:57,980 --> 00:43:01,574 el intérprete, no va a ser tan vigilante cuando se trata de averiguar 964 00:43:01,574 --> 00:43:02,990 si al código le falta algo. 965 00:43:02,990 --> 00:43:05,790 Porque después de todo, nunca dijimos que devolveríamos alguna cosa 966 00:43:05,790 --> 00:43:07,430 y entonces no lo necesitamos estrictamente. 967 00:43:07,430 --> 00:43:12,230 ¿Qué podría hacer en vez de romperlo? 968 00:43:12,230 --> 00:43:14,120 Podría devolver a n aquí 969 00:43:14,120 --> 00:43:19,580 o podría hacer esto de modo equivalente, y asegurarme de que devuelvo a n aquí. 970 00:43:19,580 --> 00:43:22,940 Y otra diferencia que hay en Python también, es el problema del alcance, 971 00:43:22,940 --> 00:43:28,880 no es tan difícil como lo fue en C. Tan pronto haya declarado que n existe 972 00:43:28,880 --> 00:43:32,030 aquí, ahora existe abajo. 973 00:43:32,030 --> 00:43:35,030 A pesar de que fue declarado dentro de esta sangría, 974 00:43:35,030 --> 00:43:38,240 no tiene alcance hacia ese bucle while solamente. 975 00:43:38,240 --> 00:43:41,900 De cualquier forma podríamos hacer que esto funcione. 976 00:43:41,900 --> 00:43:44,570 OK, intentemos ejecutarlo de nuevo. 977 00:43:44,570 --> 00:43:45,440 Entero positivo. 978 00:43:45,440 --> 00:43:46,430 1 negativo. 979 00:43:46,430 --> 00:43:47,070 0. 980 00:43:47,070 --> 00:43:47,639 1. 981 00:43:47,639 --> 00:43:49,430 Y ahora vemos el número 1. 982 00:43:49,430 --> 00:43:49,930 Muy bien. 983 00:43:49,930 --> 00:43:53,460 Haré una pausa aquí, para ver si hay alguna pregunta. 984 00:43:53,460 --> 00:43:54,360 ¿No? 985 00:43:54,360 --> 00:43:54,860 Sí. 986 00:43:54,860 --> 00:43:58,283 PÚBLICO: ¿Se importan cosas desde la biblioteca CS50 de forma individual, 987 00:43:58,283 --> 00:44:00,319 o se importa la biblioteca completa? 988 00:44:00,319 --> 00:44:01,610 DAVID: Ah, buena pregunta. 989 00:44:01,610 --> 00:44:04,401 ¿Se importan cosas desde la biblioteca CS50 de forma individual, 990 00:44:04,401 --> 00:44:06,080 o se importa la biblioteca completa? 991 00:44:06,080 --> 00:44:08,730 Técnicamente pueden importar todo, de la siguiente manera. 992 00:44:08,730 --> 00:44:11,180 Si quieren acceso a toda la biblioteca CS50, 993 00:44:11,180 --> 00:44:12,500 pueden poner asterisco 994 00:44:12,500 --> 00:44:15,990 Y asterisco en programación... bueno, en muchos contextos de computación, 995 00:44:15,990 --> 00:44:17,840 el asterisco suele ser un carácter comodín 996 00:44:17,840 --> 00:44:21,427 y significa todo lo que coincida con esta cadena. 997 00:44:21,427 --> 00:44:23,510 Esto generalmente se considera una mala práctica 998 00:44:23,510 --> 00:44:28,400 porque si el equipo de CS50 les da características o variables 999 00:44:28,400 --> 00:44:32,600 que ustedes no quieren, todas esas funciones se habrán importado, 1000 00:44:32,600 --> 00:44:34,680 a su namespace, por así decirlo. 1001 00:44:34,680 --> 00:44:38,750 Por ejemplo, si la biblioteca CS50 tenía público adentro, 1002 00:44:38,750 --> 00:44:41,570 una variable llamada x, y y z, 1003 00:44:41,570 --> 00:44:45,080 además de funciones como get_string, get_int y get_char, 1004 00:44:45,080 --> 00:44:48,830 su programa tendrá ahora las variables x, y y z. 1005 00:44:48,830 --> 00:44:51,170 Y si tienen sus propias variables llamadas x, y y z, 1006 00:44:51,170 --> 00:44:53,780 taparán esas variables dentro de las nuestras 1007 00:44:53,780 --> 00:44:55,490 y rápidamente se volverá un desorden. 1008 00:44:55,490 --> 00:44:58,550 En general, deben ser un poco más quisquillosos 1009 00:44:58,550 --> 00:45:00,290 e importar solo lo que ustedes quieran. 1010 00:45:00,290 --> 00:45:05,750 Otra convención en Python es no especificarlo de esa manera 1011 00:45:05,750 --> 00:45:08,870 y en vez de ello importar CS50. 1012 00:45:08,870 --> 00:45:11,780 Esto no tiene el mismo efecto de importar 1013 00:45:11,780 --> 00:45:13,940 todas esas palabras clave como get_int y get_string 1014 00:45:13,940 --> 00:45:18,260 en el namespace de sus programas, como la lista de símbolos 1015 00:45:18,260 --> 00:45:19,850 que pueden escribir. 1016 00:45:19,850 --> 00:45:22,020 Pero entonces, lo que debemos hacer es 1017 00:45:22,020 --> 00:45:27,560 prefijar cualquier uso de las funciones en esa biblioteca 1018 00:45:27,560 --> 00:45:30,620 con el ahora familiar, o más familiar, operador punto. 1019 00:45:30,620 --> 00:45:33,020 Pero esta es solo una decisión estilística, 1020 00:45:33,020 --> 00:45:35,264 elegí conscientemente el otro enfoque 1021 00:45:35,264 --> 00:45:38,180 de modo que inicialmente, solo pueden llamar a get_int o get_string, tal como 1022 00:45:38,180 --> 00:45:41,450 lo hicimos en C. Pero técnica y tal vez más convencionalmente 1023 00:45:41,450 --> 00:45:44,210 la gente lo haría para dejar muy en claro que este no es su método get_int, 1024 00:45:44,210 --> 00:45:47,971 sino que es la función get_int de CS50. 1025 00:45:47,971 --> 00:45:48,470 OK. 1026 00:45:48,470 --> 00:45:50,094 ¿Alguna otra pregunta? 1027 00:45:50,094 --> 00:45:50,594 Sí. 1028 00:45:50,594 --> 00:45:56,420 PÚBLICO: ¿Es una buena práctica de codificación poner el if __name__ 1029 00:45:56,420 --> 00:45:59,007 o simplemente se debe ejecutar hello, world sin definir main. 1030 00:45:59,007 --> 00:46:00,147 ¿Realmente se necesita hacer... 1031 00:46:00,147 --> 00:46:01,730 DAVID: Ah, buena pregunta. 1032 00:46:01,730 --> 00:46:03,110 La respuesta corta es, no. 1033 00:46:03,110 --> 00:46:05,720 Se los estoy mostrando de esta manera porque verán 1034 00:46:05,720 --> 00:46:08,690 ver esto en varios ejemplos en línea y en programas 1035 00:46:08,690 --> 00:46:11,360 que podrían ver que son de código abierto. 1036 00:46:11,360 --> 00:46:13,350 Estrictamente hablando, esto no es necesario. 1037 00:46:13,350 --> 00:46:17,780 Si al final crean su propia biblioteca, esto tiende a ser una característica útil, 1038 00:46:17,780 --> 00:46:23,600 Pero podría hacerse de manera equivalente, lo cual también está bien. 1039 00:46:23,600 --> 00:46:25,760 Aún puedo definir get_positive int. 1040 00:46:25,760 --> 00:46:28,130 Puedo deshacerme del main completamente. 1041 00:46:28,130 --> 00:46:30,260 Y ahora puedo hacer esto. 1042 00:46:30,260 --> 00:46:34,471 Por lo tanto, este programa es equivalente y está bien por ahora. 1043 00:46:34,471 --> 00:46:34,970 OK. 1044 00:46:34,970 --> 00:46:37,412 Una vez que aclaramos esto, veamos un par de ejemplos más 1045 00:46:37,412 --> 00:46:39,620 para ilustrar mejor las similitudes y diferencias 1046 00:46:39,620 --> 00:46:41,460 de algunas cosas. 1047 00:46:41,460 --> 00:46:46,910 Ahora abriremos, por ejemplo overflow.c, el cual vimos hace unas semanas, 1048 00:46:46,910 --> 00:46:49,580 y dividiremos de nuevo nuestras ventanas. 1049 00:46:49,580 --> 00:46:53,210 Y luego, en el lado derecho, abriré algo llamado overflow.py 1050 00:46:53,210 --> 00:46:55,430 que preparé de antemano. 1051 00:46:55,430 --> 00:47:01,640 Así que, a la izquierda tenemos un ejemplo de desbordamiento de enteros 1052 00:47:01,640 --> 00:47:05,510 en donde, si empiezo a contar en 1 y ni siquiera tengo una condición, 1053 00:47:05,510 --> 00:47:08,015 y sigo multiplicando i por 2, por 2, por 2, 1054 00:47:08,015 --> 00:47:10,140 y lo duplico, lo duplico, lo duplico y lo duplico, 1055 00:47:10,140 --> 00:47:13,190 sabemos desde C que suceden cosas malas si mantenemos 1056 00:47:13,190 --> 00:47:16,014 un incremento en algo sin ningún límite a la vista. 1057 00:47:16,014 --> 00:47:18,680 Este programa solo imprimirá cada uno de esos valores 1058 00:47:18,680 --> 00:47:20,810 y se pondrá en reposo durante un segundo en el inter. 1059 00:47:20,810 --> 00:47:23,070 El mismo programa en Python se ve bastante similar. 1060 00:47:23,070 --> 00:47:27,290 Pero noten que inicializo i en 1 y hace eternamente lo siguiente, 1061 00:47:27,290 --> 00:47:32,270 imprime i, multiplica i por 2 y luego se queda en reposo durante un segundo. 1062 00:47:32,270 --> 00:47:35,600 Pero estar en reposo no está integrado a Python en la forma en que funciona print. 1063 00:47:35,600 --> 00:47:37,142 Observen lo que tuve que incluir aquí 1064 00:47:37,142 --> 00:47:38,475 y no estaba seguro de lo que era. 1065 00:47:38,475 --> 00:47:40,520 Y sinceramente, hace unos días que busqué en Google, 1066 00:47:40,520 --> 00:47:45,140 "pausa de un segundo en Python", vi que estaba esta biblioteca, 1067 00:47:45,140 --> 00:47:46,670 en la cual está la función de reposo. 1068 00:47:46,670 --> 00:47:50,000 Y así es como cuál biblioteca debía incluir. 1069 00:47:50,000 --> 00:47:52,160 Y así como hay páginas con manuales para C, 1070 00:47:52,160 --> 00:47:55,580 hay todo un sitio web con documentación para Python 1071 00:47:55,580 --> 00:47:57,479 que también contiene toda esa información. 1072 00:47:57,479 --> 00:47:58,770 A continuación haremos lo siguiente. 1073 00:47:58,770 --> 00:48:03,640 Trataré de crear dos ventanas aquí. 1074 00:48:03,640 --> 00:48:07,310 ¿Cuál sería la mejor forma de hacerlo? 1075 00:48:07,310 --> 00:48:09,210 Dividir una en dos. 1076 00:48:09,210 --> 00:48:09,710 OK. 1077 00:48:09,710 --> 00:48:13,710 Hagamos esto, para que pueda ejecutarlo en el mismo sitio. 1078 00:48:13,710 --> 00:48:16,010 Y si voy a mi directorio fuente... 1079 00:48:16,010 --> 00:48:17,432 [PITIDO DE ADVERTENCIA] 1080 00:48:17,432 --> 00:48:18,380 Por Dios. 1081 00:48:18,380 --> 00:48:24,470 A mi directorio fuente src8, voy a weeks/1y ejecuto make overflow... 1082 00:48:24,470 --> 00:48:28,720 1083 00:48:28,720 --> 00:48:30,410 no, lo siento. 1084 00:48:30,410 --> 00:48:31,140 Week/1... 1085 00:48:31,140 --> 00:48:31,640 OK. 1086 00:48:31,640 --> 00:48:36,120 Si voy a src1, ejecuto make overflow, 1087 00:48:36,120 --> 00:48:38,660 lo cual es muy lindo semánticamente, y ahora 1088 00:48:38,660 --> 00:48:40,850 podré ejecutar un programa llamado ./overflow. 1089 00:48:40,850 --> 00:48:48,510 Mientras tanto, dividiré esta ventana también. 1090 00:48:48,510 --> 00:48:50,340 Diablos, no allí. 1091 00:48:50,340 --> 00:48:54,194 Pongamos esto aquí. 1092 00:48:54,194 --> 00:48:55,190 ¡Oh, no! 1093 00:48:55,190 --> 00:49:00,670 1094 00:49:00,670 --> 00:49:01,210 OK. 1095 00:49:01,210 --> 00:49:01,730 Un segundo, 1096 00:49:01,730 --> 00:49:02,540 perdón. 1097 00:49:02,540 --> 00:49:03,980 Overflow.py. 1098 00:49:03,980 --> 00:49:04,522 OK. 1099 00:49:04,522 --> 00:49:06,480 Así que ahora estamos... oh, ya perdí la otra ventana. 1100 00:49:06,480 --> 00:49:09,720 1101 00:49:09,720 --> 00:49:10,480 ¡Oh! Eso es genial. 1102 00:49:10,480 --> 00:49:10,980 OK. 1103 00:49:10,980 --> 00:49:13,640 Hagamos esto. 1104 00:49:13,640 --> 00:49:15,980 OK. 1105 00:49:15,980 --> 00:49:17,660 Ahora ya sé cómo usar el IDE. 1106 00:49:17,660 --> 00:49:18,230 Muy bien. 1107 00:49:18,230 --> 00:49:20,850 En el lado izquierdo, estoy a punto de ejecutar overflow. 1108 00:49:20,850 --> 00:49:25,490 Y por último, sin que suene ese pitido de nuevo, voy a entrar aquí 1109 00:49:25,490 --> 00:49:29,300 y estoy a punto de ejecutar python of overflow.py. 1110 00:49:29,300 --> 00:49:29,800 Muy bien. 1111 00:49:29,800 --> 00:49:31,700 Y a la izquierda ejecutará la versión en C 1112 00:49:31,700 --> 00:49:33,710 y a la derecha ejecutará la versión de Python. 1113 00:49:33,710 --> 00:49:34,775 Y comenzaremos a ver... 1114 00:49:34,775 --> 00:49:37,760 1115 00:49:37,760 --> 00:49:42,021 Sin dobles sentidos, ¿qué pasa con estos programas? 1116 00:49:42,021 --> 00:49:42,520 Oh, diablos. 1117 00:49:42,520 --> 00:49:43,740 Tengo que desplazarlos. 1118 00:49:43,740 --> 00:49:47,660 1119 00:49:47,660 --> 00:49:49,410 OK, seguiré desplazándolos. 1120 00:49:49,410 --> 00:49:52,240 1121 00:49:52,240 --> 00:49:53,981 Esto es divertido. 1122 00:49:53,981 --> 00:49:54,480 OK. 1123 00:49:54,480 --> 00:49:59,035 1124 00:49:59,035 --> 00:49:59,750 OK. 1125 00:49:59,750 --> 00:50:03,120 La próxima vez busquen en Google cómo ponerlos en reposo durante medio segundo. 1126 00:50:03,120 --> 00:50:04,020 OK. 1127 00:50:04,020 --> 00:50:05,010 Entonces, aquí vamos. 1128 00:50:05,010 --> 00:50:07,050 Algo malo pasó aquí 1129 00:50:07,050 --> 00:50:09,270 y ahora C se está ahogando por completo. 1130 00:50:09,270 --> 00:50:11,430 Las cosas se pusieron horribles. 1131 00:50:11,430 --> 00:50:15,260 ¿Qué pasó a la izquierda? Antes de que la respuesta se desplace. 1132 00:50:15,260 --> 00:50:16,260 Fue un desbordamiento de enteros, ¿cierto? 1133 00:50:16,260 --> 00:50:19,590 Tuvimos tantos bits convirtiéndose en uno solo, que finalmente 1134 00:50:19,590 --> 00:50:21,767 fueron confundidos temporalmente con un número negativo. 1135 00:50:21,767 --> 00:50:23,850 Y luego todo el asunto se volvió confuso 1136 00:50:23,850 --> 00:50:26,010 y se volvieron ceros permanentemente. 1137 00:50:26,010 --> 00:50:28,710 Mientras que en el lado derecho, en el de Python, ¡sí! 1138 00:50:28,710 --> 00:50:30,420 ¡Miren como funciona! 1139 00:50:30,420 --> 00:50:32,860 Sigue contando cada vez más y más y más alto. 1140 00:50:32,860 --> 00:50:35,735 Y aún no hemos hablado sobre la representación subyacente 1141 00:50:35,735 --> 00:50:37,620 de estos tipos en Python, ¿qué podemos inferir 1142 00:50:37,620 --> 00:50:43,610 de la aparente mejor corrección en la versión de Python que está a la derecha? 1143 00:50:43,610 --> 00:50:45,180 No es una representación de ocho bits. 1144 00:50:45,180 --> 00:50:47,730 E incluso C, para ser más precisos, usa 32 bits para sus enteros. 1145 00:50:47,730 --> 00:50:50,970 Y así es como obtenemos cifras tan altas como 2 mil o 4 mil millones en total. 1146 00:50:50,970 --> 00:50:52,470 Pero es la misma idea. 1147 00:50:52,470 --> 00:50:54,435 ¿Cuántos bits debe utilizar Python? 1148 00:50:54,435 --> 00:50:54,976 PÚBLICO: ¿64? 1149 00:50:54,976 --> 00:50:56,710 DAVID: Sí, tal vez 64. 1150 00:50:56,710 --> 00:50:57,600 No lo sé con exactitud. 1151 00:50:57,600 --> 00:51:01,260 Pero sé que no son 32 porque sigue contando y contando y contando. 1152 00:51:01,260 --> 00:51:03,030 Esta es otra característica de Python. 1153 00:51:03,030 --> 00:51:06,240 Mientras que los enteros en C típicamente son de 32 bits, 1154 00:51:06,240 --> 00:51:08,850 y aunque técnicamente eso es específico de la máquina, 1155 00:51:08,850 --> 00:51:11,157 los enteros en Python ahora son de 64, 1156 00:51:11,157 --> 00:51:12,990 lo cual significa que podemos hacer matemáticas a un nivel más alto y eso es 1157 00:51:12,990 --> 00:51:15,864 genial en aplicaciones que manejan datos científicos, estadísticas y demás, 1158 00:51:15,864 --> 00:51:19,020 donde tal vez tendríamos que lidiar con conjuntos enormes de datos. 1159 00:51:19,020 --> 00:51:21,960 Lamentablemente, aún tenemos algunos problemas de imprecisión. 1160 00:51:21,960 --> 00:51:24,480 Para continuar voy a cerrar este montón de ventanas 1161 00:51:24,480 --> 00:51:30,290 y abriré, por ejemplo, esta de aquí. 1162 00:51:30,290 --> 00:51:31,060 OK. 1163 00:51:31,060 --> 00:51:33,240 No, voy a omitir esto y haré algo 1164 00:51:33,240 --> 00:51:35,280 un poco más divertido, que es lo siguiente. 1165 00:51:35,280 --> 00:51:38,870 Entonces, en Python, haremos un calentamiento rápido. 1166 00:51:38,870 --> 00:51:40,483 Esto va a imprimir para mí, ¿qué? 1167 00:51:40,483 --> 00:51:41,410 PÚBLICO: Cuatro signos de interrogación. 1168 00:51:41,410 --> 00:51:42,480 DAVID: Cuatro signos de interrogación, ¿verdad? 1169 00:51:42,480 --> 00:51:45,690 Y esto es reminiscente, es como una versión realmente barata de "Super Mario 1170 00:51:45,690 --> 00:51:46,560 Bros". 1171 00:51:46,560 --> 00:51:49,445 Y si recuerdan la semana uno, donde exploramos esto, 1172 00:51:49,445 --> 00:51:52,320 había una captura de pantalla de "Super Mario Bros", en uno de los mundos 1173 00:51:52,320 --> 00:51:55,965 había cuatro signos de interrogación en los que Mario debía golpearse la cabeza 1174 00:51:55,965 --> 00:51:57,700 para ganar monedas. 1175 00:51:57,700 --> 00:52:00,435 Así que empezamos desde ese punto en C para hacer esto en su lugar. 1176 00:52:00,435 --> 00:52:02,310 Y ello nos dará otra característica. 1177 00:52:02,310 --> 00:52:05,970 Pero veamos si podemos inferir del contexto lo que hacen estos programas. 1178 00:52:05,970 --> 00:52:07,295 Aquí hay otro, Mario1. 1179 00:52:07,295 --> 00:52:07,920 ¿Qué hace esto? 1180 00:52:07,920 --> 00:52:12,080 1181 00:52:12,080 --> 00:52:13,550 De seguro está utilizando un bucle. 1182 00:52:13,550 --> 00:52:15,841 ¿Y cuántas iteraciones está usando aparentemente? 1183 00:52:15,841 --> 00:52:16,340 Cuatro. 1184 00:52:16,340 --> 00:52:18,950 De 0 a 1 a 2 a 3 en total. 1185 00:52:18,950 --> 00:52:22,110 Al parecer, cada vez imprimirá un signo de interrogación. 1186 00:52:22,110 --> 00:52:23,770 Pero ahora, solo infieran de esto. 1187 00:52:23,770 --> 00:52:25,520 Aún no he respondido a esta pregunta, 1188 00:52:25,520 --> 00:52:28,418 ¿Qué más pasa en la línea 4 y por qué? 1189 00:52:28,418 --> 00:52:30,347 PÚBLICO: No va a una nueva línea. 1190 00:52:30,347 --> 00:52:32,180 DAVID: No va a una nueva línea. ¿Verdad? 1191 00:52:32,180 --> 00:52:35,390 Así que hay esta compensación en programación, y en CS más generalmente, 1192 00:52:35,390 --> 00:52:38,850 es como decir, hey, nos quitamos de encima la \ n que era tan molesta de escribir. 1193 00:52:38,850 --> 00:52:42,210 Pero ahora, si siempre está ahí, ¿cómo la desactivan? 1194 00:52:42,210 --> 00:52:45,650 Esta es una manera de hacerlo y también 1195 00:52:45,650 --> 00:52:48,380 revela otra característica fundamental de Python. 1196 00:52:48,380 --> 00:52:52,440 Noten que print aparentemente toma, en este caso, más de un argumento. 1197 00:52:52,440 --> 00:52:55,910 El primero es una cadena, print("?",... 1198 00:52:55,910 --> 00:52:58,520 El segundo es un poco diferente. 1199 00:52:58,520 --> 00:53:00,200 Es como la palabra fin. 1200 00:53:00,200 --> 00:53:03,920 Entonces es: end=" "). 1201 00:53:03,920 --> 00:53:05,300 Pero, ¿qué es esto de aquí? 1202 00:53:05,300 --> 00:53:09,560 Sucede que Python admite lo que llamamos parámetros nombrados. 1203 00:53:09,560 --> 00:53:12,530 Así que en C, cualquier parámetro que pasemos a una función 1204 00:53:12,530 --> 00:53:16,070 se define, básicamente, por el modo en que está ordenado. 1205 00:53:16,070 --> 00:53:19,220 Porque, incluso si una función toma argumentos que tienen nombres, 1206 00:53:19,220 --> 00:53:23,690 como x y y, o a y b, o lo que sea, cuando llamamos a la función, 1207 00:53:23,690 --> 00:53:25,762 no mencionamos esos nombres. 1208 00:53:25,762 --> 00:53:28,970 Sabemos que existen y así es cómo los vemos en la documentación 1209 00:53:28,970 --> 00:53:30,800 o en el código original. 1210 00:53:30,800 --> 00:53:35,180 Pero no nombramos a los argumentos cuando los pasamos y llamamos a una función, 1211 00:53:35,180 --> 00:53:38,480 en vez de ello los pasamos en el orden apropiado, según lo digan el manual 1212 00:53:38,480 --> 00:53:40,550 o la documentación. 1213 00:53:40,550 --> 00:53:43,580 En Python, de hecho, podemos ser un poco más flexibles. 1214 00:53:43,580 --> 00:53:47,660 Si una función toma varios argumentos y todos tienen nombres, 1215 00:53:47,660 --> 00:53:50,450 podemos mencionar los nombres explícitamente, 1216 00:53:50,450 --> 00:53:53,300 lo cual nos libera de los inconvenientes menores 1217 00:53:53,300 --> 00:53:57,720 de tener que recordar y acertar siempre el orden real de los argumentos. 1218 00:53:57,720 --> 00:54:01,160 Este caso, print toma al menos dos argumentos, 1219 00:54:01,160 --> 00:54:03,140 uno de los cuales se llama end. 1220 00:54:03,140 --> 00:54:06,800 Y si quieren usarlo, lo cual es claramente opcional porque no lo he 1221 00:54:06,800 --> 00:54:10,640 utilizado aún, pueden mencionarlo por su nombre, poner un signo igual 1222 00:54:10,640 --> 00:54:13,170 y luego especificar el valor que quieren pasar. 1223 00:54:13,170 --> 00:54:18,110 Si ahora entro aquí, voy a weeks/1 y escribo python 1224 00:54:18,110 --> 00:54:23,630 mario1.py, aún obtengo... 1225 00:54:23,630 --> 00:54:25,790 umh... en weeks/2. 1226 00:54:25,790 --> 00:54:30,500 Si pongo python mario1.py, aún obtengo cuatro signos de interrogación. 1227 00:54:30,500 --> 00:54:34,940 Pero ese es el resultado de imprimirlo con una línea que termina en comillas. 1228 00:54:34,940 --> 00:54:37,850 Mientras tanto, si hago esto, lo cual es un poco estúpido 1229 00:54:37,850 --> 00:54:40,730 porque voy a obtener igual si simplemente lo omito por completo. 1230 00:54:40,730 --> 00:54:42,530 Pero ahora tengo aquí cuatro signos de interrogación. 1231 00:54:42,530 --> 00:54:46,190 Y si realmente quieren ser originales, pueden hacer algo 1232 00:54:46,190 --> 00:54:50,750 como esto, que solo se utilizará, literalmente, 1233 00:54:50,750 --> 00:54:52,580 para darles eso en cambio. 1234 00:54:52,580 --> 00:54:56,624 Aplicar este enfoque tiene una utilidad incierta, 1235 00:54:56,624 --> 00:54:57,290 Pero eso es todo... 1236 00:54:57,290 --> 00:54:57,915 [PITIDO DE ADVERTENCIA] 1237 00:54:57,915 --> 00:54:59,400 Perdón... eso está pasando. 1238 00:54:59,400 --> 00:55:00,825 Echemos un vistazo a mario2. 1239 00:55:00,825 --> 00:55:02,700 Este funciona un poco diferente también. 1240 00:55:02,700 --> 00:55:05,700 ¿Y cómo describirían la función que ofrece esta versión de Mario? 1241 00:55:05,700 --> 00:55:09,370 1242 00:55:09,370 --> 00:55:11,290 Imprime perfectamente cualquier cantidad de signos de interrogación. 1243 00:55:11,290 --> 00:55:14,040 Así que se parametriza al obtener primero un int del usuario que utiliza 1244 00:55:14,040 --> 00:55:15,670 la función get_int de CS50. 1245 00:55:15,670 --> 00:55:19,750 Y ahora estoy haciendo una iteración de i al rango de n, cualquiera que sea, 1246 00:55:19,750 --> 00:55:22,690 y luego imprimo los signos de interrogación. 1247 00:55:22,690 --> 00:55:26,850 Mientras tanto, mario3.py es un poco más elegante, 1248 00:55:26,850 --> 00:55:28,540 ¿Pero qué estoy haciendo mejor esta vez? 1249 00:55:28,540 --> 00:55:33,809 1250 00:55:33,809 --> 00:55:36,204 PÚBLICO: Te aseguras de que n sea positiva. 1251 00:55:36,204 --> 00:55:38,350 DAVID: Sí, solo me aseguro de que la n sea positiva. 1252 00:55:38,350 --> 00:55:40,510 Así que no me molesté en implementar una función completa llamada 1253 00:55:40,510 --> 00:55:41,561 get_positive_int. 1254 00:55:41,561 --> 00:55:42,310 No la necesito. 1255 00:55:42,310 --> 00:55:43,750 Este es un programa súper corto. 1256 00:55:43,750 --> 00:55:45,510 Solo estoy usando la misma lógica aquí, 1257 00:55:45,510 --> 00:55:47,260 induzco deliberadamente un bucle infinito 1258 00:55:47,260 --> 00:55:50,250 y lo rompo solo cuando haya obtenido un entero positivo, 1259 00:55:50,250 --> 00:55:54,750 y luego imprimo muchos hashtags que nos recuerdan a los ladrillos 1260 00:55:54,750 --> 00:55:55,590 en Mario. 1261 00:55:55,590 --> 00:55:59,580 Y finalmente, tenemos esta versión un poco más sofisticada 1262 00:55:59,580 --> 00:56:03,320 que en realidad imprime de una forma completamente diferente. 1263 00:56:03,320 --> 00:56:05,745 Pueden inferirlo en los comentarios, pero concéntrese más en por qué. 1264 00:56:05,745 --> 00:56:11,976 1265 00:56:11,976 --> 00:56:15,150 La primera línea 12 itera de i a n, 1266 00:56:15,150 --> 00:56:17,250 sea cual sea la n que el usuario escribió. 1267 00:56:17,250 --> 00:56:24,220 Mientras tanto, la línea 15, con sangría, itera j desde 0 hasta n también. 1268 00:56:24,220 --> 00:56:26,460 Es algo así como nuestra convención para decir 1269 00:56:26,460 --> 00:56:29,970 int i = 0... , para int j = 0..., 1270 00:56:29,970 --> 00:56:31,650 en donde ya hemos tenido bucles anidados antes. 1271 00:56:31,650 --> 00:56:35,209 Noten que ahora que tenemos este bloque, el cual es una línea de código 1272 00:56:35,209 --> 00:56:36,750 o, conceptualmente, solo una pieza de Scratch. 1273 00:56:36,750 --> 00:56:38,640 Podemos anidar uno dentro del otro. 1274 00:56:38,640 --> 00:56:40,470 Aquí puedo imprimir un hashtag, asegurándome 1275 00:56:40,470 --> 00:56:44,280 de no poner una nueva línea después de cada hashtag que imprima, 1276 00:56:44,280 --> 00:56:49,980 solo imprimo una nueva línea en la línea 17, en cada iteración del bucle externo. 1277 00:56:49,980 --> 00:56:54,700 Y observen que, mientras en C lo hubiéramos hecho por costumbre, 1278 00:56:54,700 --> 00:56:57,686 lo cual está bien, en Python no necesitamos la f 1279 00:56:57,686 --> 00:56:59,310 y tampoco necesitamos la \ n end. 1280 00:56:59,310 --> 00:57:03,030 Por lo tanto, pueden simplemente imprimir y obtendrán, al menos, 1281 00:57:03,030 --> 00:57:05,100 una \ n automáticamente. 1282 00:57:05,100 --> 00:57:07,590 Así, cuando ahora ejecuto esta versión de Mario, 1283 00:57:07,590 --> 00:57:09,270 obtenemos algo más interesante. 1284 00:57:09,270 --> 00:57:11,270 Aumentaré el tamaño de mi ventana de terminal 1285 00:57:11,270 --> 00:57:14,430 para poder introducir un número positivo como este e imprimir 10. 1286 00:57:14,430 --> 00:57:16,150 Y ahora hemos obtenido un bloque completo. 1287 00:57:16,150 --> 00:57:16,900 Bueno, eso fue mucho. 1288 00:57:16,900 --> 00:57:18,240 Vamos a tomar nuestros cinco minutos de descanso 1289 00:57:18,240 --> 00:57:22,050 Y cuando regresemos, veremos algunos ejemplos aún más sofisticados. 1290 00:57:22,050 --> 00:57:22,920 Muy bien. 1291 00:57:22,920 --> 00:57:27,810 Vamos a iniciar la transición para resolver problemas con Python, 1292 00:57:27,810 --> 00:57:30,060 después de presentar un par de características adicionales 1293 00:57:30,060 --> 00:57:34,110 que no son características sintácticas sino reales del lenguaje. 1294 00:57:34,110 --> 00:57:38,290 A la izquierda está el viejo programa argv0.c que escribimos en la semana 3, 1295 00:57:38,290 --> 00:57:40,590 cuyo único propósito era permitirles 1296 00:57:40,590 --> 00:57:43,170 la ejecución de un argumento de línea de comandos por primera vez 1297 00:57:43,170 --> 00:57:45,180 y que era una linda herramienta para tener en nuestro kit de herramientas. 1298 00:57:45,180 --> 00:57:47,000 Pero, ¿cómo podríamos mapear esto? 1299 00:57:47,000 --> 00:57:49,680 Bueno, de hecho necesitamos saber que Python funciona 1300 00:57:49,680 --> 00:57:51,610 de un modo un poco diferente, como sigue. 1301 00:57:51,610 --> 00:57:57,780 Si abro un nuevo archivo llamado, 1302 00:57:57,780 --> 00:57:59,455 vamos a llamarlo argv0.py. 1303 00:57:59,455 --> 00:58:03,930 1304 00:58:03,930 --> 00:58:06,880 Voy a traducir esto, tal como lo hicimos antes. 1305 00:58:06,880 --> 00:58:12,460 Para ello, utilizaré lo siguiente. 1306 00:58:12,460 --> 00:58:16,380 If argc, no hay argc. 1307 00:58:16,380 --> 00:58:19,450 Así que, def main( ), 1308 00:58:19,450 --> 00:58:21,540 tampoco hubo argc o argv. 1309 00:58:21,540 --> 00:58:26,209 Y no es realmente correcto hacer esto y esto, como podrían suponer. 1310 00:58:26,209 --> 00:58:28,500 Las funciones de los argumentos de la línea de comandos 1311 00:58:28,500 --> 00:58:31,030 fueron proporcionadas por un paquete de Python, por así decirlo, 1312 00:58:31,030 --> 00:58:34,080 o una biblioteca, al igual que la biblioteca CS50 es un paquete 1313 00:58:34,080 --> 00:58:36,150 que pueden importar de Python. 1314 00:58:36,150 --> 00:58:40,170 Para ello, necesito hacer lo siguiente, import sys, que me da 1315 00:58:40,170 --> 00:58:42,300 acceso a un montón de cosas relacionadas con el sistema, 1316 00:58:42,300 --> 00:58:44,770 como lo que el usuario escribió en el símbolo del sistema. 1317 00:58:44,770 --> 00:58:47,790 Y si quiero controlar si el número de palabras que el humano escribió 1318 00:58:47,790 --> 00:58:50,760 en el símbolo del sistema es dos, de hecho, 1319 00:58:50,760 --> 00:58:57,240 haré esto: if len(sys.argv) ==2: 1320 00:58:57,240 --> 00:59:03,930 A continuación: print ("hello, ") 1321 00:59:03,930 --> 00:59:05,970 y un marcador de posición aquí. 1322 00:59:05,970 --> 00:59:09,090 Con los marcadores de posición, debo convertir esto en una cadena formateada, 1323 00:59:09,090 --> 00:59:10,620 será una cadena f. 1324 00:59:10,620 --> 00:59:15,010 Dentro de las llaves, puedo poner: print (f"hello, {sys.argv [1]}") 1325 00:59:15,010 --> 00:59:18,240 1326 00:59:18,240 --> 00:59:20,350 Entonces, es un poco diferente a lo anterior. 1327 00:59:20,350 --> 00:59:23,410 Tomé prestadas casi todas las mismas ideas que antes, 1328 00:59:23,410 --> 00:59:25,144 incluyendo cómo imprimir las cadenas. 1329 00:59:25,144 --> 00:59:27,060 A pesar, de que esto es un poco más detallado, 1330 00:59:27,060 --> 00:59:29,160 ¿qué hay entre estas dos llaves? 1331 00:59:29,160 --> 00:59:32,010 Está el resultado de buscar en el paquete del sistema, que 1332 00:59:32,010 --> 00:59:34,920 tiene una variable llamada argv, por argumento del vector, 1333 00:59:34,920 --> 00:59:39,420 al igual que en C. Es en sí misma, es un arreglo, un alias de una lista en Python. 1334 00:59:39,420 --> 00:59:44,130 Aquí, tenemos el resultado de indexarlo como el elemento uno de esa lista. 1335 00:59:44,130 --> 00:59:47,160 Y la manera en que tengo acceso a esto es porque 1336 00:59:47,160 --> 00:59:49,050 importé ese paquete completo. 1337 00:59:49,050 --> 00:59:53,160 Si en el lado derecho, después de guardar ese archivo, hago: 1338 00:59:53,160 --> 00:59:57,870 python argv0.py, no veo nada. Si agrego 1339 00:59:57,870 --> 01:00:01,600 mi nombre: python argv0.py David veo: hello, David. 1340 01:00:01,600 --> 01:00:05,760 Es un programa muy similar, pero se implementó un poco diferente, 1341 01:00:05,760 --> 01:00:09,450 también notarán que la longitud de un arreglo, 1342 01:00:09,450 --> 01:00:13,530 conocido como una lista, no es algo que nosotros mismos 1343 01:00:13,530 --> 01:00:15,180 tengamos que recordar o tener cerca. 1344 01:00:15,180 --> 01:00:19,290 Podemos pedir el largo de una lista al llamar a len, 1345 01:00:19,290 --> 01:00:21,110 o L-E-N por length (longitud), 1346 01:00:21,110 --> 01:00:23,680 una función, que pasa como un argumento. 1347 01:00:23,680 --> 01:00:25,449 Ese es uno de los puntos de partida, 1348 01:00:25,449 --> 01:00:27,990 si queremos hacer algo un poco más inteligente, 1349 01:00:27,990 --> 01:00:32,700 como imprimir todas las cadenas en argv, como hace tiempo vimos, 1350 01:00:32,700 --> 01:00:34,230 podríamos recordar este ejemplo, 1351 01:00:34,230 --> 01:00:37,380 argv1.c, en donde tuve este bucle for. 1352 01:00:37,380 --> 01:00:40,950 Lo iteré desde de cero hasta argc, el conteo de argumentos, 1353 01:00:40,950 --> 01:00:44,400 imprimí cada uno de los argumentos en ese vector. 1354 01:00:44,400 --> 01:00:48,120 Python hace que incluso algo así sea aún más simple. 1355 01:00:48,120 --> 01:00:50,400 Para continuar, crearé un nuevo archivo aquí, 1356 01:00:50,400 --> 01:00:53,580 y lo llamaré, por ejemplo: argv1.py. 1357 01:00:53,580 --> 01:00:58,080 En Python puedo hacer: import sys 1358 01:00:58,080 --> 01:01:05,830 después: for s in sys.argv: print (s) 1359 01:01:05,830 --> 01:01:06,780 Lo hicimos. 1360 01:01:06,780 --> 01:01:08,830 De nuevo, solo dice lo que significa. 1361 01:01:08,830 --> 01:01:10,800 Importé la biblioteca del sistema. 1362 01:01:10,800 --> 01:01:14,530 sys.argv sé que es una lista, de argumentos de línea de comandos. 1363 01:01:14,530 --> 01:01:18,290 For algo en algo, es una nueva sintaxis que tenemos para bucles for. 1364 01:01:18,290 --> 01:01:23,630 Para alguna variable s dentro de esta lista, imprímelo. 1365 01:01:23,630 --> 01:01:25,960 Esta es una manera mucho más limpia, mucho más breve 1366 01:01:25,960 --> 01:01:29,680 de deshacerse de toda la complejidad, 1367 01:01:29,680 --> 01:01:32,174 simplemente al decir lo que queremos. 1368 01:01:32,174 --> 01:01:34,340 Mientras tanto, si quisiera imprimir cada carácter, 1369 01:01:34,340 --> 01:01:35,950 podría llevar esto un paso más allá. 1370 01:01:35,950 --> 01:01:38,500 Como hace tiempo en C, si quería imprimir 1371 01:01:38,500 --> 01:01:43,030 cada argumento de la línea de comando y cada carácter ahí podría hacer esto. 1372 01:01:43,030 --> 01:01:46,510 Solo necesito un par de bucles anidados, donde por medio del bucle externo, 1373 01:01:46,510 --> 01:01:49,960 itero todos los argumentos pasados. 1374 01:01:49,960 --> 01:01:53,410 Y en el bucle interno, itero sobre la longitud actual de la cadena 1375 01:01:53,410 --> 01:01:55,460 de cualquier argumento que imprimo. 1376 01:01:55,460 --> 01:01:58,750 Esto tuvo el efecto de imprimir todas las letras de los argumentos 1377 01:01:58,750 --> 01:02:01,030 de la línea de comandos a la vez. 1378 01:02:01,030 --> 01:02:03,470 Puedo hacer esto en Python, honestamente, es mucho más fácil. 1379 01:02:03,470 --> 01:02:05,020 Continuaré ahí. 1380 01:02:05,020 --> 01:02:10,120 Crearé un nuevo archivo llamado argv2.py, 1381 01:02:10,120 --> 01:02:11,830 e importaré sys, como lo hice: 1382 01:02:11,830 --> 01:02:12,910 import sys. 1383 01:02:12,910 --> 01:02:20,110 Después: for s in sys.argv: for c in s: print (c). 1384 01:02:20,110 --> 01:02:21,430 Lo hicimos. 1385 01:02:21,430 --> 01:02:22,720 ¿Qué hace esto? 1386 01:02:22,720 --> 01:02:27,740 Ya se fue todo esa sobrecarga para for int i, for int j y lo demás. 1387 01:02:27,740 --> 01:02:32,440 En: for s in sys.argv, iteramos sobre todos los elementos de esa lista, 1388 01:02:32,440 --> 01:02:33,490 una cadena a la vez. 1389 01:02:33,490 --> 01:02:36,550 Para: for c in s, es un poco diferente ya que técnicamente 1390 01:02:36,550 --> 01:02:39,166 es una cadena o un objeto str, que es como lo llamaremos. 1391 01:02:39,166 --> 01:02:42,040 Pero a fin de cuentas, una cadena es solo una secuencia de caracteres. 1392 01:02:42,040 --> 01:02:46,120 Python soporta, desde el inicio, la habilidad de usar un bucle for 1393 01:02:46,120 --> 01:02:48,710 incluso para iterar sobre todos los caracteres en una cadena. 1394 01:02:48,710 --> 01:02:49,990 Por ello c, significa carácter: 1395 01:02:49,990 --> 01:02:53,380 for c in s:, me da cada uno de los caracteres. 1396 01:02:53,380 --> 01:02:59,650 A fin de cuentas, si ejecuto: python argv2.py, 1397 01:02:59,650 --> 01:03:03,790 sin nada, obtengo solo el nombre del programa, 1398 01:03:03,790 --> 01:03:07,270 porque eso es, desde luego, lo primero en argv, como en C. Y si 1399 01:03:07,270 --> 01:03:13,510 escribo, una palabra como María, obtengo: argv2.pyMaria, 1400 01:03:13,510 --> 01:03:17,490 en toda una columna larga, debido a las impresiones adicionales que suceden 1401 01:03:17,490 --> 01:03:19,010 y las nuevas líneas implícitas. 1402 01:03:19,010 --> 01:03:23,320 ¿Alguna pregunta antes de proceder con el manejo de un paquete 1403 01:03:23,320 --> 01:03:27,860 llamado sys que usa estas funciones? 1404 01:03:27,860 --> 01:03:28,360 Muy bien. 1405 01:03:28,360 --> 01:03:33,130 Continuaré con algo ligeramente familiar. 1406 01:03:33,130 --> 01:03:39,520 Recordaremos initials.c de hace algún tiempo, 1407 01:03:39,520 --> 01:03:45,755 donde aceptamos como entrada en get_string el nombre de un usuario, 1408 01:03:45,755 --> 01:03:47,380 y luego imprimimos sus iniciales. 1409 01:03:47,380 --> 01:03:48,630 Para continuar, haremos algo como eso: 1410 01:03:48,630 --> 01:03:52,030 from CS50 import get_string 1411 01:03:52,030 --> 01:03:54,820 y diré, dame una cadena: 1412 01:03:54,820 --> 01:03:59,920 Quiero solicitarle al usuario su nombre, podríamos hacerlo aquí. 1413 01:03:59,920 --> 01:04:02,779 A continuación, diré: initials = " " 1414 01:04:02,779 --> 01:04:04,070 No sé lo cuales son todavía, 1415 01:04:04,070 --> 01:04:06,280 así que, inicializaré con una cadena vacía. 1416 01:04:06,280 --> 01:04:07,360 Después haré esto: 1417 01:04:07,360 --> 01:04:12,989 for c in s:, que es para cada carácter en el nombre de la persona, if 1418 01:04:12,989 --> 01:04:14,530 todavía no sé cómo decir esto: 1419 01:04:14,530 --> 01:04:24,940 If c is an uppercase letter: append c to initals 1420 01:04:24,940 --> 01:04:26,727 Y aquí abajo: print (initials) 1421 01:04:26,727 --> 01:04:28,060 Dejé un par de espacios en blanco, 1422 01:04:28,060 --> 01:04:29,950 por el momento, eso es solo pseudocódigo. 1423 01:04:29,950 --> 01:04:33,490 Pero esta línea 5, solo para ser claro, ¿qué es lo que hace? 1424 01:04:33,490 --> 01:04:35,541 ¿Qué es lo que itera? 1425 01:04:35,541 --> 01:04:36,040 La cadena. 1426 01:04:36,040 --> 01:04:41,210 Para cada carácter de la cadena, para c in s, haré dos preguntas. 1427 01:04:41,210 --> 01:04:44,350 En C, lo hicimos de dos maneras diferentes. 1428 01:04:44,350 --> 01:04:48,427 Podemos hacerlo con controles de desigualdad 1429 01:04:48,427 --> 01:04:51,010 y considerar cuáles son los valores ASCII subyacentes. 1430 01:04:51,010 --> 01:04:55,000 La biblioteca ctype tenía la función isupper e islower que usamos. 1431 01:04:55,000 --> 01:05:00,760 Bien, resulta que c no es un carácter, 1432 01:05:00,760 --> 01:05:04,090 no existe tal cosa como un carácter en Python. 1433 01:05:04,090 --> 01:05:06,430 Solo tenemos cadenas de longitud 1. 1434 01:05:06,430 --> 01:05:09,520 Y las comillas simples ya no tienen ningún significado especial, 1435 01:05:09,520 --> 01:05:13,510 así que, c es técnicamente solo una cadena de un carácter. 1436 01:05:13,510 --> 01:05:16,180 Las cadenas son lo que comenzamos a llamar objetos, 1437 01:05:16,180 --> 01:05:18,280 que es un nombre más elegante para struct. 1438 01:05:18,280 --> 01:05:22,040 Su funcionalidad se encuentra dentro de un objeto, por ejemplo, una cadena. 1439 01:05:22,040 --> 01:05:26,130 Antes vimos una parte de la funcionalidad, ¿cuál fue? 1440 01:05:26,130 --> 01:05:31,910 No es la longitud, aunque esa otra. 1441 01:05:31,910 --> 01:05:33,070 Fue el formato. 1442 01:05:33,070 --> 01:05:34,150 Lo vimos brevemente, 1443 01:05:34,150 --> 01:05:36,667 pero cuando hice string.format, propuse 1444 01:05:36,667 --> 01:05:38,500 que en realidad hay una funcionalidad incorporada 1445 01:05:38,500 --> 01:05:39,857 a una cadena llamada formato. 1446 01:05:39,857 --> 01:05:40,690 ¿Saben algo? 1447 01:05:40,690 --> 01:05:45,220 Existe un método o función dentro de la clase 1448 01:05:45,220 --> 01:05:47,380 de la cadena llamado isupper. 1449 01:05:47,380 --> 01:05:51,070 Y le puedo preguntar eso a la misma cadena que veo al decir: 1450 01:05:51,070 --> 01:05:57,610 if c issuper ( ): es verdadera, añada c a las iniciales. 1451 01:05:57,610 --> 01:06:03,800 En C, si las iniciales eran una cadena, 1452 01:06:03,800 --> 01:06:07,460 ¿Cómo podríamos agregar otro carácter a una cadena? 1453 01:06:07,460 --> 01:06:10,310 1454 01:06:10,310 --> 01:06:12,110 PÚBLICO: ¿Con c.append? 1455 01:06:12,110 --> 01:06:17,390 DAVID: No en C. En el lenguaje C. 1456 01:06:17,390 --> 01:06:18,680 OK, entonces, ¿qué es una cadena en C? 1457 01:06:18,680 --> 01:06:20,750 Una cadena en C es una secuencia de caracteres, 1458 01:06:20,750 --> 01:06:23,730 en la cual la última es diagonal inversa cero (\ 0). 1459 01:06:23,730 --> 01:06:24,230 Muy bien. 1460 01:06:24,230 --> 01:06:26,771 Es un arreglo de caracteres, donde el último es una diagonal inversa cero (\ 0). 1461 01:06:26,771 --> 01:06:29,720 Si yo, por ejemplo, escribí mi primer nombre, "David", 1462 01:06:29,720 --> 01:06:33,500 y ahora quiero agregar "Malan" al final, ¿cómo hago eso en C? 1463 01:06:33,500 --> 01:06:35,655 PÚBLICO: [INAUDIBLE] 1464 01:06:35,655 --> 01:06:36,530 DAVID: Exactamente. 1465 01:06:36,530 --> 01:06:38,030 Es como una piedra en el zapato. 1466 01:06:38,030 --> 01:06:41,240 Crearíamos un nuevo arreglo, más grande que se ajuste a ambas palabras, 1467 01:06:41,240 --> 01:06:45,230 se copiaría David al nuevo arreglo, después el apellido, poner 1468 01:06:45,230 --> 01:06:47,270 el terminador nulo en el nuevo arreglo, luego liberar, 1469 01:06:47,270 --> 01:06:48,524 probablemente, la memoria original. 1470 01:06:48,524 --> 01:06:50,940 Quiero decir, es una cantidad ridícula de procedimientos a seguir, 1471 01:06:50,940 --> 01:06:53,856 y en algunas ocasiones lo hicimos, como tal vez en 1472 01:06:53,856 --> 01:06:54,800 la serie de problemas cinco. 1473 01:06:54,800 --> 01:06:56,570 Pero Dios mío, ya pasamos por eso. 1474 01:06:56,570 --> 01:07:00,990 Para continuar, añadiremos al arreglo el carácter que nos importa. 1475 01:07:00,990 --> 01:07:03,590 En este caso, no es un arreglo, sino una lista. 1476 01:07:03,590 --> 01:07:08,000 Perdón, no es un arreglo, es una cadena objeto, que al inicio estuvo en blanco. 1477 01:07:08,000 --> 01:07:10,190 Python admite esta sintaxis, 1478 01:07:10,190 --> 01:07:14,450 += en aritmética generalmente significan sumarle un número a otro, 1479 01:07:14,450 --> 01:07:16,070 pero también significan añadir. 1480 01:07:16,070 --> 01:07:21,225 De modo que, podemos añadir a las iniciales al hacer += c, un 1481 01:07:21,225 --> 01:07:22,100 carácter adicional. 1482 01:07:22,100 --> 01:07:24,920 Aunque la cadena comience como esta y aumente en la memoria, 1483 01:07:24,920 --> 01:07:26,670 crecerá en un carácter, 1484 01:07:26,670 --> 01:07:30,620 crecerá, crecerá, crecerá, crecerá, hasta que tenga las iniciales de los usuarios. 1485 01:07:30,620 --> 01:07:33,920 Y de dónde viene ese recuerdo, ¿a quién le importa? 1486 01:07:33,920 --> 01:07:36,100 Este es el punto que ya pasamos, 1487 01:07:36,100 --> 01:07:37,570 Se lo dejamos al lenguaje. 1488 01:07:37,570 --> 01:07:40,480 Dejamos que la computadora comience a administrar esos detalles. 1489 01:07:40,480 --> 01:07:42,230 Si necesitamos llamar a malloc, está bien, 1490 01:07:42,230 --> 01:07:42,729 lo haremos. 1491 01:07:42,729 --> 01:07:44,292 No me molesten con ese detalle. 1492 01:07:44,292 --> 01:07:46,250 Podemos comenzar a pensar y escribir el código de clasificación 1493 01:07:46,250 --> 01:07:49,560 que conceptualmente está en este nivel, en lugar de este nivel. 1494 01:07:49,560 --> 01:07:52,370 De nuevo, abstraemos lo que es una cadena incluso 1495 01:07:52,370 --> 01:07:54,390 y al dejarla en el mismo lenguaje. 1496 01:07:54,390 --> 01:07:58,190 Si ahora ejecuto initials.py en Python, y escribo 1497 01:07:58,190 --> 01:08:05,000 por ejemplo, María Zlatkova, con M y Z en mayúscula, 1498 01:08:05,000 --> 01:08:08,000 Entonces, veo sus nombres porque le quité las iniciales de en medio. 1499 01:08:08,000 --> 01:08:12,080 Y si escribimos algo como David J. Malan, incluso con un punto, 1500 01:08:12,080 --> 01:08:15,890 infiere que las letras iniciales deben ir en mayúsculas. 1501 01:08:15,890 --> 01:08:18,562 De nuevo, es una manera mucho más estricta de hacer las cosas. 1502 01:08:18,562 --> 01:08:20,520 A continuación, abriré otro ejemplo, 1503 01:08:20,520 --> 01:08:22,353 que no vimos hace unas semanas, aunque se 1504 01:08:22,353 --> 01:08:26,149 incluyó en algunos de nuestros códigos de distribución, si lo desean buscar. 1505 01:08:26,149 --> 01:08:30,020 Hace algunas semanas, teníamos este programa entre el código de distribución, 1506 01:08:30,020 --> 01:08:34,790 donde declare un arreglo de cadenas llamada libro. 1507 01:08:34,790 --> 01:08:38,240 Y propuse que había varios nombres en la guía telefónica 1508 01:08:38,240 --> 01:08:41,689 por así decirlo, todos los instructores anteriores de CS50 1509 01:08:41,689 --> 01:08:43,040 ordenados alfabéticamente. 1510 01:08:43,040 --> 01:08:47,960 Y luego abajo en este programa de C, utilicé esa variable global llamada book 1511 01:08:47,960 --> 01:08:51,140 para implementar, lo que parece, una búsqueda lineal. 1512 01:08:51,140 --> 01:08:53,689 Y para implementar la búsqueda lineal en C, necesitaré 1513 01:08:53,689 --> 01:08:57,080 desde luego, un bucle para iterar sobre todas las cadenas. 1514 01:08:57,080 --> 01:08:59,689 Esta línea 26 hace exactamente eso. 1515 01:08:59,689 --> 01:09:01,709 Recuerdo que tuve que usar str compare en C, 1516 01:09:01,709 --> 01:09:03,500 porque que tropezamos con este problema 1517 01:09:03,500 --> 01:09:05,782 desde el principio, no pudimos comparar dos cadenas en C 1518 01:09:05,782 --> 01:09:07,490 porque compararíamos, accidentalmente, 1519 01:09:07,490 --> 01:09:11,370 sus ubicaciones, sus punteros, y no el valor real. 1520 01:09:11,370 --> 01:09:12,740 En este caso usamos str compare. 1521 01:09:12,740 --> 01:09:15,710 Y podía pasar el nombre que estoy buscando en el libro uno a 1522 01:09:15,710 --> 01:09:18,229 la vez, buscando la equivalencia de cero. if (strcmp (name, book[i]) == 0) 1523 01:09:18,229 --> 01:09:20,569 Puedo llamar a Mike, David o a quien sea 1524 01:09:20,569 --> 01:09:24,300 que intento llamar, o se detiene si no se encuentra al usuario. 1525 01:09:24,300 --> 01:09:25,970 ¿Qué hizo este programa? 1526 01:09:25,970 --> 01:09:31,060 Si paso a este ejemplo, que una vez más, era de la semana 3, 1527 01:09:31,060 --> 01:09:33,340 y hago make linear, 1528 01:09:33,340 --> 01:09:35,189 no, no eso. 1529 01:09:35,189 --> 01:09:36,830 Otra vez, directorio equivocado. 1530 01:09:36,830 --> 01:09:41,390 Si entro en source3 y make linear, este programa 1531 01:09:41,390 --> 01:09:43,240 se supone que se comporta de la siguiente manera. 1532 01:09:43,240 --> 01:09:47,850 Para continuar, ejecuto ./linear, busco a nuestro viejo amigo Smith, 1533 01:09:47,850 --> 01:09:48,859 encontró a Smith. 1534 01:09:48,859 --> 01:09:52,609 Si continúo y busco, digamos a Jones, que no dio clases anteriormente 1535 01:09:52,609 --> 01:09:54,061 en CS50, dice parar. 1536 01:09:54,061 --> 01:09:54,560 Muy bien. 1537 01:09:54,560 --> 01:10:00,710 Mientras tanto, en Python, nos podemos deshacer de todo eso. 1538 01:10:00,710 --> 01:10:05,600 En nuestro directorio src8, y en nuestro subdirectorio 3, 1539 01:10:05,600 --> 01:10:08,660 a continuación, en su lugar abriré esto. 1540 01:10:08,660 --> 01:10:12,650 En Python, puedo declarar un arreglo, también conocido como lista, 1541 01:10:12,650 --> 01:10:13,830 casi de la misma manera. 1542 01:10:13,830 --> 01:10:16,982 Para ser claro, ¿qué es diferente? 1543 01:10:16,982 --> 01:10:17,930 PÚBLICO: ¿Los corchetes? 1544 01:10:17,930 --> 01:10:19,640 DAVID: Entonces, los corchetes ahora son corchetes cuadrados 1545 01:10:19,640 --> 01:10:20,660 en lugar de llaves. 1546 01:10:20,660 --> 01:10:24,260 A menos que hayan inicializado estáticamente un arreglo en C, 1547 01:10:24,260 --> 01:10:26,270 como codificar los valores para su arreglo en C, 1548 01:10:26,270 --> 01:10:28,680 es posible que ni siquiera supiéramos que podíamos usar llaves. 1549 01:10:28,680 --> 01:10:30,150 Eso no es un gran problema aquí. 1550 01:10:30,150 --> 01:10:35,360 En Python, los corchetes representan una lista de elementos, 1551 01:10:35,360 --> 01:10:36,110 literalmente. 1552 01:10:36,110 --> 01:10:39,269 ¿Y qué más es diferente? 1553 01:10:39,269 --> 01:10:40,810 No declaré el tamaño del arreglo, 1554 01:10:40,810 --> 01:10:42,685 y técnicamente no tengo que hacer eso en C, 1555 01:10:42,685 --> 01:10:45,670 o bien, si codificamos todos los valores a la vez. 1556 01:10:45,670 --> 01:10:48,648 Hace falta algo en la línea 7. 1557 01:10:48,648 --> 01:10:49,529 PÚBLICO: El formato. 1558 01:10:49,529 --> 01:10:50,320 DAVID: ¿Perdón? 1559 01:10:50,320 --> 01:10:51,120 PÚBLICO: ¿El tipo? 1560 01:10:51,120 --> 01:10:51,730 DAVID: El tipo. 1561 01:10:51,730 --> 01:10:52,900 No especifiqué la cadena. 1562 01:10:52,900 --> 01:10:56,260 Esto es bastante similar a lo que hemos hecho en C. 1563 01:10:56,260 --> 01:10:58,130 Lo que es hermoso aquí, 1564 01:10:58,130 --> 01:11:01,310 para continuar, esconderé eso por solo un segundo. 1565 01:11:01,310 --> 01:11:05,170 A continuación, le pediré su nombre al usuario. 1566 01:11:05,170 --> 01:11:07,120 Pidamos su nombre aquí: name = get_string("Name: ") 1567 01:11:07,120 --> 01:11:10,660 Si quiero buscar book, que es solo una lista de nombres, 1568 01:11:10,660 --> 01:11:12,310 ¿cómo implemento la búsqueda lineal? 1569 01:11:12,310 --> 01:11:20,425 Podría hacer: if name in book: print ("Calling {name}") 1570 01:11:20,425 --> 01:11:22,510 Hagamos que esto sea una cadena f. 1571 01:11:22,510 --> 01:11:25,384 Aquí abajo, eso es todo. 1572 01:11:25,384 --> 01:11:27,550 Así es como se implementa la búsqueda lineal en Python. 1573 01:11:27,550 --> 01:11:28,600 No necesitamos un bucle, 1574 01:11:28,600 --> 01:11:30,730 solo hacernos una pregunta nosotros mismos. 1575 01:11:30,730 --> 01:11:35,490 Si book es una lista, y name es la cadena que buscamos, 1576 01:11:35,490 --> 01:11:39,280 solo le pediremos al lenguaje que nos resuelva esto. 1577 01:11:39,280 --> 01:11:43,420 if name in book, es la sintaxis que podemos usar para formular esa pregunta. 1578 01:11:43,420 --> 01:11:46,912 Python, probablemente, usará, la búsqueda lineal sobre esa lista 1579 01:11:46,912 --> 01:11:49,120 porque no necesariamente sabe que está ordenada, incluso 1580 01:11:49,120 --> 01:11:50,760 aunque lo esté de manera alfabética. 1581 01:11:50,760 --> 01:11:53,260 Lo encontrará para nosotros. Y nos lo salvará 1582 01:11:53,260 --> 01:11:58,180 de mucha complejidad y tiempo para implementar eso nosotros mismos. 1583 01:11:58,180 --> 01:12:02,270 Mientras tanto, si quiero comparar dos cadenas, 1584 01:12:02,270 --> 01:12:06,520 propondré esto, escribiré un programa rápido aquí, compare1.py. 1585 01:12:06,520 --> 01:12:11,150 Continuaré con: from cs50 import get_string 1586 01:12:11,150 --> 01:12:16,210 Proseguiré con: s = get_string("s: ") 1587 01:12:16,210 --> 01:12:20,410 Obtendré otra cadena a la que llamaré t: t = get_string("t: ") 1588 01:12:20,410 --> 01:12:22,480 cómo lo hicimos unas semanas atrás. 1589 01:12:22,480 --> 01:12:27,130 En C esto tenía errores, ¿cierto? 1590 01:12:27,130 --> 01:12:32,480 If s == t: print ("same") else: print ("different") 1591 01:12:32,480 --> 01:12:38,410 Solo para ser muy claro, ¿Por qué es incorrecta esta idea general 1592 01:12:38,410 --> 01:12:39,520 de usar dos signos de igual en C? 1593 01:12:39,520 --> 01:12:42,692 1594 01:12:42,692 --> 01:12:44,400 Sí, están comparando ubicaciones, ¿cierto? 1595 01:12:44,400 --> 01:12:47,070 Esto fue como el día antes de que desprendiéramos 1596 01:12:47,070 --> 01:12:49,350 la capa de lo que realmente es una cadena. 1597 01:12:49,350 --> 01:12:53,219 Al parecer, si s y t en C fueron char * o ubicaciones, 1598 01:12:53,219 --> 01:12:55,260 significa que si obtenemos dos cadenas diferentes, 1599 01:12:55,260 --> 01:12:56,880 incluso si escribimos los mismos caracteres, 1600 01:12:56,880 --> 01:12:58,530 se compararán dos ubicaciones diferentes, 1601 01:12:58,530 --> 01:13:00,040 que no serán lo mismo. 1602 01:13:00,040 --> 01:13:02,820 Tal vez lo podamos inferir del tema de hoy, 1603 01:13:02,820 --> 01:13:07,230 ¿Qué hará Python si se le pregunta si s y t son iguales? 1604 01:13:07,230 --> 01:13:11,250 Se responderá esa pregunta como lo esperaríamos de un humano. 1605 01:13:11,250 --> 01:13:14,910 En Python, el símbolo ==, comparará a s y a t, 1606 01:13:14,910 --> 01:13:17,730 mirará sus valores reales porque son cadenas, 1607 01:13:17,730 --> 01:13:21,550 y devolverá same si escribimos las mismas palabras. 1608 01:13:21,550 --> 01:13:27,520 Para continuar haré: python compare1.py, y escribiré, 1609 01:13:27,520 --> 01:13:33,360 por ejemplo, María, y después María, de hecho son: same. 1610 01:13:33,360 --> 01:13:36,420 Si escribo María y por ejemplo Stelios, son: 1611 01:13:36,420 --> 01:13:39,180 different, porque ahora compara las cadenas, 1612 01:13:39,180 --> 01:13:41,847 como lo esperamos hace algún tiempo. 1613 01:13:41,847 --> 01:13:43,680 Echemos un vistazo a otras cosas que 1614 01:13:43,680 --> 01:13:45,600 dieron lugar a algunos dilemas interesantes. 1615 01:13:45,600 --> 01:13:50,700 Podríamos recordar que en la semana cuatro, tuvimos este ejemplo en C, 1616 01:13:50,700 --> 01:13:54,850 noswap, llamado así porque esto simplemente no funcionó. 1617 01:13:54,850 --> 01:13:57,420 De manera lógica, aparentemente era correcto. 1618 01:13:57,420 --> 01:14:02,080 Swap no intercambió x y y, pero sí intercambió a y b. 1619 01:14:02,080 --> 01:14:02,580 ¿Por qué? 1620 01:14:02,580 --> 01:14:05,982 1621 01:14:05,982 --> 01:14:07,440 PÚBLICO: ¿Las ubicaciones en la memoria? 1622 01:14:07,440 --> 01:14:09,870 DAVID: Las ubicaciones en la memoria fueron diferentes, ¿cierto? 1623 01:14:09,870 --> 01:14:14,490 Recordemos, x y y son variables en C que existen en un fragmento de memoria 1624 01:14:14,490 --> 01:14:18,130 que llamamos un marco del stack, el marco principal en el stack. 1625 01:14:18,130 --> 01:14:22,130 Por su parte, a y b tienen ubicaciones un poco diferentes en la memoria. 1626 01:14:22,130 --> 01:14:23,880 Un poco más arriba, mantenemos un orden similar 1627 01:14:23,880 --> 01:14:27,700 como si apiláramos una bandeja del comedor en el denominado stack. 1628 01:14:27,700 --> 01:14:30,805 a y b tenían los mismos valores que x y y, 1629 01:14:30,805 --> 01:14:33,400 1 y 2, pero con sus propias copias. 1630 01:14:33,400 --> 01:14:36,230 A pesar de que de manera lógica, con Kate, creo, 1631 01:14:36,230 --> 01:14:39,150 y los Gatorade, los dos valores se intercambiaron, 1632 01:14:39,150 --> 01:14:41,280 finalmente intercambiamos los dos valores incorrectos 1633 01:14:41,280 --> 01:14:45,390 sin cambiar, de manera permanente, los x y y originales. 1634 01:14:45,390 --> 01:14:48,600 Desafortunadamente, vaya, afortunadamente y desafortunadamente en Python, 1635 01:14:48,600 --> 01:14:50,370 no hay tal cosa como un puntero. 1636 01:14:50,370 --> 01:14:51,797 Esos desaparecieron, 1637 01:14:51,797 --> 01:14:53,880 y ya no tenemos la expresividad con la que, 1638 01:14:53,880 --> 01:14:55,900 de esa manera, resolvíamos este problema. 1639 01:14:55,900 --> 01:15:01,980 Pero, propondré que lo hagamos de una manera muy astuta. 1640 01:15:01,980 --> 01:15:06,030 Para continuar, declararé: x = 1, y = 2. 1641 01:15:06,030 --> 01:15:07,710 A continuación, imprimiré tanto como sea posible 1642 01:15:07,710 --> 01:15:13,350 con una cadena de formato: print (f"x is {x}, y is {y}"), 1643 01:15:13,350 --> 01:15:15,240 al introducir sus respectivos valores. 1644 01:15:15,240 --> 01:15:16,710 pondré esta línea dos veces. 1645 01:15:16,710 --> 01:15:19,560 En medio de ellas, intentaré realizar este intercambio. 1646 01:15:19,560 --> 01:15:22,820 Si sus mentes están listas para explotar, 1647 01:15:22,820 --> 01:15:27,450 podemos hacer eso en Python, hacer el viejo intercambio en Python. 1648 01:15:27,450 --> 01:15:30,502 Esto intercambia los dos valores como esperamos: x, y = y, x. 1649 01:15:30,502 --> 01:15:31,960 Este no es un caso muy común. 1650 01:15:31,960 --> 01:15:34,500 Y para ser justos, este es un ejemplo increíblemente forzado 1651 01:15:34,500 --> 01:15:36,287 porque si necesitábamos que se intercambiaran, bueno, 1652 01:15:36,287 --> 01:15:38,620 tal vez lo debimos hacer en primer lugar. 1653 01:15:38,620 --> 01:15:40,980 Pero si se habla de una de las funciones de Python, 1654 01:15:40,980 --> 01:15:44,320 podemos hacer algo como eso. 1655 01:15:44,320 --> 01:15:48,180 Les presentaré una característica adicional que de manera reciente 1656 01:15:48,180 --> 01:15:51,360 se adquirió en C. Esa es la noción de una estructura. 1657 01:15:51,360 --> 01:15:54,320 Para continuar, haré ese en código desde cero. 1658 01:15:54,320 --> 01:15:58,410 Guardaré este archivo de manera anticipada como struct0.py, 1659 01:15:58,410 --> 01:16:00,630 es una reminiscencia de uno de nuestros programas más antiguos. 1660 01:16:00,630 --> 01:16:02,070 Iré directo a hacer eso: 1661 01:16:02,070 --> 01:16:05,730 from cs50 import get_string 1662 01:16:05,730 --> 01:16:07,590 Después, me daré una lista vacía: students = [ ] 1663 01:16:07,590 --> 01:16:09,840 Esa sería una manera convencional de darnos 1664 01:16:09,840 --> 01:16:11,400 una lista vacía en Python. 1665 01:16:11,400 --> 01:16:14,910 Al igual que en C, podemos declarar un arreglo vacío, 1666 01:16:14,910 --> 01:16:16,710 pero, en C debemos saber el tamaño del mismo 1667 01:16:16,710 --> 01:16:18,300 de lo contrario, tendremos que usar un puntero, 1668 01:16:18,300 --> 01:16:19,290 o también tenemos a malloc. 1669 01:16:19,290 --> 01:16:19,789 No. 1670 01:16:19,789 --> 01:16:21,000 Todo eso desapareció. 1671 01:16:21,000 --> 01:16:22,509 Ahora en Python, ¿queremos una lista? 1672 01:16:22,509 --> 01:16:23,550 Solo diremos, necesitamos una lista. 1673 01:16:23,550 --> 01:16:25,900 que crecerá y se reducirá lo que se necesite. 1674 01:16:25,900 --> 01:16:28,950 Para continuar, lo haré tres veces, arbitrariamente: 1675 01:16:28,950 --> 01:16:31,590 for i in range [3], a continuación, preguntaré 1676 01:16:31,590 --> 01:16:34,590 un nombre al usuario que use get_string: 1677 01:16:34,590 --> 01:16:36,720 name = get_string("Name: ") 1678 01:16:36,720 --> 01:16:39,570 Dorm también usará get_string: dorm = get_string("Dorm: ") 1679 01:16:39,570 --> 01:16:40,650 Dorm está aquí. 1680 01:16:40,650 --> 01:16:45,180 Quiero añadir al arreglo a este estudiante. 1681 01:16:45,180 --> 01:16:52,260 Entonces, podría hacer algo como esto: students.append(name). 1682 01:16:52,260 --> 01:16:54,510 Resulta que... aún no hemos dicho esto. 1683 01:16:54,510 --> 01:16:58,790 Pero hay dentro del tipo de listas de datos un método 1684 01:16:58,790 --> 01:17:02,460 que es una función integrada llamada append, que añade caracteres. 1685 01:17:02,460 --> 01:17:05,530 Si tenemos una lista vacía, 1686 01:17:05,530 --> 01:17:07,477 y la llamamos por su nombre.append, 1687 01:17:07,477 --> 01:17:09,310 agregaremos algo al final de la lista. 1688 01:17:09,310 --> 01:17:10,920 Si no hay suficiente memoria para eso, no es problema. 1689 01:17:10,920 --> 01:17:14,250 Python nos encontrará la memoria, la asignará, moverá todo en ella, 1690 01:17:14,250 --> 01:17:17,160 y seguiremos nuestro camino sin preocuparnos por eso. 1691 01:17:17,160 --> 01:17:19,320 Pero, no se quiere almacenar solo el nombre, 1692 01:17:19,320 --> 01:17:21,510 se quiere guardar el nombre y el dormitorio, 1693 01:17:21,510 --> 01:17:23,200 entonces se podría hacer esto. 1694 01:17:23,200 --> 01:17:25,770 Podría ... bueno, tal vez no queremos estudiantes. 1695 01:17:25,770 --> 01:17:27,720 Tal vez algo como los dormitorios: dorms = [ ] 1696 01:17:27,720 --> 01:17:32,910 Y aquí podría hacer: dorms.append(dorm) 1697 01:17:32,910 --> 01:17:36,750 ¿Por qué esto se convirtió en un mal diseño 1698 01:17:36,750 --> 01:17:40,260 si mi objetivo era asociar a un alumno con su dormitorio, 1699 01:17:40,260 --> 01:17:42,370 y después mantener esos valores juntos? 1700 01:17:42,370 --> 01:17:47,010 ¿Por qué tener dos arreglos separados no es el mejor método 1701 01:17:47,010 --> 01:17:50,110 en Python o incluso en C? 1702 01:17:50,110 --> 01:17:51,460 PÚBLICO: ¿Puede ser la estructura? 1703 01:17:51,460 --> 01:17:52,501 DAVID: ¿Qué es eso? 1704 01:17:52,501 --> 01:17:53,710 PÚBLICO: ¿La estructura? 1705 01:17:53,710 --> 01:17:57,467 DAVID: Seguro, hay que mantener el doble de cosas. 1706 01:17:57,467 --> 01:17:58,050 Y, ¿qué más? 1707 01:17:58,050 --> 01:18:00,030 PÚBLICO: No podemos mapearlos uno con el otro. 1708 01:18:00,030 --> 01:18:01,863 DAVID: No podemos mapearlos el uno con el otro. 1709 01:18:01,863 --> 01:18:03,540 Eso es muy arbitrario. 1710 01:18:03,540 --> 01:18:06,090 Haré un tipo de contrato social, 1711 01:18:06,090 --> 01:18:10,110 supongamos que el alumno 0 vive en el dormitorio 0, 1712 01:18:10,110 --> 01:18:12,594 y el estudiante 1 vive en el dormitorio 1. 1713 01:18:12,594 --> 01:18:13,260 Eso está bien, 1714 01:18:13,260 --> 01:18:14,190 y puede ser cierto. 1715 01:18:14,190 --> 01:18:16,790 Pero, una de las funciones de las ciencias de la computación y de la programación 1716 01:18:16,790 --> 01:18:19,890 es la idea de encapsular, es decir, asociar memoria relacionada 1717 01:18:19,890 --> 01:18:20,950 con otra. 1718 01:18:20,950 --> 01:18:22,560 ¿Qué hicimos en C? 1719 01:18:22,560 --> 01:18:24,427 No teníamos dos arreglos. 1720 01:18:24,427 --> 01:18:25,602 PÚBLICO: Tuvimos una estructura. 1721 01:18:25,602 --> 01:18:27,060 DAVID: Sí, tuvimos una estructura. 1722 01:18:27,060 --> 01:18:30,140 Así que, Python no tiene estructuras, per se. 1723 01:18:30,140 --> 01:18:31,994 En su lugar tiene algo llamado clases, 1724 01:18:31,994 --> 01:18:34,410 y algunas otras cosas como los tuples y namedtuples, 1725 01:18:34,410 --> 01:18:36,400 veremos más de eso en otro momento. 1726 01:18:36,400 --> 01:18:41,100 Al parecer, se puede implementar nuestra noción de estudiante, 1727 01:18:41,100 --> 01:18:43,050 y podría importarlo así. 1728 01:18:43,050 --> 01:18:46,380 La convención en Python es, si creamos nuestra propia estructura, 1729 01:18:46,380 --> 01:18:49,740 en lo sucesivo la llamaremos clase, y por convención iniciaremos su nombre 1730 01:18:49,740 --> 01:18:50,440 con mayúscula. 1731 01:18:50,440 --> 01:18:52,350 Es algo un poco diferente a las convenciones de C. 1732 01:18:52,350 --> 01:18:54,360 ¿Cómo lucirá un estudiante? 1733 01:18:54,360 --> 01:18:57,030 Esta es, tal vez, la sintaxis más compleja que tendremos hoy, 1734 01:18:57,030 --> 01:18:59,040 solo tiene unas pocas líneas. 1735 01:18:59,040 --> 01:19:02,960 Si queremos implementar la noción de un estudiante, ¿cómo podríamos hacerlo? 1736 01:19:02,960 --> 01:19:06,300 En Python, decimos clase Student, 1737 01:19:06,300 --> 01:19:09,240 donde clase es similar a, solo para ser claro, 1738 01:19:09,240 --> 01:19:11,250 struct o typedef struct. 1739 01:19:11,250 --> 01:19:13,620 Pero en Python, solo decimos clase, 1740 01:19:13,620 --> 01:19:15,540 después esta es la parte rara. 1741 01:19:15,540 --> 01:19:21,330 Podemos declarar una función que por convención se deberá llamar init 1742 01:19:21,330 --> 01:19:25,380 por inicializar, y toma como primer argumento la palabra clave llamada 1743 01:19:25,380 --> 01:19:30,180 self, y otros argumentos como estos: def __init__(self, name, dorm): 1744 01:19:30,180 --> 01:19:34,620 Por razones que, con suerte, aclararé en un momento, 1745 01:19:34,620 --> 01:19:37,000 escribiré un código dentro de este método. 1746 01:19:37,000 --> 01:19:39,090 En resumen, ¿qué hice aquí? 1747 01:19:39,090 --> 01:19:42,810 Declaré un nuevo tipo de estructura de datos llamada Student, 1748 01:19:42,810 --> 01:19:45,420 y dentro de esta estructura de datos, de manera implícita, 1749 01:19:45,420 --> 01:19:47,580 hay dos cosas dentro de sí mismas, 1750 01:19:47,580 --> 01:19:50,370 algo llamado name y algo llamado dorm. 1751 01:19:50,370 --> 01:19:53,280 Así es como normalmente haríamos normalmente una estructura en C 1752 01:19:53,280 --> 01:19:56,790 con los tipos de datos y puntos y comas dentro de las llaves. 1753 01:19:56,790 --> 01:19:59,250 Mientras tanto, hay un método aquí. 1754 01:19:59,250 --> 01:20:02,820 Este método, en lo que cabe, está dentro de clase. 1755 01:20:02,820 --> 01:20:05,550 De lo contrario, es una función, con un nombre diferente. 1756 01:20:05,550 --> 01:20:09,990 Este método init toma lo que en sí mismo, hablaré más sobre eso en otro momento. 1757 01:20:09,990 --> 01:20:13,020 Pero, toma cero o más argumentos personalizados que podemos proporcionar, 1758 01:20:13,020 --> 01:20:14,730 y se llamaron nam y dorm. 1759 01:20:14,730 --> 01:20:17,370 Este método especial init 1760 01:20:17,370 --> 01:20:21,450 es una función que llamaremos de manera automática cada vez que se 1761 01:20:21,450 --> 01:20:24,160 crea el objeto Student. 1762 01:20:24,160 --> 01:20:26,010 ¿Qué es lo que eso significa? 1763 01:20:26,010 --> 01:20:30,150 Eso significa que en nuestro código podemos hacer esto. 1764 01:20:30,150 --> 01:20:36,810 Se puede crear un alumno en la memoria al decir: 1765 01:20:36,810 --> 01:20:38,070 s = Student(name, dorm) 1766 01:20:38,070 --> 01:20:40,606 No tenemos esta función en C. 1767 01:20:40,606 --> 01:20:42,480 En el lado derecho, lo que se destacó 1768 01:20:42,480 --> 01:20:45,540 es el nombre de la clase y sus dos argumentos, 1769 01:20:45,540 --> 01:20:48,670 name y dorm, que son lo que el usuario exactamente escribió. 1770 01:20:48,670 --> 01:20:52,704 Lo que clase hace por mí, es que me asigna memoria 1771 01:20:52,704 --> 01:20:54,120 por debajo del agua para Student. 1772 01:20:54,120 --> 01:20:56,190 Tiene que ser lo bastante grande para name y para dorm, 1773 01:20:56,190 --> 01:20:58,590 así de grande, por así decirlo, en la memoria. 1774 01:20:58,590 --> 01:21:02,220 Y se ponen las cadenas name y dorm en ese objeto, 1775 01:21:02,220 --> 01:21:04,660 que devuelve al objeto completo. 1776 01:21:04,660 --> 01:21:08,730 Podemos pensar esto como una versión mucho más elegante de malloc, 1777 01:21:08,730 --> 01:21:10,950 que asigna toda la memoria que necesitamos. 1778 01:21:10,950 --> 01:21:14,700 Pero también se instala dentro de la memoria de name y dorm, 1779 01:21:14,700 --> 01:21:18,870 y lo agrupa, no solo dentro de un pedazo arbitrario de memoria, 1780 01:21:18,870 --> 01:21:23,910 en algo que podemos llamar el objeto Student. 1781 01:21:23,910 --> 01:21:26,760 Ahora, para nuestros estudiantes todo esto significa 1782 01:21:26,760 --> 01:21:30,460 que podemos continuar y anexar a ese estudiante a la lista. 1783 01:21:30,460 --> 01:21:36,450 Si más adelante quiero iterar: for student in students 1784 01:21:36,450 --> 01:21:42,030 A continuación imprimiré: 1785 01:21:42,030 --> 01:21:47,170 print (f"student name lives in {student.dorm"}) 1786 01:21:47,170 --> 01:21:49,380 Y si ahora por aquí, 1787 01:21:49,380 --> 01:21:51,450 ups, se cierra eso. 1788 01:21:51,450 --> 01:21:56,520 Para continuar, ejecuto: python struct0.py, 1789 01:21:56,520 --> 01:21:59,275 ¡Oh no! 1790 01:21:59,275 --> 01:22:01,920 Oh, gracias. 1791 01:22:01,920 --> 01:22:03,240 Eso va ahí, 1792 01:22:03,240 --> 01:22:04,220 Entonces ahora, diablos. 1793 01:22:04,220 --> 01:22:06,992 1794 01:22:06,992 --> 01:22:11,350 Llave perdida, gracias. 1795 01:22:11,350 --> 01:22:11,850 OK. 1796 01:22:11,850 --> 01:22:15,390 Para continuar, escribiré: María, Cabot, David, Mather, 1797 01:22:15,390 --> 01:22:20,160 Rob, y por ejemplo, Kirkland, ahora tenemos 1798 01:22:20,160 --> 01:22:20,820 los tres nombres. 1799 01:22:20,820 --> 01:22:22,528 También, hay otras maneras, si quisiéramos 1800 01:22:22,528 --> 01:22:25,080 de almacenar esto en disco. 1801 01:22:25,080 --> 01:22:27,420 Postergaré eso para un ejemplo en línea. 1802 01:22:27,420 --> 01:22:30,690 Veamos un ejemplo final, que con suerte 1803 01:22:30,690 --> 01:22:32,760 hará que nos arrepintamos de las últimas semanas o, 1804 01:22:32,760 --> 01:22:35,640 en cambio, aprovechemos las siguientes. 1805 01:22:35,640 --> 01:22:38,822 Recordemos eso, 1806 01:22:38,822 --> 01:22:41,530 aunque el primero, se supone, podría ser cierto incluso sin mi ayuda. 1807 01:22:41,530 --> 01:22:46,320 Si vamos al código de distribución, veremos este programa, 1808 01:22:46,320 --> 01:22:48,240 y no recorreremos todas sus líneas. 1809 01:22:48,240 --> 01:22:51,390 Este es un programa escrito en Python llamado speller. 1810 01:22:51,390 --> 01:22:55,350 ¿Qué fue lo que me bloqueó con speller.c desde la serie de problemas 5? 1811 01:22:55,350 --> 01:22:58,830 Hace poco lo convertí de izquierda a derecha, desde C a Python, 1812 01:22:58,830 --> 01:23:03,300 y se implementó en Python de la manera más cercana a la que se pudo, 1813 01:23:03,300 --> 01:23:05,190 al usar las funciones de Python. 1814 01:23:05,190 --> 01:23:08,940 Solo con un vistazo, veremos que en apariencia mi implementación de speller 1815 01:23:08,940 --> 01:23:12,480 en Python hay una clase llamada Dictionary, la cual es muy similar a 1816 01:23:12,480 --> 01:23:16,290 dictionary.h en C. Notemos que todavía se tiene una constante aquí. 1817 01:23:16,290 --> 01:23:19,740 No es una constante, es una variable llamada length que es igual a 45. 1818 01:23:19,740 --> 01:23:23,520 Como lo hizo speller.c, también lo codifiqué en dictionaries/large. 1819 01:23:23,520 --> 01:23:26,230 Se usaron argumentos de línea de comandos, como lo vimos anteriormente, 1820 01:23:26,230 --> 01:23:28,710 pero en vez de C se implementó en Python. 1821 01:23:28,710 --> 01:23:31,050 Noten que podemos hacer cosas raras como esta, 1822 01:23:31,050 --> 01:23:33,930 que es una reminiscencia de nuestro truco de intercambio de hace un poco. 1823 01:23:33,930 --> 01:23:36,960 Si queremos declarar varias variables, todas en la misma línea 1824 01:23:36,960 --> 01:23:40,200 e inicializarlas, podemos enumerarlas con comas. 1825 01:23:40,200 --> 01:23:42,330 Entonces, del otro lado del signo igual, 1826 01:23:42,330 --> 01:23:46,290 enumeraré con comas los valores que deseamos asignar a esas variables. 1827 01:23:46,290 --> 01:23:49,440 Si nos desplazamos hacia abajo, 1828 01:23:49,440 --> 01:23:53,110 veremos en el código, sin tantos detalles, algunas frases familiares. 1829 01:23:53,110 --> 01:23:57,120 Este es el programa que ejecuta un diccionario para estudiantes 1830 01:23:57,120 --> 01:24:02,490 en alguna entrada, y después imprime todo esto en la parte inferior, 1831 01:24:02,490 --> 01:24:06,060 todas las frases familiares que podríamos recordar de la serie de problemas cinco. 1832 01:24:06,060 --> 01:24:09,567 Implementarlo en C tomó mucho trabajo. De manera comprensible, 1833 01:24:09,567 --> 01:24:11,400 posiblemente se usó una lista vinculada inicialmente, 1834 01:24:11,400 --> 01:24:13,790 o en última instancia, pudimos usar una tabla hash o tatar 1835 01:24:13,790 --> 01:24:15,870 o luchar con algo entre esas dos. 1836 01:24:15,870 --> 01:24:19,161 Eso es una función de C, es difícil, 1837 01:24:19,161 --> 01:24:21,660 es un desafío, porque tenemos que hacer todo por nuestra cuenta. 1838 01:24:21,660 --> 01:24:25,960 Una ventaja es que, en teoría, se obtiene un 1839 01:24:25,960 --> 01:24:26,875 gran rendimiento, 1840 01:24:26,875 --> 01:24:30,000 Una vez que se implementó el código, estaremos tan cerca del hardware 1841 01:24:30,000 --> 01:24:30,790 como sea posible. 1842 01:24:30,790 --> 01:24:33,450 Nuestro código se ejecuta bastante bien y depende 1843 01:24:33,450 --> 01:24:37,500 solo de nuestros algoritmos, no de nuestra elección de lenguaje. 1844 01:24:37,500 --> 01:24:41,010 Continuaré con la implementación de un archivo llamado dictionary.py. 1845 01:24:41,010 --> 01:24:44,690 Propondré esas palabras: class Dictionary: 1846 01:24:44,690 --> 01:24:50,400 el equivalente, lo siento, de dictionary.h sería este archivo. 1847 01:24:50,400 --> 01:24:54,420 Y tendrá una función llamada check, 1848 01:24:54,420 --> 01:24:57,030 que toma un argumento llamado word: def check(self, word): 1849 01:24:57,030 --> 01:24:59,760 Tendrá una función llamada load, que 1850 01:24:59,760 --> 01:25:02,520 toma un argumento que se llama dictionary: def load(self, dictionary): 1851 01:25:02,520 --> 01:25:08,430 Tendrá un método llamado size, que no toma otro argumento más que así mismo: 1852 01:25:08,430 --> 01:25:10,535 def size(self): 1853 01:25:10,535 --> 01:25:12,660 Tendrá un método llamado unload, que tampoco toma otro argumento que así mismo: 1854 01:25:12,660 --> 01:25:14,980 def unload(self): 1855 01:25:14,980 --> 01:25:18,300 Si les hubiéramos asignado la serie de problemas cinco en Python, 1856 01:25:18,300 --> 01:25:20,960 esencialmente, le habríamos dado un archivo llamado dictionary.py 1857 01:25:20,960 --> 01:25:23,460 con estos marcadores de posición ya que recuerdan a la serie de problemas cinco, 1858 01:25:23,460 --> 01:25:25,230 todos esos fueron para dos. 1859 01:25:25,230 --> 01:25:27,660 En sentido estricto, podría haber otro aquí. 1860 01:25:27,660 --> 01:25:31,260 Probablemente por cada clase en Python tendremos: def __init__(self): 1861 01:25:31,260 --> 01:25:33,780 porque cada clase en Python, normalmente tiene este método init, 1862 01:25:33,780 --> 01:25:38,459 para inicializar la estructura de datos: self.words = set( ) 1863 01:25:38,459 --> 01:25:39,750 Para continuar, haré esto, 1864 01:25:39,750 --> 01:25:41,460 todavía no sabemos mucho de Python, 1865 01:25:41,460 --> 01:25:44,470 y damos por hecho que el deletreo funciona. 1866 01:25:44,470 --> 01:25:46,960 A continuación, cargaré algunas palabras en dictionary, 1867 01:25:46,960 --> 01:25:48,829 con mi método llamado load. 1868 01:25:48,829 --> 01:25:51,370 Dictionary es el nombre del diccionario que se cargará 1869 01:25:51,370 --> 01:25:55,830 ustedes mismos implementaron esto al cargar esos archivos desde el disco. 1870 01:25:55,830 --> 01:25:58,110 Haré lo siguiente en Python: 1871 01:25:58,110 --> 01:26:02,100 file = open(dictionary, "r") 1872 01:26:02,100 --> 01:26:05,790 for line in file: 1873 01:26:05,790 --> 01:26:10,590 Para continuar, agregaré: 1874 01:26:10,590 --> 01:26:16,230 self.word.add(line.rstrip("\ n")) 1875 01:26:16,230 --> 01:26:20,970 Continuaré con: file.close( ) return True 1876 01:26:20,970 --> 01:26:23,340 se terminó de implementar load. 1877 01:26:23,340 --> 01:26:27,760 Ese es el método load en Python. 1878 01:26:27,760 --> 01:26:28,500 ¡Sí, estoy feliz! 1879 01:26:28,500 --> 01:26:29,000 OK. 1880 01:26:29,000 --> 01:26:29,766 Así que, verifiquemos, 1881 01:26:29,766 --> 01:26:31,140 verificar también es una lucha, ¿cierto? 1882 01:26:31,140 --> 01:26:33,690 Porque una vez que tengamos nuestra tabla hash, o una vez que tratemos 1883 01:26:33,690 --> 01:26:35,850 de navegar en esa estructura en la memoria, 1884 01:26:35,850 --> 01:26:38,016 recursivamente, o de manera repetitiva, al seguir muchos 1885 01:26:38,016 --> 01:26:40,330 de punteros y similares, al seguir una lista vinculada. 1886 01:26:40,330 --> 01:26:42,950 ¿Qué tal si yo solo hago? 1887 01:26:42,950 --> 01:26:54,980 if word.lower( ) in self.words: return True 1888 01:26:54,980 --> 01:26:56,960 else: return False 1889 01:26:56,960 --> 01:26:59,280 Terminamos, 1890 01:26:59,280 --> 01:27:01,210 hemos terminado. 1891 01:27:01,210 --> 01:27:04,170 Size, podemos inferir cómo hacer esto: 1892 01:27:04,170 --> 01:27:06,630 return len(self.words) 1893 01:27:06,630 --> 01:27:07,610 ¡Terminamos! 1894 01:27:07,610 --> 01:27:11,430 Unload, no nos preocuparemos por la memoria de Python, terminamos. 1895 01:27:11,430 --> 01:27:13,685 Ahí está, un problema de la serie cinco. 1896 01:27:13,685 --> 01:27:14,260 [APLAUSOS] 1897 01:27:14,260 --> 01:27:16,320 Gracias. 1898 01:27:16,320 --> 01:27:18,960 ¿Cuáles son las conclusiones? 1899 01:27:18,960 --> 01:27:22,227 Sienten gran euforia de que ahora tienen este poder, o gran tristeza de que 1900 01:27:22,227 --> 01:27:24,810 primero implementaron eso en C. Pero esto 1901 01:27:24,810 --> 01:27:26,280 en última instancia, pretende ser temático. 1902 01:27:26,280 --> 01:27:29,280 Esperemos seguir adelante, aún si tuvimos problemas con cualquiera de estos 1903 01:27:29,280 --> 01:27:31,860 temas, listas vinculadas, tablas hash, punteros y similares, 1904 01:27:31,860 --> 01:27:33,300 con suerte tendremos una comprensión general 1905 01:27:33,300 --> 01:27:35,550 de algunos de estos fundamentos y lo qué las computadoras 1906 01:27:35,550 --> 01:27:36,870 hacen por debajo del agua. 1907 01:27:36,870 --> 01:27:40,740 Y ahora con lenguajes como Python y pronto con JavaScript, SQL, 1908 01:27:40,740 --> 01:27:43,984 con un poco de HTML y CSS mezclados para nuestras interfaces de usuario, 1909 01:27:43,984 --> 01:27:45,900 tendremos la capacidad de resolver problemas, 1910 01:27:45,900 --> 01:27:49,020 dando por hecho tanto su comprensión de esos temas 1911 01:27:49,020 --> 01:27:52,974 y la realidad de que alguien más implementó esos conceptos para nosotros 1912 01:27:52,974 --> 01:27:55,890 de modo que cuando se trate de resolver la serie de problemas seis, siete y ocho, 1913 01:27:55,890 --> 01:27:58,650 y después de dejar CS50 y resuelvan problemas de su propio dominio, 1914 01:27:58,650 --> 01:28:00,900 tengan muchas más herramientas en su kit. 1915 01:28:00,900 --> 01:28:03,870 El objetivo para ustedes será elegir 1916 01:28:03,870 --> 01:28:05,814 el que sea más apropiado. 1917 01:28:05,814 --> 01:28:06,730 Así que, ¡levantémonos de aquí! 1918 01:28:06,730 --> 01:28:07,770 Me quedaré para responder preguntas. 1919 01:28:07,770 --> 01:28:09,160 Nos vemos la próxima vez. 1920 01:28:09,160 --> 01:28:11,420 ¡Que tengan la mejor de las suertes en el examen!