How to Think Like a Computer Scientist

492 views

Published on

Published in: Education, Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
492
On SlideShare
0
From Embeds
0
Number of Embeds
20
Actions
Shares
0
Downloads
4
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

How to Think Like a Computer Scientist

  1. 1. HowtoThinkLike a ComputerScientist<br />Juan G. VélezRodríguez<br />Joane M. De JesúsDátiz<br />23 de junio de 2010<br />
  2. 2. Capítulo 6: “Interation”<br />
  3. 3. Multiple Assignment<br />Podemos asignar distintos valores a una misma variable.<br />Es legal asignarle el mismo nombre a diferentes variables ya que al hacerlo, la variable deja de hacer referencia al valor anterior (valor original) y comienza a referirse a un nuevo valor.<br />
  4. 4. Ejemplo<br />bruce = 5<br />print bruce, <br />bruce = 7<br />print bruce<br />La coma se interpone y tomaprioridad ante el “new line” paraque los resultadosquedenuno al lado del otro y no en distintaslíneas.<br />Resultado en la Pantalla:<br />5 7<br />
  5. 5. Diagrama de Estado<br />bruce<br />5<br />7<br />Deja de ser un 5 para ser un 7.<br />
  6. 6. <ul><li> Es importanterecalcarquelasigualdades en Matemáticas son conmutativaspero la asignación de variables en Python no lo son.
  7. 7. Porejemplo, en Matemáticassi a = 7 entonces 7 = a.
  8. 8. En Phytones legal decirque a = 7 perodecirque 7 = a no lo es.</li></li></ul><li>The While Statement (Mientras)<br /><ul><li> Las computadorasrealizantareasrepetitivas.
  9. 9. Repetirtareasidénticasesunatareaquelascomputadorasrealizanbastantebien, algoque los sereshumanos no realizaríanmuybien.
  10. 10. Estasrepeticiones se conocencomo “Iteration”.</li></li></ul><li>Ejemplo de un While<br />def countdown (n):<br /> while n> 0:<br /> print n<br /> n = n-1<br /> print “Blastoff!”<br />Estafuncióncontinuarámostrando el valor de n y lo va a reducir de uno en unohastallegar a 0 queescuando el programatermina y muestra la palabra Blastoff!.<br />
  11. 11. Lo queocurre en el While es lo siguiente: <br />Se evalúa la condición, 0 ó 1<br />Si la condiciónesfalsa (0), se sale del While y continúa con el próximoestado.<br />Si la condiciónescierta (1), se ejecutancadauno de los estados en el “body” y se regresa al paso 1.<br /> El “body” o cuerpoconsiste de todos los estadosbajo el encabezamientoquecontienen la mismaalineación, “tabs”, dentro del loop.<br />
  12. 12. Loop (Lazo)<br />Este tipo de estado se conocetambiéncomo un “loop” debido a queluego del tercerpaso, regresanuevamente al comienzo de la función.<br />Notemosquesi la condiciónesfalsadesde el comienzo, los estadosdentro del lazo no seránejecutadospues no seránecesario.<br />El cuerpo del lazodebecambiar el valor de una o más variables paraqueeventualmente la condición sea falsa y el lazotermine.<br />
  13. 13. LazoInfinito (Infinite Loop)<br />Se puededar el caso en el que un lazo no tenga final y sigarepitiéndoseparasiempre.<br />Los Científicos de Computadorascomparanesto con lasdirecciones al usar un “Shampoo”.<br />Ejemplo:<br />Lavado, enjuague, repetir.<br />
  14. 14. LazoInfinito (Infinite Loop)<br />En el caso de la función “countdown”, podemoscomprobarque el lazoterminayaque el valor de nesfinito, podemosverquenvadecreciendocadavezque el lazo se ejecuta y eventualementeobtenemos el valor de 0.<br />
  15. 15. Otroscasos…<br />Hay vecesque no es tan fácil de mostrar:<br />def sequence (n):<br /> while n != 1:<br /> print n, <br /> if n%2 ==0: # n es un número par<br /> n = n/2<br /> else: # n es un númeroimpar<br /> n = n*3+1<br />
  16. 16. Cadavezque el programaejecuta, compruebasi el númeroes par o impar. Si es par lo divide entre 2. Si esimpar, reemplaza el valor por n*3+1.<br />Debido a que n algunasvecesaumenta o disminuye, no hay pruebaobviaparadecirquenalcanzará el 1 o que el programatermine.<br />Una de lasventajasquetienen los lazosesque son buenosparagenerartablas.<br />
  17. 17. Tablas <br />Antes de queexistieranlascomputadoras, las personas teníanquecalcularlogaritmos, senos, cosenos y otrasfuncionesmatemáticas a mano.<br />Para facilitarse la vida, en los libros de matemáticas se incluíangrandestablasqueincluíanestosvalores. <br />Crearlastablas era lento y aburrido y podíancontenererrores.<br />
  18. 18. Ejemplo de Tablas<br />El siguienteprogramamuestraunasecuencia de valores en la columna de la izquierda y suslogartimos en la columna de la derecha.<br />x= 1.0<br />while x <10.0:<br /> print x, ‘ ’ , math.log(x)<br /> x = x +1.0<br />
  19. 19. Tabla<br /><ul><li>Si esosvalores de la tabla anterior los queremos con un logaritmo de base 2 entoncesdebemosusar la siguientefórmula :</li></li></ul><li>Continuación<br />Si realizamos el siguientecambio en el código:<br /> print x, ‘/t’, math.log(x)/math.log(2.0)<br />Obtenemos: <br />
  20. 20. Vimosque los números 1, 2, 4 y 8 son potencias del 2 yaquesuslogaritmos de base 2 son númerosenteros. <br />Si queremosencontrarotroslogaritmos de potencia 2 podemosmodificar el programa de éstamanera:<br />x = 1.0<br />while x < 100.0<br /> print x, ‘/t’, math.log(x)/math.log(2.0)<br /> x = x * 2.0<br />
  21. 21. Resultado<br />
  22. 22. Tabla de dos dimensiones<br />Tabla en la cual se leen los valores en la intersección entre unafila y unacolumna. <br />Ejemplo: tabla de multiplicar.<br />Crearemosunatabla de multiplicar del 1 al 6 utilizando un lazoqueimprima los múltiplos de dos en unalínea.<br />i = 1 #counter<br /> while i <= 6:<br /> print 2*1, ‘ ’,<br />i = i + 1<br /> print #Resultados: 2, 4, 6, 8, 10, 12<br />
  23. 23. Encapsulación y Generalización<br />Encapsulaciónes el proceso de empacarunapieza del código en unafunción.<br />Generalizaciónsignificatomaralgo en específico, comoimprimir los múltiplos de 2 y hacerlomásgeneralizado, comoimprimir los múltiplos de cualquiernúmeroentero.<br />
  24. 24. Ejemplo<br />La siguientefunciónencapsula el lazo anterior y lo generalizaparaqueimprima los múltiplos de n:<br />def printMultiples(n):<br />i = 1<br /> while I <= 6:<br /> print n*i, ‘ ’,<br />i = i + 1<br /> print<br />Para encapsular, lo quedebemoshaceresañadir la primeralíneaquees la quedeclara el nombre de la función y la lista de parámetros. Para generalizar, solo reemplazamos el 2 por el parámetron.<br />
  25. 25. ContinuaciónEncapsulación y Generalización<br />Si invocamoséstafunción con el argumento 2, obtenemos los mismosvalores en pantalla.<br />Con el argumento 3 obtenemos:<br /> 3, 6, 9, 12, 15, 18<br />Con el argumento 4 obtenemos:<br /> 4, 8, 12, 16, 20, 24<br />Si invocamosprintMultiples en repetidasocasiones con diferentesargumentosobtenemosunatabla de multiplicar.<br />
  26. 26. ContinuaciónEncapsulación y Generalización<br />En esecasopodemosutilizarotrolazo (Loop):<br />i = 1<br />while i <= 6:<br />printMultiples(i)<br />i = i + 1<br />Obtenemos:<br />
  27. 27. Variables Locales<br />Las variables quehansidodefinidasdentro de unafunción no pueden ser accesadasdesdeafuera de esafunción.<br />Se puedetenermúltiples variables con el mismonombresiempre y cuando no esténdentro de la mismafunción.<br />
  28. 28. Stack Diagram<br />Dos variables distintasllamadasiquecambian de valor sin afectarseuna con la otra.<br />
  29. 29. Ejemplo de Generalización<br />Para crearunatabla de multiplicación de cualquiertamaño, sólo hay queañadir un parámetro a printMultTable:<br />def printMultTable(high):<br />i = 1<br /> while i <= high:<br />printMultiples(i)<br />i = i + 1<br />
  30. 30. Reemplazamos el valor 6 por el de “high”.<br />Si llamamos “printMultTable ” con el argumento 7 nosmuestra:<br />
  31. 31. Funciones<br />Darle un nombre a unasecuencia de estados (statements) hacesuprogramafácil de leer y de ejecutar.<br />Dividir un programa en variasfuncionesnospermiteseparar el programa en partes, ejecutarellasporseparado y luegoadjuntarlas en un solo componente. <br />
  32. 32. Facilitan la recursión y la iteración. (Loops)<br />Funcionesbiendiseñadas son útilesparavariosprogramas. Unavez se escribe y se ejecutaalguna, se puedenreusar.<br />
  33. 33. Capítulo 7: “Strings”<br />
  34. 34. Datos<br />Hastaestepunto, hemosvistodistintostipos de datos, porejemplo, “int”, “float”, “string”.<br />Los “strings” son cualitativamentedistintos de los otros dos tipos de datosyaqueestancompuestos de pequeñaspiezas– caracteres.<br />Tipos de datosquecontienenpiezaspequeñas son conocidoscomo “compound data types.”<br />
  35. 35. Los corchetesseleccionan un solo caracter del string:<br />>>> fruit = “banana”<br /> >>> letter = fruit[1]<br /> >>> print letter<br />La expresión fruit [1] selecciona el caracter en la posición 1 de la palabra fruit. <br />Cuando “letter” aparece en la pantalla, nosmuestra la letra a.<br />La primeraletra de la palabra banana es b, peroestaletraesta en la posición 0 y esporesoqueaparece la letra a, quees la queestá en la posición 1.<br />
  36. 36. Índice<br />La expresiónqueestá en corchetes se conocecomoíndice (index).<br />Un índiceespecifica un miembro de un conjuntoordenado, en estecaso, el conjunto de caracteres en el string.<br />El índiceindicaquecaracteres el quequeremos, en vez de sunombre. Puede ser un entero.<br />
  37. 37. Length (Longitud)<br />La función “len” nosdevuelve el número de caracteres en un “string”.<br />>>> fruit = “banana”<br />>>> len(fruit)<br />6<br />
  38. 38. Length<br />Para obtener el últimocaracter de un “string”, debemosrestar 1 del “length”<br />length = len(fruit)<br />last = fruit[length-1]<br />Si utilizamosíndicesnegativos, contaremosdesde el últimohasta el primer caracter. Ejemplo: fruit [-1] últimocaracter, fruit[-2] penúltimocaracter, etc.<br />
  39. 39. Traversal & for Loops<br />“Traversal” son los recorridosque se hacen a los caracteres de un “string” desde el primerohasta el último, realizando los cambiosnecesarios a cadauno de los caracteres en eseproceso.<br />Este procesoes tan común en Python, queexisteunaalternativapredefinidallamada “for loop”.<br />
  40. 40. Ejemplo de un “for”:<br /> for char in fruit:<br /> print char<br />Cadavezque se ejecuta el lazo (loop), el próximocaracterdisponible en el “string” esasignado a la variable “char”. El “loop” continúahastaque no hayamasningúncaracter en el “string”.<br />
  41. 41. String Slices<br />Un segmento de un “string ” se conocecomo un “slice”. Seleccionar un “slice” es similar a seleccionar un caracter.<br />El operador [n:m] nosdevuelve la parte del “string” desde la posición n hasta la posición m.<br />
  42. 42. String Slices<br />Ejemplo:<br />Si se omite el primer índice, (anterior a la comilla), el “slice” comenzaría al principio del “string”.<br />>>> fruit = “banana”<br />>>> fruit [:3]<br />‘ban’<br />>>> fruit [3:]<br />‘ana’<br />
  43. 43. Comparación de Strings<br />Se puedencomparar “strings”. Para hacerlo, veamos el siguienteejemplo:<br /> if word == “banana”<br /> print “Yes, we have bananas!”<br />Se puedenhacercomparacionesparaponerpalabras en ordenalfabético, perodebemostener mucho cuidadoyaque Python no ve la diferencia entre letrasmayúsculas y letrasminúsculas. Las letrasmayúsculastomanprioridad ante lasletrasminúsculas.<br />
  44. 44. Immutable Strings <br />Los “strings” no se puedenmodificarluego de ser creados.<br />Si necesitahacercambios, lo mejorescrear un nuevo “string” con lasvariaciones del original.<br />
  45. 45. Función “find”<br />Es lo contrario del operador [].<br />En vez de tomar un índice (index) y extraersucorrespondientecaracter, lo quehaceestomar el caracter y encuentra el índicedondeapareceesecaracter. Si el caracter no aparece, la funciónnosdevuelve un -1. <br />
  46. 46. Conteos (Counter)<br />El siguienteprogramarealiza un conteodentro de un lazo (loop):<br /> Al declararseuna variable llamada “count”, ésta se inicializa a 0 y se vaincrementandocadavezque se encuentra un ‘a’.<br />
  47. 47. Módulo “String”<br />Móduloquecontienevariasfuncionesútilesparamanipular “strings”.<br />>>> import string<br />Incluyeunafunciónllamada “find” quehace lo mismoquevimosanteriormente.<br />
  48. 48. Clasificación de Caracteres<br />Es muyútilexaminar un caracter y comprobarsies de letramayúscula o minúscula, o sies un caracter o un dígito.<br />El “string” ‘string.lowercase’ contienetodaslasletrasque el sistemapodríaconsiderarletrasminúsculas.<br />El “string” ‘string.uppercase’ contienetodaslasletrasque el sistemapodríaconsiderarletrasmayúsculas.<br />
  49. 49. Clasificación de Caracteres<br />El “string” ‘string.whitespace’ contienetodos los espacios en blanco, incluyendo ‘space’, ‘tab’ ( ) y ‘newline’ ( ).<br />
  50. 50. Capítulo 8: Listas<br />
  51. 51. Listas <br />Una lista es un conjunto de valores, donde cada valor es identificado por un índice. <br />Los valores que componen una lista son llamados elementos. <br />Las listas son similares a los “strings”,que son una cadena de caracteres, a excepción de que los elementos de una lista pueden ser de cualquier tipo. <br /> Las listas y las cadenas de caracteres son llamados secuencias.<br />
  52. 52. 8.1 Listas de valores<br />Hay varias maneras de formar una nueva lista; la forma más simple es encasillar los elementos en unos corchetes ([y]).<br />Ejemplos:<br />Lista de cuatro enteros [10, 20, 30, 40]<br />Listas de “strings” [“un”, “dos”, ”tres”]<br />Lista dentro de otra lista [“hola”, 2.0, 5, [10,20] ]<br />Si una lista esta dentro de otra entonces se dice que la lista esta anidada.<br />
  53. 53. Las listas que contienen enteros consecutivos son comunes, por lo que Phyton provee una forma simple para crearlas:<br /> >>> range (1,5)<br /> [1, 2, 3, 4]<br />La función rango toma dos argumentos y devuelve una lista que contiene todos los enteros desde el primero hasta el segundo, sin incluir el segundo.<br />
  54. 54. Hay dos formas del alcance.<br />Argumento simple: se crea una lista que comienza en 0.<br />>>> range(10)<br /> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9<br />Si existe un tercer argumento, este específica el espacio entre los valores sucesivos, lo que es llamado “stepsize”.<br />Ejemplo: Cuenta desde 1 al 10 de 2 en 2.<br />>>>range(1, 10, 2)<br />[1, 3, 5, 7, 9]<br />
  55. 55. Una lista vacía es una lista especial que no contienen elementos.<br />Este tipo de lista se denota por corchetes [].<br />Podemos usar todas las formas anteriores de listas para asignar valores a variables.<br />
  56. 56. 8.2 Acceso de elementos<br />La sintaxis para accesar elementos de una lista es igual a la sintaxis utilizada para accesar caracteres de un “string”.<br />Para esto utilizamos los corchetes [], donde la expresión dentro de los mismos especifica el índice.<br />Recordemos que los índices comienzan en 0.<br />printnumbers[0]<br />numbers[1] = 5<br />
  57. 57. Los corchetes pueden apareces en cualquier lugar de una expresión.<br />Cuando estos aparecen en el lado izquierdo de lo asignado, cambia uno de los elementos de la lista, por lo que el enésimo elemento de la lista ”numbers”, que era 123, es ahora 5.<br />Cualquier expresión con un número entero puede se utilizada como índice.<br />>>> numbers[3-2]<br /> 5<br />>>>numbers[1.0]<br />TypeError: sequence index must be integer<br />
  58. 58. Sin embargo, si intentamos leer o escribir un elemento que no existe, entonces obtenemos un error al correr el programa.<br />>>> numbers[2] = 5<br />IndexError: list assignment index out of range<br />Si un índice tiene un valor negativo, este cuenta desde el final de la lista<br />>>> numbers[-1]<br /> 5<br />>>> numbers[-3]<br />IndexError: list index out of range<br />
  59. 59. En el ejemplo anterior:<br />numbers[-1] es el último elemento de la lista<br />numbers[-2] es el penúltimo elemento de la lista<br />numbers[-3] no existe en la lista<br />Es muy común usar un “loop” como el índice de una lista.<br />Ejemplo:<br />horsemen = ["war", "famine", "pestilence", "death"]<br /> i = 0<br />while i < 4:<br />printhorsemen[i]<br /> i = i + 1<br />
  60. 60. Este “whileloop” cuenta desde 0 a 4.<br />Cuando el “loop” de la variable i es 4, la condición falla y el “loop” termina.<br />Por lo tanto, el cuerpo del “loop” se ejecuta cuando i es 0, 1, 2 y 3.<br />Cada vez que pasamos por el “loop”, la variable i es utilizada como un índice en la lista, y se imprime el elemento i de la lista en ese momento. (lista de recorrido)<br />
  61. 61. 8.3 Largo de la lista<br />La función “len” devuelve el largo de la lista.<br />Es buena idea utilizar este valor como el límite superior de un “loop” en lugar de una constante.<br />En ese caso, si el tamaño de la lista cambia, no tenemos que ir a través del programa cambiando todos los “loops”, pues estos trabajarán correctamente con una lista de cualquier tamaño.<br />
  62. 62. Ejemplo:<br /> horsemen = ["war", "famine", "pestilence", "death"]<br />i = 0<br />whilei < len(horsemen):<br />printhorsemen[i]<br /> i = i + 1<br />La última vez que el “loop” fue ejecutado, i es len(horsemen)-1, que es el índice del último elemento.<br />
  63. 63. Cuando i es igual a len(horsemen), la condición falla y el cuerpo del programa no es ejecutado, lo cual es bueno, porque este valor no es un índice legal.<br />A pesar de que una lista puede contener otra, la lista anidada cuenta solo como un elemento.<br />[’spam!’, 1, [’Brie’, ’Roquefort’, ’Pol le Veq’], [1, 2, 3]]<br />En este ejemplo el largo de la lista es 4.<br />
  64. 64. 8.4 Membrecía de una lista<br />“in” es un operador “booleano” que prueba la membrecía en una lista.<br />Además de ser utilizado con “strings”, también se usan con listas y otras secuencias.<br />Podemos usar “not” en combinación con “in” para probar si un elemento no es miembro de la lista.<br />El “forloop” también puede ser utilizado con listas.<br />
  65. 65. 8.5 Listas y “forloops”<br />La sintaxis general de un “forloop” es:<br />forVARIABLE in LIST:<br /> BODY<br />Este enunciado es equivalente a :<br /> i = 0<br />while i < len(LIST):<br /> VARIABLE = LIST[i]<br /> BODY<br /> i = i + 1<br />El “forloop” es más conciso porque podemos eliminar el “loop” de la variable i. <br />
  66. 66. 8.6 Operaciones con listas<br />Operador +<br /> >>> a = [1, 2, 3]<br /> >>> b = [4, 5, 6]<br /> >>> c = a + b<br /> >>> print c<br /> [1, 2, 3, 4, 5, 6]<br />Operador *<br />Repite una lista el número dado de veces<br /> >>> [1, 2, 3] * 3<br /> [1, 2, 3, 1, 2, 3, 1, 2, 3]<br />
  67. 67. 8.7 Partes de una lista<br />Las operaciones de particiones también trabajan con listas.<br /> >>> list = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]<br /> >>> list[1:3]<br /> [’b’, ’c’]<br /> >>> list[:4]<br /> [’a’, ’b’, ’c’, ’d’]<br /> >>> list[3:]<br /> [’d’, ’e’, ’f’]<br />
  68. 68. Si omitimos el primer índice, la partición comienza desde el principio.<br />Si omitimos el segundo, la partición va al final.<br />Si omitimos ambas, la partición es realmente una copia de la lista completa.<br /> >>> list[:]<br /> [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]<br />
  69. 69. 8.8 Las listas son mutables<br />A diferencia de los “strings”, las listas son mutables, lo que quiere decir que podemos cambiar sus elementos.<br />Usando corchetes al lado izquierdo de la asignación, podemos actualizar uno de los elementos.<br />
  70. 70. Con el operador de partición podemos actualizar varios elementos a la vez.<br /> >>> list = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]<br /> >>> list[1:3] = [’x’, ’y’]<br /> >>> printlist<br /> [’a’, ’x’, ’y’, ’d’, ’e’, ’f’]<br />También podemos remover elementos de una lista asignándoles una lista vacía.<br /> >>> list = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]<br /> >>> list[1:3] = []<br /> >>> printlist<br /> [’a’, ’d’, ’e’, ’f’]<br />
  71. 71. Podemos añadir elementos a una lista moviéndolos a una partición vacía.<br /> >>> list = [’a’, ’d’, ’f’]<br /> >>> list[1:1] = [’b’, ’c’]<br /> >>> printlist<br /> [’a’, ’b’, ’c’, ’d’, ’f’]<br /> >>> list[4:4] = [’e’]<br /> >>> printlist<br /> [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]<br />
  72. 72. Eliminación de una lista<br />Usando particiones para eliminar elementos de una lista puede ser difícil, por lo que entonces estamos propensos a errores.<br />“del” remueve un elemento de una lista.<br />Ejemplo:<br /> >>> a = [’one’, ’two’, ’three’]<br /> >>> del a[1]<br /> >>> a<br /> [’one’, ’three’]<br />
  73. 73. Como esperamos “del” maneja índices negativos y causa un error en la corrida si el índice esta fuera del alcance.<br />Podemos usar una partición como un índice para “del”.<br /> >>> list = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]<br /> >>> del list[1:5]<br /> >>> printlist<br /> [’a’, ’f’]<br />
  74. 74. 8.10 Valores y objetos<br />Si ejecutamos las siguientes asignaciones:<br /> a = "banana"<br /> b = "banana“<br />sabemos que a y b se refieren a un “string” con letras “banana”. <br />Sin embargo, no podemos decir que ambos apuntan al mismo “string”.<br />
  75. 75. Hay dos estados posibles:<br />En el primer caso, a y b se refieren a dos cosas diferentes que tienen el mismo valor.<br />En el segundo caso, ambos se refieren a la misma cosa.<br />
  76. 76. Estas “cosas” tienen nombre y se conocen como objetos.<br />Un objeto es algo a lo que una variable se puede referir.<br />Cada objeto tiene un identificador único, el que puede ser obtenido con la función “id”.<br />
  77. 77. Imprimiendo el identificador de a y b, podemos decir que ambos se refieren al mismo objeto.<br /> >>> id(a)<br /> 135044008<br /> >>> id(b)<br /> 135044008<br />De hecho, obtenemos el mismo identificador doble, lo que significa que Phyton solo ha creado un “string”, y a y b se refieren a el.<br />
  78. 78. Las listas se comportan diferente.<br />Cuando creamos dos listas, tenemos dos objetos:<br /> >>> a = [1, 2, 3]<br /> >>> b = [1, 2, 3]<br /> >>> id(a)<br /> 135045528<br /> >>> id(b)<br /> 135041704<br />Entonces el diagrama de estado es el siguiente:<br /> donde a y b tienen el mismo valor pero no se refieren al mismo objeto.<br />
  79. 79. 8.11 Alias<br />Dado que las variables se refieren a objetos, si asignamos una variable a otra, ambas variables se refieren al mismo objeto.<br /> >>> a = [1, 2, 3]<br /> >>> b = a<br />En este caso, el diagrama de estado es:<br />Como la misma lista tiene dos nombres diferentes, a y b, decimos que esta es un alias.<br />
  80. 80. Cambios hechos a un alias afectan al otro.<br />A pesar de que este comportamiento puede ser beneficioso, en algunos casos puede ser inesperado o indeseable.<br />En general, es más seguro evitar los alias cuando estamos trabajando con objetos mutables.<br />Claro que para elementos inmutables, no hay problema porque Phyton es libre de “strings” alias, cuando se presenta la oportunidad de economizar.<br />
  81. 81. 8.12 Clonando listas<br />Si deseamos modificar una lista y a la vez guardar una copia de la lista original, necesitamos ser capaces de crear una copia de la lista misma, no solo una referencia.<br />A veces este proceso se conoce como clonación, para evitar la ambigüedad del término copia. <br />La manera más fácil de clonar una lista es usar el operador de partición.<br /> >>> a = [1, 2, 3]<br /> >>> b = a[:]<br /> >>> print b<br /> [1, 2, 3]<br />
  82. 82. Tomando cualquier partición de a se crea una nueva lista, que en este caso consiste de la lista completa.<br />Ahora podemos realizar cualquier cambio a b sin la preocupación de modificar a.<br /> >>> b[0] = 5<br /> >>> print a<br /> [1, 2, 3]<br />
  83. 83. 8.13 Parámetros de listas<br />Pasar una lista como un argumento pasa una referencia a la lista, no una copia de la lista.<br />Por ejemplo, la función “head” toma una lista como un argumento y devuelve el primer elemento.<br />defhead(list):<br />returnlist[0]<br />Se utiliza la siguiente forma:<br /> >>> numbers = [1, 2, 3]<br /> >>> head(numbers)<br /> 1<br />
  84. 84. El parámetro “list” y la variable “numbers” son alias para el mismo objeto.<br />El diagrama de estado es:<br />Como el objeto de la lista es compartido por dos marcos, entonces lo dibujamos entre ambos.<br />Si una función modifica el parámetro de una lista, entonces se elimina el cambio.<br />
  85. 85. Por ejemplo, “deleteHead” remueve el primer elemento de una lista.<br />defdeleteHead(list):<br /> del list[0]<br />Entonces mostramos como se utiliza el comando “deleteHead”.<br /> >>> numbers = [1, 2, 3]<br /> >>> deleteHead(numbers)<br /> >>> printnumbers<br /> [2, 3]<br />
  86. 86. Si una función devuelve una lista, esta devuelve una referencia a la lista.<br />Por ejemplo, “tail” devuelve una lista que contiene todo menos el primer elemento de la lista.<br />deftail(list):<br />returnlist[1:]<br />
  87. 87. “tail” funciona de la siguiente forma:<br /> >>> numbers = [1, 2, 3]<br /> >>> rest = tail(numbers)<br /> >>> printrest<br /> [2, 3]<br />Como el valor devuelto fue creado por el operador de particiones, es una lista nueva. Por lo que haber creado “rest” no tiene ningún efecto en “numbers”.<br />
  88. 88. 8.14 Listas anidadas<br />Una lista anidada es una lista que aparece como un elemento de otra lista.<br />En esta lista, el tercer elemento es una lista anidada:<br /> >>> list = ["hello", 2.0, 5, [10, 20]]<br />Si imprimimos “list[3]”, obtenemos “[10, 20]”.<br />
  89. 89. 8.15 Matrices<br />Las listas anidadas también son utilizadas para representar matrices.<br />Por ejemplo, la matriz puede ser <br /> representada como:<br /> >>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]<br />“matrix” es una lista con tres elementos, donde cada elemento es una fila de la matriz.<br />
  90. 90. Podemos seleccionar una fila entera de una matriz de la siguiente forma:<br />>>> matrix[1]<br /> [4, 5, 6]<br />Podemos extraer un solo elemento de la matriz usando un doble índice:<br /> >>> matrix[1][1]<br /> 5<br />El primer índice selecciona una fila, el segundo índice selecciona una columna.<br />
  91. 91. 8.16 Listas y “strings”<br />Dos de las funciones más utilizadas en el módulo “string” envuelve listas de “strings”.<br />La función “split” rompe un “string” como una lista de palabras.<br />Cada espacio en blanco entre los caracteres es considerado el límite de una palabra.<br />>>> importstring<br /> >>> song = "The rain in Spain..."<br /> >>> string.split(song)<br /> [’The’, ’rain’, ’in’, ’Spain...’]<br />
  92. 92. Existe un argumento opcional llamado delimitador, el cual puede ser usado para especificar cuales caracteres son utilizados como límites de las palabras.<br />El siguiente ejemplo usa el “string” ai como el delimitador<br /> >>> string.split(song, ’ai’)<br /> [’The r’, ’n in Sp’, ’n...’]<br />Notemos que el delimitador no aparece en la lista.<br />
  93. 93. Esta toma una lista de “strings” y une los elementos con un espacio entre cada par.<br /> >>> list = [’The’, ’rain’, ’in’, ’Spain...’]<br /> >>> string.join(list)<br /> ’The rain in Spain...’<br />Como “split”, “join” toma un delimitador opcional que es insertado entre los elementos.<br /> >>> string.join(list, ’_’)<br /> ’The_rain_in_Spain...’<br />
  94. 94. Capítulo 9: Tuplas<br />
  95. 95. 9.1 Mutabilidad y tuplas<br />Un “string” está compuesto de caracteres; mientras una lista está compuesta de elementos de cualquier tipo.<br />Una de las diferencias más notables es que los elementos de una lista pueden ser modificados, pero los caracteres de un “string” no.<br />En otras palabras, los “strings” son inmutables y las listas mutables.<br />
  96. 96. En Phyton también existen las tuplas, la cual es similar a una lista con la excepción de que es inmutable.<br />Sintácticamente, una tupla es una lista de valores separados por comas.<br />Ejemplo:<br />>>> tuple = ’a’, ’b’, ’c’, ’d’, ’e’<br />
  97. 97. Aunque no es necesario, convencionalmente las tuplas se escriben entre paréntesis.<br /> >>> tuple = (’a’, ’b’, ’c’, ’d’, ’e’)<br />Para crear un tupla con un solo elemento, tenemos que incluir una coma al final.<br />>>> t1 = (’a’,)<br /> >>> type(t1)<br /> <type ’tuple’><br />
  98. 98. Sin la coma, Phyton trata (‘a’) como un “string” entre paréntesis.<br />>>> t2 = (’a’)<br /> >>> type(t2)<br /> <type ’str’><br />Si dejamos la sintaxis a un lado, las operaciones en las tuplas son igual a las operaciones en las listas.<br />
  99. 99. El operador índice selecciona un elemento de una tupla.<br /> >>> tuple = (’a’, ’b’, ’c’, ’d’, ’e’)<br /> >>> tuple[0]<br /> ’a’<br />El operador partición selecciona el alcance de los elementos.<br /> >>> tuple[1:3]<br /> (’b’, ’c’)<br />
  100. 100. Si intentamos modificar uno de los elementos de la tupla obtenemos un error.<br /> >>> tuple[0] = ’A’<br />TypeError: object doesn’t support item assignment<br />Como no podemos modificar los elementos de una tupla, podemos reemplazarlo con una diferente.<br /> >>> tuple = (’A’,) + tuple[1:]<br /> >>> tuple<br /> (’A’, ’b’, ’c’, ’d’, ’e’)<br />
  101. 101. 9.2 Asignando tuplas<br />A veces es bueno cambiar los valores de dos variables.<br />Con la forma convencional de asignación, teníamos que utilizar una variable temporera.<br />Ejemplo para cambiar a y b:<br />>>> temp = a<br /> >>> a = b<br /> >>> b = temp<br />
  102. 102. Si tenemos que hacer esto a menudo, este proceso sería engorroso.<br />Phyton provee una forma de asignación de tuplas que resuelve este problema:<br /> >>> a, b = b, a <br />El lado izquierdo es la tupla de las variables y el lado derecho es el de los valores.<br />Cada valor es asignado a su variable correspondiente.<br />
  103. 103. Todas las expresiones en el lado derecho son evaluadas antes de cualquier asignación.<br />Esto hace que la asignación de tuplas sea versátil.<br />El número de variables en el lado izquierdo y el número de variables en el derecho tienen que ser iguales.<br />Ejemplo:<br />>>> a, b, c, d = 1, 2, 3<br />ValueError: unpack tuple of wrong size<br />
  104. 104. 9.3 Tuplas como valores devueltos<br />Las funciones pueden devolver tuplas como respuestas.<br />Por ejemplo, podemos escribir una función que cambia dos parámetros:<br />def swap(x, y):<br />return y, x<br />Después podemos asignar el valor devuelto a una tupla con dos variables:<br />a, b = swap(a, b)<br />
  105. 105. En este caso, no es ventajoso realizar una función “swap”.<br />De hecho, existe un peligro en intentar encapsular “swap”, el cual es el siguiente error:<br />def swap(x, y): # incorrectversion<br /> x, y = y, x<br />Si llamamos la función de la siguiente manera:<br />swap(a, b)<br /> entonces a y x son alias para el mismo valor.<br />
  106. 106. Cambiando x dentro de “swap” hace que x se refiera a un valor diferente, pero no tiene efecto en “in_main_”.<br />Similarmente, cambiar y no tiene ningún efecto en b.<br />Esta función corre sin producir un mensaje de error, pero no realiza lo que se pretende.<br />Este es un buen ejemplo para un error de semántica.<br />
  107. 107. 9.4 Números aleatorios<br />Muchos programas de computadoras hacen lo mismo cada vez que son ejecutados, por lo que podemos llamarlos determinísticos.<br />El determinismo es usualmente bueno, porque esperamos que el mismo cálculo arroje el mismo resultado.<br />Para algunas aplicaciones, queremos que la computadora sea impredecible.<br />Ejemplo: Juegos<br />
  108. 108. Hacer un programa no determinístico no es sencillo, pero existen formas para que lo sea lo menos posible.<br />Una de las formas es generando números aleatorios y utilizarlos para determinas la salida del programa.<br />Phyton provee una función pre-construida que genera números seudo-aleatorios, los cuales no son completamente aleatorios en sentido matemático, pero para nuestros propósitos si lo son.<br />
  109. 109. El módulo “random” contiene una función llamada “random” que devuelve un número decimal entre 0.0 y 1.0.<br />Cada vez que realizamos la operación, obtenemos el siguiente número en una serie larga.<br />Ejemplo:<br />importrandom<br />for i in range(10):<br /> x = random.random()<br />print x<br />
  110. 110. 9.2 Lista de números aleatorios<br />El primer paso es generar una lista de valores aleatorios.<br />“randomList” toma un argumento entero y devuelve una lista de números aleatorios con el largo dado.<br />Se comienza con una lista de n ceros.<br />Cada vez que pasamos a través del “loop”, este reemplaza uno de los elementos con un número aleatorio.<br />
  111. 111. El valor devuelto es una referencia a la lista completa.<br />def randomList(n):<br /> s = [0] * n<br /> for i in range(n):<br /> s[i] = random.random()<br /> return s<br />Los números generados por “random” son distribuidos uniformemente, lo que significa que cada valor es igualmente probable.<br />
  112. 112. Si dividimos el alcance de los valores posibles en “buckets” del mismo tamaño, y contamos el número de veces que el valor aleatorio cae en cada “bucket”, tendremos seguramente el mismo número en cada uno.<br />Podemos probar esta teoría escribiendo un programa que divida el alcance en “buckets” y cuente el número de valores en cada uno.<br />
  113. 113. 9.6 Contando<br />Una buena propuesta para problemas como este es dividir el problema en partes y buscar soluciones computacionales a estos problemas.<br />En este caso, deseamos recorrer una lista de números y contar el número de veces que un valor cae en el rango dado.<br />Podemos proceder copiando el programa y adaptándolo para el problema actual.<br />
  114. 114. El programa original es:count = 0<br />forchar in fruit:<br />ifchar == ’a’:<br />count = count + 1<br />printcount<br />Este primer paso es para reemplazar “fruit” with “t” y “char” con “num”.<br />Esto no cambia el programa, solo lo hace más fácil para leer.<br />
  115. 115. El segundo paso es cambiar la prueba.<br />No tenemos la intención de encontrar valores, deseamos saber si “num” esta entre los valores “low” y “high”.<br />Ejemplo:<br />count = 0<br />forchar in fruit:<br />ifchar == ’a’:<br />count = count + 1<br />printcount<br />
  116. 116. El último paso es encapsular este código en la función “inBucket”.<br />Los parámetros son la lista y los valores “low” y “high”.<br />definBucket(t, low, high):<br />count = 0<br />fornum in t:<br />iflow < num < high:<br />count = count + 1<br />returncount<br />
  117. 117. Copiando y modificando un programa existente, somos capaces de escribir esta función rápidamente y economizar tiempo.<br />Este plan de desarrollo se conoce como pareo de patrones.<br />Si trabajamos en un problema que hemos resuelto anteriormente, reusamos la solución.<br />
  118. 118. 9.7 Muchos “buckets”<br />Si el número de “buckets” aumenta, la función “inBucket” se vuelve un poco difícil. <br />Con dos “buckets”:<br />low = inBucket(a, 0.0, 0.5)<br />high = inBucket(a, 0.5, 1)<br />Con cuatro “buckets” se vuelve engorroso:<br />bucket1 = inBucket(a, 0.0, 0.25)<br /> bucket2 = inBucket(a, 0.25, 0.5)<br /> bucket3 = inBucket(a, 0.5, 0.75)<br /> bucket4 = inBucket(a, 0.75, 1.0)<br />
  119. 119. Existen dos problemas.<br />Tenemos que declarar un nombre nuevo para cada resultado de la variable.<br />Tenemos que calcular el rango para cada “bucket”.<br />Podemos resolver el segundo problema primero.<br />Si el número de “buckets” es “numBuckets”, entonces el ancho de cada “bucket” es “1.0/numBuckets”.<br />Usamos un “loop” para calcular el rango de cada “bucket”.<br />
  120. 120. La variable “loop”, i, cuenta desde 0 a “numBuckets-1”<br />bucketWidth = 1.0 / numBuckets<br />for i in range(numBuckets):<br />low = i * bucketWidth<br />high = low + bucketWidth<br />printlow, "to", high<br />Para calcular el limite inferior para cada “bucket”, multiplicamos la variable “loop” por el ancho del “bucket”.<br />
  121. 121. El limite superior es la suma del inferior y el “bucketWidth”.<br />Ejemplo:Con“numBuckets=8”, el “output” es:<br />0.0 to 0.125<br /> 0.125 to 0.25<br /> 0.25 to 0.375<br /> 0.375 to 0.5<br /> 0.5 to 0.625<br /> 0.625 to 0.75<br /> 0.75 to 0.875<br /> 0.875 to 1.0<br />
  122. 122. Podemos confirmar que cada “bucket” tiene el mismo ancho, que no se solapan, y que cubren completamente el alcance desde 0.0 a 1.0.<br />Para el primer problema, necesitamos una forma para guardar ocho enteros, usando la variable “loop” para indicar uno a la vez.<br />Tenemos que crear una lista “bucket” fuera del “loop”, porque solo queremos recorrerla una vez<br />
  123. 123. Dentro del “loop”, llamaremos el “inBucket” repetidamente y actualizaremos el enésimo elemento i de la lista.<br />Ejemplo:<br />numBuckets = 8<br />buckets = [0] * numBuckets<br />bucketWidth = 1.0 / numBuckets<br />for i in range(numBuckets):<br />low = i * bucketWidth<br />high = low + bucketWidth<br />buckets[i] = inBucket(t, low, high)<br />printbuckets<br />
  124. 124. Con una lista de 1000 valores, el código produce la siguiente lista “bucket”:<br /> [138, 124, 128, 118, 130, 117, 114, 131]<br />Estos números están bien cerca de 125, que es lo que esperamos. <br />Al estar tan cerca podemos creer que el generador de números aleatorios está funcionando.<br />
  125. 125. 9.8 Solución por una prueba<br />A pesar de que el programa funciona, no es tan eficiente como podría ser.<br />Cada vez que se llama el “inBucket”, se recorre la lista completa.<br />Si el numero de “buckets” aumenta, también el número de recorridas.<br />Sería mejor si pasamos una sola vez por la lista y computamos el índice del “bucket” en el cual falla para cada valor.<br />
  126. 126. Luego podemos aumentar el contador apropiado.<br />Deseamos tomar un valor en el rango de 0.0 a 1.0 para calcular el índice del “bucket” en el cual se falla.<br />Dado que el problema es el inverso del problema anterior, podemos pensar que debemos dividir por el “bucketWidth” en vez de multiplicar, como en el ejemplo anterior.<br />Dado que “bucketWidth”=“1.0/numBuckets”, dividiendo por “bucketWidth” es lo mismo que multiplicar por “numBuckets”.<br />
  127. 127. Si multiplicamos un número en el rango 0.0 a 1.0 por “numBuckets”, obtenemos un número en el rango desde 0.0 hasta “numBuckets”.<br />Si redondeamos ese número al entero menor, obtenemos exactamente lo que estamos buscando, un índice del “bucket”.<br />numBuckets = 8<br />buckets = [0] * numBuckets<br />for i in t:<br />index = int(i * numBuckets)<br />buckets[index] = buckets[index] + 1<br />
  128. 128. Usamos le función “int” para convertir un número decimal en un entero.<br />Una lista que cuenta el número de valores en cada rango se conoce como un histograma, el cual se realiza con la función “histogram”.<br />

×