Más

Secuencias de comandos de Python para clases de entidades (repetir, ordenar, fusionar y reemplazar)

Secuencias de comandos de Python para clases de entidades (repetir, ordenar, fusionar y reemplazar)


Esto es lo que tengo que lograr usando un script de Python para ArcGIS 10.1:

  1. Recorra todas las clases de entidad y primero agregue un campo, luego escriba el nombre de la clase de entidad en el campo agregado.
  2. Fusionar todas las clases de entidad de 1. en una clase de entidad llamada OSRS_ORN_NER.
  3. Ordene esta clase de entidad por HWY_NUM y reemplace OSRS_ORN_NER por la ordenada.

Este es el código que tengo para eso hasta ahora:

Creo que la primera parte del código es correcta, pero no sé si hice bien la segunda parte o si estoy en el camino correcto para la última parte. Además, ¿cómo exactamente ejecutaría una secuencia de comandos de Python en ArcGIS? ¡Cualquier ayuda sería genial!

código:

import arcpy, os arcpy.env.workspace = r'W:  S&P  s & p techs  Emily  TownshipsDissolved  FinalDissolved.gdb '# Recorriendo las clases de entidades disueltas, agregando el campo' Nombre 'y escribiendo # el nombre de la clase de entidad en el campo agregado . para fc en arcpy.ListFeatureClasses (): arcpy.AddField_management (fc, "Name", "TEXT", field_length = 50) con arcpy.da.UpdateCursor (fc, "Name") como cursor: para la fila en el cursor: fila [ 0] = fc cursor.updateRow (fila) # Fusionando las múltiples clases de entidad en una lista OSRS_ORN_NER llamada = [] para r en la fila: list.append (r) arcpy.Merge_management (list, "W:  S&P  s & p techs  Emily  TownshipsDissolved  FinalDissolved.gdb  OSRS_ORN_NER ") # Ordenar por HWY_NUM_PR y reemplazar OSRS_ORN_NER por la clase de entidad ordenada Sort_management (" OSRS_ORN_NER "," OSRS_ORN_NER_new ", [[" HWY_NUM_PRING "," ASC)

Primero debe asignar elListFeatureClasses ()a una variable para poder llamarla más tarde para la fusión

importar arcpy, os arcpy.env.workspace = r'W:  S&P  s & p techs  Emily  TownshipsDissolved  FinalDissolved.gdb 'fcs = arcpy.ListFeatureClasses () para fc en fcs: arcpy.AddField_management (fc, "Nombre", "TEXT", field_length = 50) con arcpy.da.UpdateCursor (fc, "Name") como cursor: para la fila en el cursor: fila [0] = fc cursor.updateRow (fila) mergeOutput = r "W:  S&P  s & p techs  Emily  TownshipsDissolved  FinalDissolved.gdb  OSRS_ORN_NER "sortOutput = r" W:  S&P  s & p techs  Emily  TownshipsDissolved  FinalDissolved.gdb  OSRS_ORN_NER_new "arcpy.Merge_management (fcs), mergecpy , [["HWY_NUM_PR", "ASCENDING"]])

se ve bastante bien, pero debe inicializar su lista antes de hacer un bucle en el fc, y sangrar correctamente agregando los nombres de fc a su lista

para fc en arcpy.ListFeatureClasses (): list.append (fc)… arcpy.Merge_management (lista, nombre de salida) arcpy.Sort_management (nombre de salida, nombre final, [["HWY_NUM_PR", "ASCENDING"]])

¿Cómo puedo saber dónde está colgando mi script de Python?

Así que estoy depurando mi programa de Python y encontré un error que hace que el programa se cuelgue, como en un bucle infinito. Ahora, tuve un problema con un bucle infinito antes, pero cuando colgó, pude matar el programa y Python escupió una excepción útil que me dijo dónde terminaba el programa cuando le envié el comando kill. Ahora, sin embargo, cuando el programa cuelga y presiono ctrl-c, no aborta sino que continúa ejecutándose. ¿Hay alguna herramienta que pueda utilizar para localizar el colgado? Soy nuevo en la creación de perfiles, pero por lo que sé, un generador de perfiles solo puede proporcionarle información sobre un programa que se haya completado con éxito. ¿O puede usar un generador de perfiles para depurar tales problemas?


¿A qué llamamos web scraping?

