Cosas que debe saber si desea cambiar de PHP a Python

¿Alguna vez pensaste que un día te metiste en la programación web PHP demasiado rápido?
Ya han pasado varios años, ha ganado mucha experiencia y no puede pensar en otras formas de trabajar con la web, excepto PHP. Quizás, a veces dudas de la elección que has hecho, pero no puedes confirmar tus dudas aquí y ahora. Al mismo tiempo, necesitas ejemplos reales; Desea comprender los cambios que pueden ocurrir en aspectos particulares de su trabajo.

Hoy trataré de responder la siguiente pregunta: " ¿Qué pasa si usamos Python en lugar de PHP? ".

He hecho esta pregunta muchas veces. He estado usando PHP durante 11 años y soy un especialista certificado en PHP. Lo he dominado para que funcione de la manera que quiero. Realmente me sorprendieron varios artículos que criticaban severamente a PHP ( PHP: un fractal de mal diseño ). Sin embargo, cuando llegó la oportunidad, me cambié a Ruby y luego a Python. Finalmente, elegí el último. Ahora intentaré explicar cómo vivimos los chicos de Python.



Formato del artículo


La mejor manera de aprender un nuevo idioma es compararlo con un idioma que ya pueda aplicar, a menos que el nuevo idioma difiera drásticamente del actual. Un artículo en el portal web de Ruby ( Ruby de otros idiomas ) proporciona esa comparación, sin embargo, carece de ejemplos.

También debo señalar que este mismo artículo compara solo los aspectos que llaman su atención durante las primeras semanas después de cambiar al nuevo idioma.

Preparando consolas


He hecho todo lo posible para que este artículo sea interactivo. Por lo tanto, recomiendo ejecutar todos los ejemplos en las consolas al leer el artículo. Necesitará una consola PHP, o puede usar la consola PsySH , que es aún mejor:

php -a 

Y una consola Python. Recomiendo usar bpython o ipython , ya que cuentan con una comparación de finalización de código con la consola predeterminada integrada en el idioma. Sin embargo, la siguiente opción también es aplicable:

 python 

Y luego:

 import rlcompleter import readline readline.parse_and_bind("tab: complete") # Enable autocomletion 

Evitar la repetición de estas acciones.
Cree un archivo ~ / .pyrc con:

 import rlcompleter import readline readline.parse_and_bind("tab: complete") 

Agregue algunas líneas en el archivo ~ / .bashrc:

 export PYTHONSTARTUP="${HOME}/.pyrc" export PYTHONIOENCODING="UTF-8" 

Adn para hacer cambios inmediatamente sin volver a iniciar sesión:

 source ~/.bashrc 


Sobre idiomas


  • Python es un lenguaje que presenta una tipificación dinámica de pato fuerte ( consulte Información sobre la tipificación ). Python no está limitado en términos de su aplicación. Se utiliza para desarrollo web, demonios, cálculos científicos o como lenguaje de extensiones. Idiomas similares en términos de mecanografía: Ruby.
  • PHP es un lenguaje que presenta una tipificación dinámica de pato débil. PHP también es un lenguaje de propósito común, sin embargo, su área de aplicación cubre principalmente web y demonios. Otras características no se resuelven correctamente, por lo que no es aplicable en producción. Algunas personas creen que PHP está destinado a morir . Lenguajes similares en términos de mecanografía: JavaScript, Lua, Perl.

