¿Qué significa cuando Python informa el siguiente error?
Por último, hablaremos de los problemas que puedes encontrar al utilizar más funciones de Python (tipos de datos, funciones, módulos, clases, etc.). ). Debido al espacio limitado, intentamos ser concisos y directos, especialmente para algunos conceptos avanzados. Para obtener más detalles, lea los capítulos "Consejos" y "Gotcha" en Learning Python, segunda edición.
La llamada para abrir un archivo no utiliza la ruta de búsqueda del módulo.
Cuando llamas a open() en Python para acceder a un archivo externo, Python no utiliza la ruta de búsqueda del módulo para localizar el archivo de destino. Utilizará la ruta absoluta que usted proporcione o asumirá que el archivo está en el directorio de trabajo actual. La ruta de búsqueda del módulo se utiliza sólo para cargar el módulo.
Los diferentes tipos tienen diferentes métodos.
Los métodos de lista no se pueden utilizar en cadenas y viceversa. Normalmente, las invocaciones de métodos son relativas al tipo de datos, pero las funciones intrínsecas generalmente se pueden usar en muchos tipos. Por ejemplo, el método inverso de lista solo es útil para listas, pero la función len funciona para cualquier objeto con longitud.
Los tipos de datos inmutables no se pueden cambiar directamente.
Recuerda que no puedes cambiar directamente objetos inmutables (por ejemplo, tuplas, cadenas):
t = (1, 2, 3)
t【2】= 4 #Error
Construir nuevos objetos cortándolos, uniéndolos, etc. y asígnele el valor de la variable original según sea necesario. Debido a que Python recupera automáticamente memoria inútil, no es un desperdicio como parece:
T = T[:2]+(4,)#No hay problema: T se convierte en (1, 2, 4).
Utiliza un bucle for simple en lugar de while o range.
Cuando desea iterar sobre todos los elementos de un objeto ordenado de izquierda a derecha, usar un bucle for simple (por ejemplo, for x en seq:) es más fácil de escribir y generalmente es mejor que while- o basado en rango: el ciclo de conteo se ejecuta más rápido. Intente evitar el uso de rangos en bucles for a menos que sea absolutamente necesario: deje que Python se encargue del etiquetado por usted. En el siguiente ejemplo, las tres construcciones de bucle están bien, pero la primera suele ser mejor en Python, la simplicidad es primordial;
S="Lumberjack"
Para c en S: imprimir c# es más fácil
Para I (disparo) dentro del rango: imprimir Hay demasiadas s【 I】#.
I = 0 #demasiados
Cuando i<len(S):print S[I] += 1
No intentes cambiar de Obtenga el resultado de la función del objeto.
Las operaciones de cambio directo como los métodos list.append() y list.sort() cambiarán un objeto, pero no devolverán el objeto que cambiaron (no devolverán ninguno); llámalo directamente sin asignar un valor al resultado. A menudo se ve que los principiantes pueden escribir código como este:
mi lista = mi lista append(X)
El propósito es obtener el resultado de agregar, pero en realidad es este. pondrá Ninguno en su lugar. No, la lista modificada se asigna a mylist. Un ejemplo más específico es la iteración sobre los elementos de un diccionario utilizando valores clave ordenados. Vea el siguiente ejemplo:
D = {...}
Para k() en D.keys. sort(): print D[k]
Casi exitoso: el método de claves creará una lista de claves y luego ordenará la lista con el método de clasificación, pero debido a que el método de clasificación devolverá Ninguno, el bucle falla porque en realidad iterará sobre Ninguno (que no es una secuencia). Para corregir este código, separe las llamadas a métodos y colóquelas en declaraciones diferentes, de la siguiente manera:
Ks = D.keys()
Ks.sort()
Para k en Ks: print D[k]
La conversión de tipos solo existe en tipos numéricos.
En Python, una expresión como 123+3.145 funciona: convierte automáticamente el número entero a un tipo de punto flotante y luego usa aritmética de punto flotante. Pero el siguiente código generará un error:
s="42"
I = 1
X = S+I #Tipo de error.
Esto también es intencional porque no está claro: ¿está convirtiendo cadenas en números (suma) o números en cadenas (concatenación)? En Python creemos que "claro es mejor que vago" (es decir, eibti (explícito es mejor que implícito)), por lo que puedes convertir el tipo manualmente:
x = int(S)+I # Add:43
x = S+str(I)# Unión de cadenas: "421"
Las estructuras de datos en bucle provocarán bucles.
Aunque esto es poco común en la práctica, si una colección de objetos contiene una referencia a sí misma, se dice que es un objeto cíclico. Si se encuentra un bucle en el objeto, Python generará […] para evitar caer en un bucle infinito:
& gt& gt& gtL = [‘grial‘] #En L, se hace referencia a L mismo nuevamente.
& gt& gt& gtCrea un bucle en el objeto.
& gt& gt& gtL
["Santo Grial", [...]]
Además de saber que estos tres puntos representan períodos en el objeto También vale la pena aprender de este ejemplo. Debido a que sin darte cuenta puedes tener estructuras de bucle como esta en tu código, tu código saldrá mal. Si es necesario, mantenga una lista o diccionario que represente los objetos que se han visitado y luego verifíquelo para ver si se ha encontrado un ciclo.
La declaración de asignación no crea una copia del objeto, solo una referencia.
Esta es una idea central de Python y, cuando se comporta incorrectamente, a veces genera errores. En el siguiente ejemplo, se asigna un objeto de lista a una variable denominada l, a la que luego se hace referencia en la lista m. Si l se cambia internamente, también cambiará el objeto al que hace referencia m, ya que ambos apuntan al mismo objeto.
& gt& gt& gtL =【1, 2, 3】# * * * listar objeto
& gt& gt& gtm =【'X', L, 'Y'】# Incrustar referencia a L
& gt& gt& gtM
['X', [1, 2, 3], 'Y']
& gt& gt& gtl[ 1]=0 #m también cambia.
& gt& gt& gtM
['X', [1, 0, 3], 'Y']
Por lo general, esto sólo es cierto para más grande Muy importante en el programa, estas * * * citas suelen ser lo que necesitas. Si no, puedes crear explícitamente una copia de ellos para evitar * * el uso de referencias para listas, puedes crear una copia de nivel superior usando parte de una lista vacía:
& gt& gt& gtl =; 【 1, 2, 3]
& gt& gt& gtm =['X', L[:], 'Y'] #Incrustar una copia de L.
& gt& gt& gtL【1】= 0 #Solo cambia L, no afecta m.
& gt& gt& gtL
[1, 0, 3]
& gt& gt& gtM
['X',[1 , 2, 3], 'Y']
El rango de corte va desde el valor predeterminado 0 hasta la longitud máxima de la secuencia de corte. Si se omiten ambos, la división extraerá todos los elementos de la secuencia y creará una copia de nivel superior (un nuevo objeto que no se comparte). Para diccionarios, utilice el método dict.copy() del diccionario.
Nombre de variable que identifica estáticamente el dominio local.
De forma predeterminada, Python trata los nombres de variables asignados en una función como variables locales. Estas variables existen en el alcance de la función y solo existen mientras la función se está ejecutando. Técnicamente, Python reconoce variables locales estáticamente cuando se compila el código def, no cuando se encuentran asignaciones en tiempo de ejecución. Si no comprende esto, puede causar malentendidos.
Por ejemplo, mire el siguiente ejemplo, qué sucede cuando asigna un valor a una variable después de una referencia:
& gt& gt& gtX = 99
& gt& gt& gtdef func() :
...printX #no existe actualmente.
...X = 88 #Trate x como una variable local en toda la definición.
...
& gt& gt& gtfunc()# ¡Error!
Obtendrá un error de "nombre de variable no definido", pero el motivo es muy sutil. Al compilar este código, Python piensa que en cualquier parte de esta función, al ejecutar una declaración que asigna un valor a La declaración de asignación aún no ha ocurrido, por lo que Python informará un error de "nombre de variable indefinido".
En realidad, lo que el ejemplo anterior intenta hacer es muy vago: ¿quieres generar primero la X global y luego crear la X local, o es esto un error de programación? Si realmente desea exportar esta X global, debe declararla en una declaración global o hacer referencia a ella por el nombre del módulo del sobre.
Parámetros predeterminados y objetos variables
Al ejecutar una instrucción def, el valor del parámetro predeterminado solo se analiza y guarda una vez, en lugar de analizarse y guardarse cada vez que se llama a la función. Generalmente esto es lo que desea, pero debido a que necesita mantener el mismo objeto cada vez que se llama al valor predeterminado, debe tener cuidado al intentar cambiar un valor predeterminado mutable. Por ejemplo, la siguiente función utiliza una lista vacía como valor predeterminado y luego cambia su valor cada vez que se llama a la función:
& gt& gt& gtdef saver(x = []): #Guardar una lista objeto.
...x . append(1) # y cada vez que se llama.
...Imprime x # para cambiar su valor
...
& gt& gt& gtsaver([2]) #No usar el valor predeterminado .
[2, 1]
& gt& gt& gtsaver()#Usar valor predeterminado
[1]
& gt& gt& gtsaver () ¡# se incrementará con cada llamada!
[1, 1]
& gt& gt& gtprotector()
[1, 1, 1]
Algunas personas piensan en esto es una característica de Python: debido a que los argumentos variables predeterminados conservan su estado cada vez que se llama a la función, pueden proporcionar funciones similares a las variables de funciones locales estáticas en C. Sin embargo, por extraño que parezca cuando lo encuentra por primera vez, existen formas más fáciles en Python de guardar el estado entre diferentes llamadas (por ejemplo, clases).
Para eliminar este comportamiento, use una porción o método para crear una copia de los parámetros predeterminados al comienzo de la función, o mueva la expresión para el valor predeterminado a la función siempre que los valores; están en la función cada vez que se llama, obtienes un nuevo objeto cada vez:
& gt& gt& gtdef saver(x=None):
...si x es Ninguno:x=[]# Ninguno ¿Pasar parámetros?
...x . append(1) #Cambiar la nueva lista.
...print x
...
& gt& gt& gtsaver([2]) #No utilice el valor predeterminado.
[2, 1]
& gt& gt& gtsaver()# No cambiará esta vez.
[1]
& gt& gt& gtprotector()
[1]
Otras trampas comunes de programación
Aquí hay algunos otros errores que no se pueden detallar aquí:
El orden de las declaraciones en los archivos de nivel superior es especial: debido a que al ejecutar o cargar un archivo se ejecutarán sus declaraciones de arriba a abajo, asegúrese de Colocar ilimitado llamadas a funciones o llamadas a clases después de la definición de función o clase.
La recarga no afecta los nombres cargados con from: la recarga se usa mejor con la declaración import.
Si usa una declaración from, recuerde ejecutar from nuevamente después de recargar; de lo contrario, se seguirá usando el nombre anterior.
El orden de las mezclas en herencia múltiple es especial: esto se debe a que la búsqueda de superclases es de izquierda a derecha. Al principio de una definición de clase, si hay nombres duplicados en múltiples superclases, prevalecerá el nombre de clase más a la izquierda.
Una cláusula except vacía en una declaración try puede detectar más errores de los esperados. Una cláusula except vacía en una declaración try significa que se detectan todos los errores, incluso los errores reales del programa y las llamadas sys.exit().