El web scraping es un proceso automatizado de recopilación de datos públicos. Los web scrapers extraen automáticamente grandes cantidades de datos públicos de los sitios web de destino en segundos.

Este tutorial de raspado web de Python funcionará para todos los sistemas operativos. Habrá ligeras diferencias al instalar Python o entornos de desarrollo, pero no en ninguna otra cosa.

  • Construyendo un raspador web: preparación de Python
  • Llegar a las bibliotecas
  • WebDrivers y navegadores
  • Encontrar un lugar acogedor para nuestro raspador web Python
  • Importar y usar bibliotecas
  • Elegir una URL
  • Definición de objetos y listas de construcción
  • Extrayendo datos con nuestro raspador web Python
  • Exportando los datos
  • Más listas. ¡Más!
  • Web scraping con las mejores prácticas de Python
  • Conclusión

¿Qué secciones de Python debo aprender para ArcGis?

Quiero aprender Python para ArcGis. He comprado & quot; Automatiza las cosas aburridas con Python & quot; Es un libro divertido, ¡pero es grande! ¿En qué secciones / código debería centrarme al aprender Python para ArcGis? Por ejemplo, ¿debería centrarme en el bucle & quot while & quot, etc.? ¡Gracias!

Debería trabajar con todo el libro. No lleva mucho tiempo. Es donde comencé y hacer todo le dará una buena base antes de entrar en Python para GIS.

¿Es este un libro, me recomiendas que lo consiga? He trabajado con R antes, sé cómo hacer algunas acciones básicas de consulta: p y eso es todo.

Sí, en las clases que tomé, literalmente revisamos toda la lista de Toolbox, enfocándonos más en las características de procesamiento oscuras que realmente deberían ejecutarse en Python de todos modos.

También es genial repasar la teoría y los problemas de la programación. No tenía ni idea de los problemas de programación (como depurar todos los diferentes tipos de errores) hasta que tomé un curso de ciencias de la computación.

Muchas de las funciones GIS (como ejecutar herramientas de geoprocesamiento) que necesita con arcpy son bastante específicas de esri, por lo que cuando aprende python no GIS, es principalmente una comprensión básica de la estructura de un script (configuración de variables, sintaxis, importar bibliotecas, etc.) y aprender a repetir cosas, como recorrer una carpeta de archivos.

Romper con arcpy lo antes posible. Existe un enorme mundo de herramientas y opciones.

Creo que "los conceptos básicos" son los capítulos 1-10. Pero seguiría adelante después de eso. Todo el libro es bueno.

Los tipos de datos son importantes y los métodos para verificarlos y resumirlos.

Zip para iterar sobre varios elementos al mismo tiempo

Comprensión de listas especialmente para crear cadenas personalizadas

Entonces descubra cómo la documentación de arcgis es totalmente útil ahora con arcpy

Luego, busque en Google su problema con site: stackexchange.com para obtener ejemplos, explicaciones y notas al margen sobre su problema, y ​​aprenda.

Reutiliza tu código. Guarde una versión antes de realizar cambios importantes.

Una vez que todo va bien, puede mirar los entornos conda o los entornos virtuales para introducir análisis muy interesantes, aprendizaje estadístico, gráficos y bibliotecas de transformación de datos.

Incluyendo el cuaderno jupyter, que permite una fácil prueba de código y auto documentación, incluso para principiantes.

En cualquier momento del camino o después de que tenga tiempo e interés, lea y trabaje un libro lo más que pueda. Recomiendo Learning Python de OReilly Press.


Python es uno de los muchos software de aplicación de programación orientada a objetos de código abierto disponibles en el mercado. Algunos de los muchos usos de Python son desarrollo de aplicaciones, implementación del proceso de prueba de automatización, permite compilación de programación múltiple, biblioteca de programación completamente construida, se puede usar en todos los principales sistemas operativos y plataformas, accesibilidad del sistema de base de datos, código simple y legible, fácil de se aplica en procesos de desarrollo de software complejos, ayuda en el enfoque de desarrollo de aplicaciones de software basado en pruebas, aprendizaje automático / análisis de datos, ayuda en el reconocimiento de patrones, compatible con múltiples herramientas, permitido por muchos de los marcos aprovisionados, etc.

10 usos importantes de Python

Python puede ser más fácil de usar debido a sus ventajas. A continuación, encontrará los usos del lenguaje Python por diferentes razones:

Desarrollo web, lenguajes de programación, pruebas de software y otros

1. Aplicaciones