Detalles generales


  • El código está escrito en archivos .py independientemente de la versión de Python. No se requieren etiquetas de apertura como <? PHP, ya que Python se desarrolló originalmente como un lenguaje de programación de propósito general.
  • Además, no hay php.ini por la misma razón. Hay dos docenas
    variables de entorno , sin embargo, no están definidas en la mayoría de los casos (aparte de PYTHONIOENCODING). En otras palabras, no hay conexiones predeterminadas a bases, gestión de filtros de error, gestión de límites, extensiones, etc., lo cual es natural para la mayoría de los lenguajes de uso general. Como resultado, los programas se comportan de manera similar en la mayoría de los casos (su comportamiento no depende de la configuración favorita del líder de su equipo). Ajustes como php.ini se almacenan en el archivo de configuración principal de una aplicación en la mayoría de los casos.
  • No se necesita un punto y coma al final de una cadena. Sin embargo, si ponemos un punto y coma allí, funciona como en PHP. Sin embargo, es innecesario y no deseado, por lo que simplemente puede olvidarse de él.
  • Las variables no comienzan con $ (que PHP heredó de Perl que a su vez lo adoptó
    de Bash).
  • La asignación en ciclos y condiciones no se aplica, por lo que nadie confunde la comparación con la asignación, lo cual es un error común (como cree el autor del idioma). Vea PEP 572 para python 3.8 si lo necesita.
  • Al analizar los archivos, Python coloca automáticamente la copia del archivo con la extensión .pyc (siempre que su versión de Python sea inferior a 3.3 y no haya instalado PYTHONDONTWRITEBYTECODE ) en la misma carpeta donde se encuentra su código de bytes. Entonces siempre ejecuta este mismo archivo, a menos que cambie la fuente.
    Estos archivos se ignoran automáticamente en todos los IDE y generalmente no interfieren. Esta característica se puede percibir como un análogo completo de PHP APC, teniendo en cuenta que los archivos .pyc probablemente se ubicarán en la memoria caché de archivos.
  • En lugar de NULL, TRUE, false deberíamos usar None, True, false (particularmente en este caso).

Anidamiento y sangría


Aquí hay algo inusual: la anidación de código se determina con sangrías en lugar de corchetes.

Entonces, en lugar de:

 foreach($a as $value) { $formatted = $value.'%'; echo $formatted; } 

Deberíamos escribir lo siguiente:

 for value in a: formatted = value + '%' print(formatted) 

¡Espera, espera! No cierres el artículo. Aquí podrías cometer el mismo error que cometí.
Una vez creí que la idea de usar sangrías para anidar código es ridícula. Toda mi naturaleza protestaba contra eso, ya que todos los desarrolladores escriben su código a su manera, independientemente de las diferentes Guías de estilo.
Aquí está el misterio del mundo: no hay problema de sangría. En la mayoría de los casos (99% de los casos), el IDE coloca automáticamente las sangrías como en cualquier otro idioma. Simplemente no lo piensas en absoluto. No he enfrentado ningún problema relacionado con sangrías durante más de 2 años de usar el idioma.

Mecanografía fuerte


Lo siguiente a lo que debe prestarle atención es a Strong Typing. Sin embargo, algo de código primero:

 print '0.60' * 5; print '5' == 5; $a = array('5'=>true); print $a[5]; $value = 75; print $value.'%'; $a='0'; if($a) print 'non zero length'; // Will not print, common mistake 

Todos los ejemplos anteriores son posibles gracias a la tipificación dinámica.
Sí, sé que la declaración de tipo está disponible para PHP. Pero no está habilitado de forma predeterminada y no funciona en todas partes.

Sin embargo, lo siguiente no funcionará en Python:

 >>> print "25" + 5 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: cannot concatenate 'str' and 'int' objects 

Excepto ...
Excepto por los valores booleanos, pero es por diseño .

Por lo general, los tipos de datos no se mezclarán en su código y este efecto no lo distraerá. En general, cuando codifiqué en PHP, solo hubo algunas situaciones por proyecto en las que la escritura dinámica realmente ayudó. En todos los demás casos, las variables del mismo tipo interactúan entre sí.

Typing fuerte afecta el manejo de errores. Por ejemplo, si una función int devuelve un entero, no puede devolver None a una cadena, de la que este tipo no se puede extraer explícitamente. En este caso, se generará una excepción. Puede requerir convertir todos los datos del usuario al tipo de datos necesario, de lo contrario, se generará una excepción en la versión de producción algún día.

 try: custom_price = int(request.GET.get('custom_price', 0)) except ValueError: custom_price = 0 

Afecta no solo las funciones estándar, sino también algunos métodos de las listas, cadenas y algunas funciones de bibliotecas adicionales. Por lo general, un desarrollador de Python tiene en cuenta todas las excepciones que se pueden generar y las considera. Si el desarrollador no los recuerda, verifican el código de la biblioteca. Por supuesto, a veces no se consideran todos los casos, y los usuarios pueden causar excepciones en la versión de Producción. Dado que este es un fenómeno raro, y generalmente los marcos web los envían automáticamente al correo del administrador, tales casos se corrigen rápidamente.