Python se puede utilizar para desarrollar diferentes aplicaciones como aplicaciones web, aplicaciones basadas en interfaces gráficas de usuario, aplicaciones de desarrollo de software, aplicaciones científicas y numéricas, programación de redes, juegos y aplicaciones 3D y otras aplicaciones comerciales. Hace una interfaz interactiva y fácil desarrollo de aplicaciones.

2. Múltiples paradigmas de programación

También se utiliza porque proporciona soporte continuo a varios paradigmas de programación, ya que admite programación orientada a objetos y programación estructurada. Python tiene características que también admiten varios conceptos de lenguaje de programación funcional. Se utiliza para el sistema de tipo dinámico y la gestión automática de memoria. Las características del lenguaje Python y los paradigmas de programación le permiten desarrollar aplicaciones tanto pequeñas como grandes. Puede utilizarse para aplicaciones de software complejas.

3. Biblioteca estándar robusta

Tiene una biblioteca estándar grande y robusta para usar en el desarrollo de aplicaciones. También hace que los desarrolladores usen Python sobre otros lenguajes. La biblioteca estándar lo ayuda a usar la diferente gama de módulos disponibles para Python, ya que este módulo lo ayuda a agregar la funcionalidad sin escribir más código. Para obtener información sobre varios módulos, se puede consultar la documentación de la biblioteca estándar de Python. Al desarrollar cualquier aplicación web, implementar servicios web, realizar operaciones de cadenas y otros usos como el protocolo de interfaz, la documentación de la biblioteca estándar ayuda.

4. Compatible con las principales plataformas y sistemas

Es principalmente compatible con las principales plataformas y sistemas por lo que se utiliza principalmente para desarrollar aplicaciones. Con la ayuda de los intérpretes de Python, el código de Python se puede ejecutar en plataformas y herramientas específicas, ya que es compatible con muchos sistemas operativos. Como Python es un lenguaje de programación de alto nivel interpretado y le permite ejecutar el código en múltiples plataformas. El código nuevo y modificado se puede ejecutar sin volver a compilar, y su impacto se puede monitorear o verificar. Significa que no es necesario volver a compilar el código después de cada cambio. Esta característica ayuda a ahorrar el tiempo de desarrollo de los desarrolladores.

5. Acceso a la base de datos

Los usos de Python también ayudan a acceder fácilmente a la base de datos. Python ayuda a personalizar las interfaces de diferentes bases de datos como MySQL, Oracle, Microsoft SQL Server, PostgreSQL y otras bases de datos. Tiene una base de datos de objetos como Durus y ZODB. Se utiliza para la API de base de datos estándar y está disponible gratuitamente para su descarga.

6. Legibilidad del código

El código Python es fácil de leer y mantener. También es fácilmente reutilizable donde sea necesario. Python tiene una sintaxis simple, que permite que los diferentes conceptos se desarrollen sin escribir ningún código adicional. El código debe ser de buena calidad y fácil de mantener el código fuente y simplificar el mantenimiento, que se requiere para desarrollar la aplicación de software. También enfatiza la legibilidad del código, que es una gran característica, a diferencia de otros lenguajes de programación. Ayuda a crear aplicaciones personalizadas y el código limpio ayuda a mantener y actualizar las aplicaciones de software sin poner un esfuerzo adicional en el mismo código.

7. Simplifique el desarrollo de software complejo

Las aplicaciones de Python se utilizan para simplificar el complejo proceso de desarrollo de software, ya que es un lenguaje de programación de propósito general. Se utiliza para desarrollar aplicaciones complejas como aplicaciones científicas y numéricas y para aplicaciones web y de escritorio. Python tiene características como el análisis de datos y la visualización, lo que ayuda a crear soluciones personalizadas sin invertir tiempo ni esfuerzo adicional. Le ayuda a visualizar y presentar datos de forma eficaz.

8. Muchos marcos y herramientas de código abierto

Python es de código abierto y está fácilmente disponible. Esto también ayuda a calcular los costos del desarrollo de software de manera significativa. Hay muchas aplicaciones de código abierto de marcos, bibliotecas y herramientas de desarrollo de Python para desarrollar la aplicación sin poner un costo adicional. Los frameworks de Python simplifican y aceleran el proceso para el desarrollo de aplicaciones web, y los frameworks son Django, Flask, pyramid, etc. Los frameworks de GUI de Python están disponibles para desarrollar la aplicación basada en GUI.