Para usar valores de varios tipos de datos dentro de una sola expresión, deben convertirse. Hay funciones para eso: str , int , bool , long . Además, hay decisiones más convenientes para el formateo.

Cuerdas


Formateo


En PHP:

 $this_way = 'this_way'; echo "Currently you do it $this_way or {$this way}."; echo "Or ".$this_way."."; echo sprintf("However the following is possible: , %s or %1$'.9s.", $this_way); 

Ahora deberías aprender a hacerlo de una manera diferente:

 etot = 'this' var = 'option' print('To %s option' % etot) print(etot + ' option can also be used, but not recommended) print('Or to %s %s' % (etot, var)) print('Or to %(etot)s %(var)s' % {'etot': etot, 'var': var}) # Very useful for localization team print('Or to {} {}'.format(etot, var)) print('Or to {1} {0}'.format(var, etot)) print('Or to {etot} {var}'.format(var=var, etot=etot)) # And finally print(f'Or to {etot} {var}') # Starting from Python 3.6 

Hay más opciones y hay una opción conveniente para las localizaciones.

Métodos de cuerda


Python tiene algo que falta en PHP: métodos incorporados. Comparemos:

 strpos($a, 'tr'); trim($a); 

vs

 a.index('tr') a.strip() 

¿Y con qué frecuencia haces algo así?

 substr($a, strpos($a, 'name: ')); 

vs

 a[a.index('name: '):] 

Soporte Unicode


Finalmente, Unicode. En Python 2, todas las cadenas NO son Unicode por defecto. (En Python 3, todas las cadenas son Unicode por defecto). Sin embargo, cuando agrega el carácter u al comienzo de una cadena, automáticamente se convierte en Unicode. Y luego todos los métodos de cadena integrados (y no integrados) de Python funcionarán correctamente.

 >>> len(' ') # Hello world in Russian 19 >>> len(u' ') 10 

En PHP, el procesamiento natural de Unicode se estaba desarrollando para PHP 6, pero PHP 6 se canceló ( Andrei Zmievski: Qué sucedió con Unicode y PHP 6 ).
En PHP, por cierto, puede usar la sobrecarga de la función MBString para recibir un efecto similar, pero está en desuso.
Sin embargo, no podrá trabajar con cadenas binarias utilizando funciones sobrecargadas, pero aún podrá trabajar con una cadena como una matriz.

Acerca de cadenas sin formato (opcional)

Cuerdas crudas


Debe saber la diferencia entre cadenas de comillas simples y cadenas de comillas dobles:

 $a = 'Hello.\n'; $a[strlen($a)-1] != "\n"; 

La característica similar en Python ha llamado cadenas en bruto. Para usarlo, coloque r caracterizada antes de una cadena entre comillas simples.

 a = r'Hello.\n' a[-1] != '\n' 


Matrices


Ahora es el momento de las matrices. En PHP puedes usar enteros o cadenas como claves:

 var_dump([0=>1, 'key'=>'value']); 

En PHP, las matrices no son matrices estándar ( listas ), sino matrices asociativas ( diccionario ). Las matrices estándar también están disponibles en PHP, son SPLFixedArray . Requieren menos memoria, potencialmente funcionan más rápido, pero debido a la complejidad de crear y extender, rara vez se usan.

En Python, se usan cuatro tipos de datos para una matriz:

  • lista

     a = [1, 2, 3] # short form a[10] = 11 # Unexist indexes cannot be added. # > IndexError: list assignment index out of range a.append(11) # but you can adds an element to the end of a list. del a[0] # and delete the element using the index a.remove(11) # and also remove an element using its value 
  • dict - diccionario. Los diccionarios no tienen un orden de almacenamiento de datos (como lo hacen en PHP).

     d = {'a': 1, 'b': 2, 'c': 3} # short form d[10] = 11 # Random indexes can be added d[True] = False # And use any immutable types (integers, strings, booleans, tuples, frozen-sets) del d[True] # And delete using a key 
  • tupla Algo así como una matriz fija de valores no homogéneos. Perfectamente adecuado para devolver varios valores de una función y para el almacenamiento compacto de configuraciones.

     t = (True, 'OK', 200, ) # short form t[0] = False # Elements are immutable # > TypeError: 'tuple' object does not support item assignment del t[True] # Cannot be deleted using a key # > TypeError: 'tuple' object doesn't support item deletion t = ([], ) # However, nested mutable structures can be muted (lists, dictionaries, sets, bite arrays, objects) t[0].append(1) # > a == ([1], ) 
  • conjunto Básicamente, esta es una lista de valores únicos que no tienen orden de almacenamiento.

     s = set([1,3,4]) s[0] = False # sets do not support indexing # > TypeError: 'set' object does not support indexing s.add(5) # adds an element s.remove(5) # deletes an element # # Standard maths for sets s | s # Merge s & s # Intersection s - s # Difference s ^ s # Merge of unique elements 

En PHP, las matrices son una especie de navaja suiza: pueden servir para todos los propósitos. En cuanto a Python, debe usar matrices de datos que sean nativas para Computer Science. Además, debe usar matrices de datos apropiadas para cada caso. Puede decir que estas son dificultades innecesarias que los programadores nunca deberían enfrentar. Bueno, ese no es el punto.

  • Primero: la posibilidad de elegir entre tupla, set, list y dict no dificulta las cosas, solo se convierte en un hábito subconsciente como cambiar de marcha.
  • Segundo: lista o dict se utilizan en la mayoría de los casos.
  • Tercero: en la mayoría de los casos, cuando necesita almacenar el par clave-valor, el orden no es esencial, sin embargo, cuando necesita mantener el orden, en la mayoría de los casos solo hay valores en lugar de pares clave-valor.
  • Cuarto: Python tiene un diccionario ordenado: OrderedDict .


Importaciones


Esta es una característica muy interesante. Es una especie de concepto alternativo de espacios de nombres que deben usarse.
En PHP, escribe require_once y permanece disponible hasta el final de la sesión de ejecución de PHP. Generalmente, cuando usan CMS, los desarrolladores colocan todo en clases, los colocan en ubicaciones especiales, escriben una pequeña función que conoce estas ubicaciones y registran esta función a través de spl_autoload_register al comienzo del archivo.

En Python, sin embargo, cada archivo tiene su propio espacio de nombre. Como resultado, un archivo solo contendrá objetos que importe allí. Por defecto, solo está disponible la biblioteca estándar de Python (aproximadamente 80 funciones).

Verifique el siguiente ejemplo:
Supongamos que ha creado el archivo tools / logic.py :

 def is_prime(number): max_number = int(sqrt(number)) for multiplier in range(2, max_number + 1): if multiplier > max_number: break if number % multiplier == 0: return False return True 

Ahora, desea usarlo en el archivo main.py. En este caso, debe importar el archivo completo o las entidades de archivo que necesita en el archivo de destino en el que está trabajando.

 from tools.logic import is_prime print(is_prime(79)) 

Esta regla se aplica a todo Python. En la mayoría de los casos, cuando comienza a trabajar en cualquier archivo, primero necesita importar objetos auxiliares de Python en su archivo: sus bibliotecas propias e integradas. Es como si las funciones de PHP como mysqli_ *, pdo_ *, memcached_ *, así como todo su código, estuvieran almacenadas en espacios de nombres y usted tuviera que importarlas en cada archivo con el que trabaja. ¿Qué ventajas tiene este enfoque?

  • Primero: diferentes objetos en diferentes archivos pueden tener nombres idénticos. Sin embargo, es usted quien selecciona el objeto, su nombre y el archivo de destino.
  • Segundo: la refactorización es mucho más fácil. Siempre puede realizar un seguimiento de una clase, función o cualquier otra entidad. Use una búsqueda simple para localizar una función y ver dónde / cómo se usa.
  • Tercero: esta característica hace que los desarrolladores piensen en la estructura del código (al menos en cierta medida).

Por otro lado, solo podemos mencionar un inconveniente: las importaciones circulares . Sin embargo, es un problema raro. Además, es un problema familiar y los desarrolladores conocen las formas de resolverlo.

¿Es conveniente utilizar las importaciones todo el tiempo? Depende de tu preferencia. Si desea tener más control sobre el código, preferirá usar importaciones. Algunos equipos incluso tienen reglas que regulan el orden de asignación de código externo, a fin de minimizar la cantidad de importaciones circulares. Si su equipo no tiene tales reglas y no quiere molestarse mucho, simplemente puede confiar en IDE que importará automáticamente todo lo que use. Además: las importaciones no son una característica única de Python, también se usan en Java y C #.

No ha habido quejas hasta ahora.

Parámetros * args y ** kwargs en una función


La sintaxis con los parámetros predeterminados es generalmente la misma:

 function makeyogurt($flavour, $type = "acidophilus") { return "Making a bowl of $type $flavour."; } 

vs

 def makeyogurt(flavour, ftype="acidophilus"): return "Making a bowl of %s %s." % (ftype, flavour, ) 

Sin embargo, a veces puede necesitar una función para un número desconocido de argumentos.
Por ejemplo, una función proxy, una función de registro o una función para recibir señales. En PHP, a partir de la versión 5.6, está disponible la siguiente sintaxis:

 function sum(...$numbers) { $acc = 0; foreach ($numbers as $n) { $acc += $n; } return $acc; } echo sum(1, 2, 3, 4); // or echo add(...[1, 2, 3, 4]); 

Respectivamente, en Python, puede agregar argumentos sin nombre en una matriz y agregar argumentos con nombre en un diccionario:

 def acc(*args, **kwargs): total = 0 for n in args: total += n return total print(acc(1, 2, 3, 4)) # or print(acc(*[1, 2, 3, 4])) 

Respectivamente, * args - lista de argumentos sin nombre, ** kwargs - diccionario de argumentos con nombre.

Clases


Echa un vistazo al siguiente código:

 class BaseClass: def __init__(self): print("In BaseClass constructor") class SubClass(BaseClass): def __init__(self, value): super(SubClass, self).__init__() # or short form: super().__init__() starting from Python 3 self.value = value def __getattr__(self, name): print("Cannot found: %s" % name) c = SubClass(7) print(c.value) 

Las principales diferencias con PHP son las siguientes:

  • self se usa en lugar de $ this , y los métodos siempre se llaman usando el operador de acceso ("."). Además, "self" siempre debe ser el primer argumento en todos los métodos (bueno, en la mayoría de ellos). El punto es que Python proporciona todos los métodos con un enlace al objeto con el primer argumento (el objeto mismo se puede agregar a una variable con cualquier nombre).
  • Como en PHP, hay un análogo de nombres mágicos . En lugar de __construct - __init__ . En lugar de __get - __getattr__ , etc.
  • No se requiere nuevo. Crear una instancia de clase es lo mismo que llamar a una función.
  • Una llamada más compleja al método principal. En cuanto a super, siempre debes tener en cuenta todos los detalles. parent :: En cuanto a PHP, la estructura es menos voluminosa.

También debemos mencionar lo siguiente:

  • Se puede heredar más de una clase.
  • No público , protegido , privado . Python permite cambiar una estructura de instancia (así como toda la clase) en la ejecución mediante una asignación simple, por lo que no se necesita protección. Por lo tanto, la reflexión no es necesaria también. Sin embargo, hay un análogo del estado protegido: doble guión bajo antes del nombre. Sin embargo, esta operación simplemente cambia el nombre visible de la variable / método a _% ClassName% __% varname% que permite trabajar con datos ocultos.
  • No hay clases estáticas, finales e interfaces. El modelo está más basado en objetos en Python en general. En lugar de Singleton, es probable que tenga un archivo que contenga todas las funciones requeridas o un archivo que devuelva la misma instancia al importar. En lugar de la interfaz, es probable que cree una clase que genere excepciones para los métodos que no se reasignan por alguna razón (es decir, es posible una solución alternativa).
  • No se desea aplicar solo programación orientada a objetos (OOP). Como todo es un objeto de todos modos (incluso bool) y la sintaxis no tiene operadores diferentes para llamar a un método o función desde un archivo importado, todas las llamadas se realizan con el operador de acceso ("."). Por lo tanto, la encapsulación no necesariamente requiere OOP. Por lo tanto, en la mayoría de los proyectos, las clases se crean donde realmente se requieren.

Estilo de codificación


He trabajado en varios proyectos a largo plazo y noté que todos los miembros del equipo tienen un estilo de codificación diferente. En muchos casos, un código puede ayudar a identificar al autor del código. Siempre quise que se adoptara cualquier estándar de estilo de código con fines de coherencia.

Sin embargo, siempre ha habido muchos argumentos al aprobar este documento dentro del equipo. Este problema también afecta a Python, pero en menor medida, ya que hay varias recomendaciones de especialistas calificados, que definitivamente serán suficientes para comenzar:


Además, hay un llamado Zen de Python. Una de sus reglas establece que "debería haber una, y preferiblemente solo una, la forma anterior de hacerlo". Por lo tanto, un código no se puede escribir de varias maneras aproximadamente similares. Por supuesto, eso es idealismo, pero ayuda en muchos casos:

  • En lugar de una gran biblioteca de existencias que contiene varias funciones que se duplican parcialmente entre sí, utilizamos un conjunto más pequeño de métodos y bibliotecas de integración adicionales (por ejemplo, para totales de hash).
  • En lugar de strlen and count , siempre usamos len .

etc.

Versiones de Python


Las nuevas versiones de PHP siempre son compatibles con versiones anteriores, aunque a veces se requieren mejoras. Por otro lado, hay Python 2 y Python 3 Son incompatibles poco por defecto. Sin embargo, recientemente, los desarrolladores de Python han mejorado significativamente la situación. Puede escribir un código para dos versiones de Python, pero si utiliza las nuevas funciones de Python 3, como la programación asincrónica o las nuevas funciones de Unicode (UTF 8), es probable que tenga dificultades. Debido a esto, los proyectos que ya se han desarrollado y codificado durante varios años, todavía usan Python 2.

Pero para nuevos proyectos no hay razón para usar Python 2.

Alias ​​de idiomas cruzados


A continuación se muestra la lista de palabras clave que explican la alternativa que Python proporciona a la tecnología que está utilizando actualmente.

  • compositor -> pip
  • mod_php -> mod_wsgi
  • nginx + php-fpm -> nginx + uwsgi + uwsgi_python
  • daemon.io -> tornado, retorcido
  • Marco Zend -> Django
  • Phalcon -> halcón

Conclusión


¿Cómo sabes si lo necesitas o no?

  • Usted cree que cuanto más fuerte sea la escritura, mejor.
  • Prefieres un lenguaje que presente una arquitectura bien organizada.
  • Eres perfeccionista, la diversidad excesiva te molesta.
  • Los puestos de trabajo de Python en su ciudad parecen más prometedores (o se ha aburrido de desarrollar solo portales web).
  • Desea que su lenguaje de programación principal sea adecuado para desarrollar cualquier tipo de software (teniendo en cuenta las restricciones razonables relacionadas con la escritura dinámica).
  • No le gusta el nivel de habilidad de los desarrolladores junior (debido a la curva de aprendizaje relativamente baja).

Mi manera de aprender Python


Si eres un desarrollador experimentado, necesitarás hasta tres semanas para aprenderlo sin esforzarte demasiado.

  • Primera semana : Lea Inmersión en Python , capítulos 2-7. Puede revisar brevemente otros capítulos, prestando atención solo a los puntos interesantes. Al mismo tiempo, completa 10 tareas con el Proyecto Euler . Finalmente, cree una utilidad de consola que acepte parámetros. Puede portar cualquiera de sus scripts de bash anteriores o crear un análogo de ls desde BusyBox , o algo nuevo. El punto es que el script debe hacer algo útil, algo que haces con frecuencia. Por ejemplo, porté mi utilidad PHP que puede mostrar datos en la memoria caché.
  • Segunda semana : crea un análogo simple de Medium en Django y arma en cualquier hosting. Tenga en cuenta los componentes: registro, inicio de sesión, recuperación de contraseña, compartir publicaciones y comentarios y eliminarlos, verificando los permisos para acciones.
  • Tercera semana : seleccione una empresa para la que le gustaría trabajar, envíeles su CV solicitando una tarea de prueba de Python para evaluar sus habilidades.

Buena suerte

Source: https://habr.com/ru/post/es436180/


All Articles