9. Adopte el desarrollo basado en pruebas

Python facilita la codificación y las pruebas con la ayuda de la adopción del enfoque de desarrollo basado en pruebas. Los casos de prueba se pueden escribir fácilmente antes de cualquier desarrollo de código. Siempre que se inició el desarrollo del código, los casos de prueba escritos pueden comenzar a probar el código simultáneamente y proporcionar el resultado. Estos también se pueden usar para verificar o probar los requisitos previos basados ​​en el código fuente.

10. Otras aplicaciones para las que se usa Python

Hay otras aplicaciones para las que se usa Python que son robótica, web scraping, scripting, inteligencia artificial, análisis de datos, aprendizaje automático, detección de rostros, detección de color, aplicaciones CAD 3D, aplicaciones basadas en consola, aplicaciones basadas en audio, aplicaciones basadas en video. aplicaciones, aplicaciones empresariales y aplicaciones para imágenes, etc. Estas son algunas de las principales aplicaciones utilizadas.

Conclusión

En este artículo de Usos de Python, hemos visto que Python es uno de los principales lenguajes utilizados para desarrollar aplicaciones web y de escritorio. Python tiene características que se encargan de las tareas de programación comunes. Python es simple de aprender y fácil de usar. A veces, Python se marca como más lento que otros lenguajes de programación ampliamente utilizados como Java. Las aplicaciones de Python pueden acelerarse simplemente manteniendo el código y usando tiempo de ejecución personalizado.

Python admite los módulos y paquetes, lo que fomenta la modularidad del programa y la reutilización del código. Python proporciona un aumento en la productividad, lo que lo convierte en la primera opción de los desarrolladores. Tiene una gran curva de aprendizaje, ya que admite el lenguaje de programación funcional y procedimental. Es de código abierto y se puede distribuir libremente. El lenguaje de programación se selecciona principalmente en función de los requisitos y la compatibilidad con las plataformas y la base de datos.

Artículos recomendados

Esta ha sido una guía para los usos del lenguaje Python. Aquí hemos discutido en detalle los diferentes usos de Python & # 8217, como el fácil acceso a la base de datos, el desarrollo de software, la confiabilidad del código y la sólida biblioteca estándar. También puede echar un vistazo a los siguientes artículos para obtener más información & # 8211


5. Varias operaciones de reemplazo: reemplace múltiples patrones con la misma cadena

Reemplace cualquiera de foo, bar o baz con foobar

Una buena herramienta de Linux de reemplazo es rpl, que se escribió originalmente para el proyecto Debian, por lo que está disponible con apt-get install rpl en cualquier distribución derivada de Debian, y puede serlo para otras, pero de lo contrario, puede descargar el archivo tar.gz de SourceForge.

Tenga en cuenta que si la cadena contiene espacios, debe ir entre comillas. Por defecto, rpl se encarga de letras mayúsculas pero no de palabras completas, pero puede cambiar estos valores predeterminados con las opciones -i (ignorar mayúsculas y minúsculas) y -w (palabras completas). También puede especificar varios archivos:

O incluso especificar el extensiones (-x) para buscar o incluso buscar recursivamente (-R) en el directorio:

También puede buscar / reemplazar en modo interactivo con la opción -p (indicador):

La salida muestra el número de archivos / cadenas reemplazados y el tipo de búsqueda (mayúsculas / minúsculas, palabras completas / parciales), pero puede ser silencioso con -q (Modo silencioso), o incluso más detallada, enumerando los números de línea que contienen coincidencias de cada archivo y directorio con -v (modo detallado) opción.

Otras opciones que vale la pena recordar son -e (honor miscapes) que permiten expresiones regulares, por lo que puede buscar también pestañas ( t), nuevas líneas ( n), etc. Puede usar -f para forzar permisos (por supuesto, solo cuando el usuario tiene permisos de escritura) y -d para preservar los tiempos de modificación`).

Finalmente, si no está seguro de qué sucederá exactamente, use la -s (modo de simulación).


Un programa completo: solicitudes asincrónicas

Has llegado hasta aquí, y ahora es el momento de la parte divertida e indolora. En esta sección, usted & rsquoll construye un recopilador de URL de raspado web, areq.py, utilizando aiohttp, un marco cliente / servidor HTTP asíncrono increíblemente rápido. (Solo necesitamos la parte del cliente). Esta herramienta podría usarse para mapear conexiones entre un grupo de sitios, con los enlaces formando un gráfico dirigido.

Nota: Puede que se pregunte por qué Python & rsquos solicita el paquete no es & rsquot compatible con Async IO. Las solicitudes se construyen sobre urllib3, que a su vez usa módulos Python & rsquos http y socket.

De forma predeterminada, las operaciones de socket se bloquean. Esto significa que Python ganó & rsquot como await orders.get (url) porque .get () no es awaitable. En contraste, casi todo en aiohttp es una corrutina que se puede esperar, como session.request () y response.text (). De lo contrario, es un gran paquete, pero no se hace un flaco favor al usar solicitudes en código asincrónico.

La estructura del programa de alto nivel se verá así:

Lea una secuencia de URL de un archivo local, urls.txt.

Envíe solicitudes GET para las URL y decodifique el contenido resultante. Si esto falla, deténgase allí para obtener una URL.

Busque las URL dentro de las etiquetas href en el HTML de las respuestas.

Escriba los resultados en foundurls.txt.

Haga todo lo anterior de la forma más asincrónica y simultánea posible. (Utilice aiohttp para las solicitudes y aiofiles para los archivos adjuntos. Estos son dos ejemplos principales de IO que son adecuados para el modelo de IO asíncrono).

Aquí está el contenido de urls.txt. No es enorme y contiene principalmente sitios con mucho tráfico:

La segunda URL de la lista debería devolver una respuesta 404, que usted & rsquoll debe manejar con elegancia. Si está ejecutando una versión expandida de este programa, probablemente tendrá que lidiar con problemas mucho más complicados que este, como desconexiones del servidor y redireccionamientos sin fin.

Las solicitudes en sí deben realizarse utilizando una sola sesión, para aprovechar la reutilización del grupo de conexiones internas de sesión y rsquos.

Dejemos que & rsquos eche un vistazo al programa completo. Nosotros & rsquoll revisamos las cosas paso a paso después de:

Este script es más largo que nuestros programas de juguete iniciales, así que vamos a analizarlo con & rsquos.

La constante HREF_RE es una expresión regular para extraer lo que buscamos en última instancia, etiquetas href dentro de HTML:

La corrutina fetch_html () es un envoltorio alrededor de una solicitud GET para realizar la solicitud y decodificar el HTML de la página resultante. Realiza la solicitud, espera la respuesta y aumenta de inmediato en el caso de un estado que no sea 200:

Si el estado es correcto, fetch_html () devuelve la página HTML (a str). En particular, no se realiza ningún manejo de excepciones en esta función. La lógica es propagar esa excepción a la persona que llama y dejar que se maneje allí:

Esperamos session.request () y resp.text () porque necesitan corrutinas en espera. De lo contrario, el ciclo de solicitud / respuesta sería la parte de la aplicación de cola larga y que ocupa el tiempo, pero con la E / S asíncrona, fetch_html () permite que el bucle de eventos funcione en otros trabajos disponibles, como analizar y escribir URL que ya se han recuperado. .

A continuación en la cadena de corrutinas viene parse (), que espera en fetch_html () una URL determinada, y luego extrae todas las etiquetas href de esa página & rsquos HTML, asegurándose de que cada una sea válida y formateándola como una ruta absoluta.

Es cierto que la segunda parte de parse () está bloqueando, pero consiste en una coincidencia rápida de expresiones regulares y garantiza que los enlaces descubiertos se conviertan en rutas absolutas.

En este caso específico, este código sincrónico debe ser rápido y discreto. Pero recuerde que cualquier línea dentro de una corrutina determinada bloqueará otras corrutinas a menos que esa línea use rendimiento, espera o retorno. Si el análisis fue un proceso más intensivo, es posible que desee considerar ejecutar esta parte en su propio proceso con loop.run_in_executor ().

A continuación, la corrutina write () toma un objeto de archivo y una única URL, y espera a parse () para devolver un conjunto de las URL analizadas, escribiendo cada una en el archivo de forma asincrónica junto con su URL de origen mediante el uso de aiofiles, un paquete para archivo asíncrono IO.

Por último, bulk_crawl_and_write () sirve como el principal punto de entrada a la cadena de secuencias de comandos y rsquos. Utiliza una sola sesión y se crea una tarea para cada URL que finalmente se lee de urls.txt.

Aquí hay algunos puntos adicionales que merecen ser mencionados:

La ClientSession predeterminada tiene un adaptador con un máximo de 100 conexiones abiertas. Para cambiar eso, pase una instancia de asyncio.connector.TCPConnector a ClientSession. También puede especificar límites por host.

Puede especificar tiempos de espera máximos tanto para la sesión en su conjunto como para solicitudes individuales.

Este script también usa async with, que funciona con un administrador de contexto asincrónico. No he dedicado una sección completa a este concepto porque la transición de administradores de contexto sincrónicos a asincrónicos es bastante sencilla. Este último tiene que definir .__ aenter __ () y .__ aexit __ () en lugar de .__ exit __ () y .__ enter __ (). Como era de esperar, async with solo se puede usar dentro de una función de rutina declarada con async def.

Si desea explorar un poco más, los archivos complementarios para este tutorial en GitHub también tienen comentarios y cadenas de documentación adjuntas.

Aquí & rsquos la ejecución en todo su esplendor, ya que areq.py obtiene, analiza y guarda los resultados de 9 URL en menos de un segundo:

¡Eso y rsquos no está mal! Como comprobación de cordura, puede comprobar el recuento de líneas en la salida. En mi caso, es & rsquos 626, aunque tenga en cuenta que esto puede fluctuar:

Próximos pasos: Si desea subir la apuesta, haga que este webcrawler sea recursivo. Puede usar aio-redis para realizar un seguimiento de las URL que se han rastreado dentro del árbol para evitar solicitarlas dos veces, y conectar enlaces con la biblioteca de Python y rsquos networkx.

Recuerda ser amable. Enviar 1000 solicitudes simultáneas a un sitio web pequeño y desprevenido es malo, malo, malo. Hay formas de limitar la cantidad de solicitudes simultáneas que realiza en un lote, como al usar los objetos sempahore de asyncio o un patrón como este. Si no presta atención a esta advertencia, es posible que obtenga una gran cantidad de excepciones TimeoutError y solo termine dañando su propio programa.


1 respuesta 1

¡Gracias por compartir tu código!

No cubriré todas sus preguntas, pero haré todo lo posible.

(advertencia, mensaje largo entrante)

¿Es correcta mi implementación? (Las pruebas lo dicen)

En la medida en que intenté romperlo, diría que sí, es correcto. Pero vea a continuación métodos de prueba más completos.

¿Puede acelerarse?

Lo primero que hice fue cambiar ligeramente el perfil de su archivo de prueba (lo llamé test_heap.py) para generar la generación de la lista aleatoria. También cambié la llamada random.sample para que sea más flexible con el parámetro sample_size.

Entonces, la población de random.sample siempre es mayor que mi sample_size. ¿Quizás haya una mejor manera?

También configuré el tamaño de la muestra en 50000 para tener un tamaño decente para el siguiente paso.

El siguiente paso fue perfilado el código con python -m cProfile -s cumtime test_heap.py. Si no está familiarizado con el generador de perfiles, consulte el documento. Lanzo el comando varias veces para comprender las variaciones en la sincronización, lo que me da una línea de base para la optimización. El valor original era:

Ahora tenemos un objetivo que superar y algo de información sobre lo que lleva tiempo. No pegué la lista completa de llamadas a funciones, es bastante larga, pero entiendes la idea.

Se gasta mucho tiempo en _siftdown y mucho menos en _siftup, y algunas funciones se llaman muchas veces, así que veamos si podemos solucionarlo.

(Debería haber comenzado por _siftdown, que era el pez gordo aquí, pero por alguna razón, comencé por _siftup, perdóname)

Acelerando _siftup

Cambié la forma de calcular parent_index porque miré la fuente del módulo heapq y lo usan. (ver aquí) pero no pude ver la diferencia en el momento de este cambio solo.

Luego eliminé la llamada a _get_parent e hice el cambio apropiado (algo así como incluirlo porque la llamada a la función no es barata en Python) y la nueva hora es

Las llamadas de función disminuyeron obviamente, pero el tiempo solo disminuyó alrededor de 70-80 milisegundos. No es una gran victoria (un poco menos del 3% de aceleración). Y la legibilidad no se mejoró, así que depende de usted si vale la pena.

Acelerando _siftdown

El primer cambio fue mejorar la legibilidad.

Transformé la asignación ternaria

Lo encuentro mucho más legible, pero probablemente sea una cuestión de gustos. Y para mi sorpresa, cuando volví a perfilar el código, el resultado fue:

(Lo ejecuté 10 veces y siempre había ganado alrededor de 80-100 milisegundos). Realmente no entiendo por qué, si alguien me puede explicar.

Como en _siftup, incluí 2 llamadas de la función auxiliar _get_left_child y _get_right_child y ¡valió la pena!

Eso es una aceleración del 30% desde la línea de base.

(Lo que sigue es una optimización adicional que trato de explicar, pero perdí el código que escribí para ella, intentaré corregirlo más tarde. Podría darte una idea de la ganancia)

Luego, usar el truco de heapq de especializar la comparación para max y min (usando una versión _siftdown_max y _siftup_max reemplazando el comparador por & gt y haciendo lo mismo para min) nos da:

No llegué más lejos en las optimizaciones, pero el _siftdown sigue siendo un pez gordo, así que tal vez haya espacio para más optimizaciones. Y pop and push tal vez podría modificarse un poco, pero no sé cómo.

Al comparar mi código con el del módulo heapq, parece que no proporcionan una clase heapq, sino que solo proporcionan un conjunto de operaciones que funcionan en listas. ¿Es esto mejor?

Muchas implementaciones que vi iterar sobre los elementos usando un bucle while en el método siftdown para ver si llega al final. En lugar de eso, llamo de nuevo a Siftdown sobre el niño elegido. ¿Este enfoque es mejor o peor?

Dado que las llamadas a funciones son caras, el bucle en lugar de la recursividad podría ser más rápido. Pero lo encuentro mejor expresado como una recursividad.

¿Mi código es limpio y legible?

¡En su mayoría, sí! Buen código, tienes cadenas de documentación para tus métodos públicos, respetas PEP8, todo está bien. ¿Quizás también podría agregar documentación para el método privado? Especialmente para cosas difíciles como _siftdown y _siftup.

el ternario que cambié en _siftdown lo considero personalmente muy difícil de leer.

comparer parece un nombre francés, ¿por qué no comparar? O me perdí algo o tu lenguaje mezclado y no deberías.

¿Mi prueba es suficiente (por ejemplo, una entrevista)?

Yo diría que no. Utilice un módulo para realizar pruebas unitarias. Personalmente, me gusta pytest.

Prefijo el nombre de su archivo de prueba con test_ y luego sus métodos de prueba tienen el prefijo / sufijo test_ / _test. Luego, simplemente ejecuta pytest en la línea de comando y descubre las pruebas automáticamente, las ejecuta y le da un informe. Te recomiendo que lo pruebes.

Otra gran herramienta que podría haber utilizado es la hipótesis, que realiza pruebas basadas en propiedades. Funciona bien con pytest.

Básicamente ofrece el mismo tipo de prueba que hizo en su automatic_test, pero se le agregan un montón de características interesantes y es más corto de escribir.

Raymond Hettinger hizo una charla realmente genial sobre las herramientas que se pueden usar cuando se realizan pruebas con un presupuesto de tiempo corto, mencionó tanto pytest como hipótesis, échale un vistazo :)

¿Es el uso de las subclases MinHeap y MaxHeap y su método de comparación que las distingue, un buen enfoque para proporcionar ambos tipos de montones?

¡Creo que lo es! Pero en cuanto a la velocidad, debería volver a declarar el tamizado y el tamizado en las subclases y reemplazar la instancia de comparar (a, b) por a & lt bo a & gt b en el código.

Lo último es un comentario, en wikipedia, el artículo dice:

Sift-up: mueve un nodo hacia arriba en el árbol, siempre que sea necesario para restaurar la condición del montón después de la inserción. Se llama & quotsift & quot porque el nodo sube por el árbol hasta que alcanza el nivel correcto, como en un tamiz.

Sift-down: mueve un nodo hacia abajo en el árbol, similar al sift-up utilizado para restaurar la condición del montón después de eliminarlo o reemplazarlo.

Y creo que lo usó en este contexto, pero en la implementación del módulo heapq parece tener el nombre al revés.

Usan siftup en pop y siftdown en push, mientras que wikipedia nos dice que hagamos lo contrario. ¿Alguien puede explicar por favor?


Algoritmo de doble metafono

El principio del algoritmo se remonta al siglo pasado, en realidad al año 1918 (cuando faltaban años para la primera computadora).

Solo como información complementaria (si alguna vez participas en un concurso millonario), la primera computadora estaba a 23 años de distancia.

El Z3 era un ordenador electromecánico alemán diseñado por Konrad Zuse. Fue la primera computadora digital totalmente automática y programable en funcionamiento del mundo. El Z3 fue construido con 2600 relés, implementando una longitud de palabra de 22 bits que operaba a una frecuencia de reloj de aproximadamente 4-5 Hz. El código del programa se almacenó en una película perforada. Los valores iniciales se ingresaron manualmente (Wikipedia)

Entonces, en 1918, en ese año, Robert C. Russell de la Oficina del Censo de EE. UU. Inventó el algoritmo Soundex que es capaz de indexar el idioma inglés de una manera que se pueden encontrar múltiples ortografías del mismo nombre con solo una mirada superficial.

Los inmigrantes a los Estados Unidos tenían un idioma nativo que no se basaba en caracteres romanos. Para escribir sus nombres, los nombres de sus parientes o las ciudades de las que llegaron, los inmigrantes tuvieron que adivinar cómo expresar su lenguaje simbólico en inglés. El gobierno de los Estados Unidos se dio cuenta de la necesidad de poder categorizar los nombres de ciudadanos privados de una manera que permitiera agrupar múltiples grafías del mismo nombre (por ejemplo, Smith y Smythe). (Lee la historia completa aquí)

El algoritmo Soundex se basa en una categorización fonética de letras del alfabeto. En su patente, Russell describe la estrategia asignando un valor numérico a cada categoría. Por ejemplo, Johnson se asignó a J525, Miller a M460, etc.

El algoritmo Soundex evolucionó con el tiempo en el contexto de la eficiencia y la precisión y fue reemplazado por otros algoritmos.

En su mayor parte, todos han sido reemplazados por el poderoso sistema de indexación llamado Double Metaphone. El algoritmo está disponible como código abierto y su última versión se lanzó alrededor de 2009.

Afortunadamente, hay una biblioteca de Python disponible, que usamos en nuestro programa. Escribimos algunos métodos de envoltura pequeños alrededor del algoritmo e implementamos un método de comparación.

La doble metafono El método devuelve una tupla de clave de dos caracteres, que son una traducción fonética de la palabra pasada. Nuestra comparar El método muestra la capacidad de clasificación del algoritmo, que es bastante limitada.

Realicemos algunas comprobaciones de verificación para evaluar la eficiencia del algoritmo mediante la introducción de test_class.py que se basa en Python pytest marco de referencia.

El marco de pytest facilita la escritura de pequeñas pruebas, pero escala para admitir pruebas funcionales complejas para aplicaciones y bibliotecas. (Enlace)

Su uso es sencillo y puede ver la implementación de la clase de prueba a continuación.

Los resultados de las pruebas se muestran a continuación. Usamos dos nombres (A + B) y verificamos con algunos nombres cambiados (A1 / A2 + B1 / B2 / B3) la eficiencia del algoritmo.

  • A1 + B1 pasó el control de coincidencia fuerte. Entonces, los espacios faltantes y los reemplazos de ü / ä con u / a parecen no afectar la generación de claves de doble metafono
  • B2 pasa el partido Normal. Los errores ortográficos también están cubiertos por el algoritmo
  • A2 + B3 están fallando. A2 utiliza una abreviatura de una parte del nombre, que no se puede afrontar. Teníamos que esperar este comportamiento y decidimos introducir el algoritmo de expansión de nombres (ver más arriba). B3 falló debido a que faltaba "-". Esto fue inesperado, pero cubrimos este comportamiento con un paso de limpieza de segundo nombre.

Lista de comprensiones (opcional)

Las listas de comprensión son una característica más avanzada que es útil en algunos casos, pero no es necesaria para los ejercicios y no es algo que deba aprender al principio (es decir, puede omitir esta sección). Una lista de comprensión es una forma compacta de escribir una expresión que se expande a una lista completa. Supongamos que tenemos una lista de números [1, 2, 3, 4], aquí está la lista de comprensión para calcular una lista de sus cuadrados [1, 4, 9, 16]:

La sintaxis es [ expr for var in list ] -- the for var in list looks like a regular for-loop, but without the colon (:). La expr to its left is evaluated once for each element to give the values for the new list. Here is an example with strings, where each string is changed to upper case with '. ' appended:

You can add an if test to the right of the for-loop to narrow the result. The if test is evaluated for each element, including only the elements where the test is true.


Ver el vídeo: POO python parte 1