Vous êtes ici : Accueil Tutoriels Débuter Python lorsque l'on vient de PHP

Débuter Python lorsque l'on vient de PHP

PHP est un langage publié sous licence open-source dès 1995, spécialement créé pour répondre à des problématiques concrètes pour des sites web en étant guidé par la volonté d'être accessible au plus grand nombre. D'abord impératif, il lui a été adjoint une sémantique objet. Bien qu’extrêmement différent de Python, PHP partage divers points communs: il est de haut niveau, dynamiquement typé et bien que chaque problématique interne au langage soit traitée totalement différemment, pour le développeur qui utilise le langage des ressemblances permettent de passer de l'un à l'autre sans trop de difficultés. Cet article ne cherchera pas à faire une évaluation de Python versus PHP, mais d'aider des développeurs PHP débutants ou confirmer à faire leurs premiers pas en Python grâce à des analogies. On ne parlera que de Python 3, bien que Python 2.7 soit encore très utilisé (du moins au moment de la rédaction de cet article).

Introduction

La première chose à faire, lorsque l'on commence avec Python, est de l'installer. La démarche est détaillée dans le livre "Python, les fondamentaux du langage", aux éditions ENI.

Bien que beaucoup de développeurs PHP l'ignorent (n'en ayant pas besoin), il existe une console PHP. Pour cela, il suffit de se rendre dans une console système et de taper :

$ php -a

En Python, le passage par cette console est un excellent moyen de tester le langage et de faire ses premiers pas. Pour ouvrir une console Python, il suffit de se rendre dans une console système et de taper :

$ python

Entrons donc dans le vif du sujet avec la création de quelques variables.

Variables

Considérations techniques

En PHP, une variable est caractérisée par le caractère $ suivi du nom de la variable. Techniquement, il s'agit d'un pointeur vers une structure C qui est celle-ci:

struct {
    union {
        long lval;
        double dval;
        struct {
            char *val;
            int len;
        } str;
        HashTable *ht;
        zend_object_value obj;
    } value;
    zend_uint refcount;
    zend_uchar type;
    zend_uchar is_ref;
} zval;

Ainsi, chacun des 8 types de variables PHP peut se représenter à l'aide d'une seule et même structure. Un de ces 8 types est l'objet. Il y a donc une distinction entre type et objet et, bien entendu, il peut y avoir autant de classe que possible, celles-ci représentant un type d'objet, en quelque sorte.

La grande différence pour Python est qu'il n'y a pas de types. Tout est objet. Par conséquent, les entier, flottant, chaîne de caractères, etc.. sont aussi des objets et le mot type désigne le nom de la classe d'un objet.

Similitudes entre PHP et Python

Certes, cette différence est importante à connaître, mais dans la pratique, la différence n'est pas importante. Voici un tableau comparant la déclaration de variables :

TypePHPPython Commentaires
Entier$entier = 1;entier = 1
Flottant$flottant = 1.0;flottant = 1.0
Chaîne de caractères$chaine = 'chaîne';chaine = 'chaîne'En Python, il n'y a pas de différences entre simples et doubles quotes.
Tableau numérique
/ Liste
$liste = array(42);liste = [42]La syntaxe raccourcie existe également pour PHP à partir de PHP 5.4
Tableau associatif
/ Dictionnaire
$dictionnaire = array('clé' => 'valeur');dictionnaire = {'clé': 'valeur'}Même remarque qu'au dessus.

En plus des commentaires du tableau, on note simplement le fait qu'en Python, le point virgule n'est pas obligatoire en fin de ligne. Pour le reste, on retrouve des similitudes fortes.

Autres types basiques apportés par Python

L'utilisation de ces types seuls permet de faire beaucoup de choses, mais Python offre étalement quelques autres outils, parmi lesquels :

TypeDéclaration Commentaires
Ensembleensemble = {42}Permet de bénéficier des outils ensemblistes (union, différence, ...), peut s'utiliser comme une liste non ordonnée et automatiquement dédoublonnée.
N-upletnuplet = (42,)Peut ressembler au premier abord à une liste, mais en est très différent, en particulier sur le plan sémantique.Il est utilisé lorsque la signification de l'ordre des éléments a une signification particulière comme l'on veut représenter un point dans le plan ou dans l'espace par exemple (le premier élément est X, le second Y et le dernier Z). En PHP, on utiliserait un array pour cela.
Octetsoctets = b'octets'Python fait une différence entre la chaîne de caractère et l'octet. Une chaîne de caractère est en unicode. PHP n'a pas encore réussi sa transition vers l'unicode, mais elle est à l'étude.

Utilisation des variables

L'utilisation d'opérateurs entre Python et PHP est identique à l'exception du fait que pour la concaténation, on utilise += en Python là où l'on utilise .= en PHP (alors que += en PHP a une tout autre signification et n'est quasiment jamais utilisée). Les syntaxes pour l'utilisation de ces opérateurs sont exactement identiques, à l'exception du caractère $ devant le nom des variables et le point-virgule en fin de ligne, comme auparavant.

Par contre, dès que l'on veut faire des manipulation sur les variables, il faut de préférence penser objet avec Python. Par exemple :

$s = str_replace($s, 'recherché', 'remplacement');

Pour réaliser la même chose en Python, il faudra préférentiellement écrire :

s = s.replace('recherché', 'remplacement')

il est cependant possible d'écrire ceci (si c'est plus facile pour vous) :

s = str.replace(s, 'recherché', 'remplacement')

En réalité, il s'agit d'un appel statique d'une méthode de la classe str qui est la classe des chaînes de caractères. On reviendra sur cet aspect dans le chapitre sur le modèle objet.

La plupart des fonctions PHP permettant la manipulation des types de données ont un équivalent en Python qui porte un nom très similaire. Python propose également des outils supplémentaires relativement puissants (voir le livre "Python, les fondamentaux du langage", aux éditions ENI au chapitre 9 qui y est dédié).

Synthèse

Comme pour PHP, les variables sont dynamiquement typées, c'est à dire que la valeur porte le type et qu'il n'est pas nécessaire de le déclarer en amont. De plus, une variable peut être réaffectée avec une valeur d'un type différent 

$a = 1; $a = 'chaîne'; // PHP
a = 1; a = 'chaîne' # Python

On en profite pour signaler que les commentaires en Python débutent par # en lieu et place de // et qu'il n'y a pas de commentaires multi-lignes (comme avec /* */ en PHP).

Maintenant que l'on a fait ce petit tour d'horizon, il est temps d'aller écrire quelques routines

Dans la plupart des cas, l'apprentissage d'un type Python lorsque l'on connaît un type PHP est assez aisé. Dans un premier temps, on peut développer en Python comme on développe en PHP, à l'exception du fait qu'il faut penser objet, et dans un second temps, avec la pratique, on pourra apprendre à tirer parti de tous les types standard de Python

Routines

Conditions

L'expression de condition entre PHP et Python ne change pas beaucoup. Pour s'en convaincre, voici un exemple simple en PHP :

if ($a === null) {
    echo 'Cas 1';
} elseif ($a == 0) {
    echo 'Cas 2';
} else {
    echo 'Cas 3';
}

Voici le même code en Python 

if a is None:
    print('Cas 1');
elif $a == 0:
    print('Cas 2)';
else:
    print('Cas 3');

Les différences évidentes sont celles-ci: Le mot clé elseif est remplacé par le mot-clé elif, le mot clé null est remplacé par le mot-clé None et l'entrée dans un bloc ne se fait pas à l'aide des traditionnelles parenthèses communes à tant de langages, mais avec le caractère deux-points et par le fait que l'indentation augmente. Ainsi, il est obligatoire de respecter une bonne indentation pour un code correct, ce qui peut paraître déroutant si l'on est pas habitué mais qui est garant d'une bonne lisibilité (ne pas utiliser de tabulations de préférences, mais en tous les cas ne pas mélanger tabulations et espaces). A noter qu'il n'y a pas besoin de parenthèses pour isoler la condition placée entre le mot clé et l'entrée dans le bloc.

De plus, il n'y a en Python qu'une comparaison forte (équivalente au === de PHP) puisque le langage Python est fortemente typé. Par contre, il y a une comparaison entre le fait que deux variables soient identiques (et non pas égales) à l'aide du mot-clé is.

En effet, en Python, certains types de variable ont une représentation en mémoire figée et qui ne peut changer. Pour illustrer ceci, voici un exemple :

a = None; b = None; c = None

les trois variables pointent vers la même zone mémoire. Ainsi, elles sont identiques. Il en est de même lorsque l'on utilise True ou False (notez la majuscule, contrairement à PHP où ces deux éléments sont écrits en minuscules).

Enfin, pour terminer, on a vu au passage que pour écrire quelque chose, là ou PHP utilise echo qui est une instruction (sans parenthèses), Python utilise print qui est une fonction (avec parenthèses).

Il y a donc beaucoup de subtilités, mais dans l'esprit les deux codes se ressemblent. Notons également qu'il n'y a pas de structure swicth / case / default en Python. Il faut à la place utiliser if / elif / else à la place, puisque cela permet exactement la même chose. Cela provient de la volonté de Python de ne pas avoir deux façons de répondre à une seule problématique.

Itérations

Avec PHP, la principale manière d'itérer est celle-ci :

foreach($arr as $a) {
    block
}

Il s'agit donc de parcourir une liste. En Python, cela se fait ainsi :

for a in arr:
    block

PHP travaille en réalité avec des tableaux numériques. Il devient alors simple d'avoir l'indice de chaque élément d'une liste :

foreach($arr as $i => $a) {
    block
}

En Python, on fait intervenir un générateur qui va créer cet indice :

for i, a in enumerate(arr):
    block

Étant donné la nature des types de PHP, le même moyen que précédemment est utilisé pour itérer à travers un tableau associatif :

foreach($arr as $key => $value) {
    block
}

En Python, il est nécessaire d'utiliser une méthode du dictionnaire (équivalent aux tableaux associatifs de PPH :

for key, value in arr.items():
    block

On a également le choix de n'itérer que sur les valeurs (ce qui est possible en PHP) :

for key, value in arr.values():
    block

Ou que sur les clés (ce qui n'est pas possible en PHP, on itère sur les clés ET les valeurs) :

for key, value in arr.keys():
    block

Enfin, l'autre moyen d'itérer en PHP est l'utilisation des mots-clés for ou while. L'utilisation de ces mots-clés est interchangeable et permet de faire la même chose avec des syntaxes différentes. En Python, toujours par la volonté de ne pas avoir deux façons différentes de faire la même chose, il n'y a que le mot clé while. Il fonctionne comme pour PHP, à la différence près (toujours la même) de la syntaxe d'un bloc avec les deux-points et l'indentation ainsi que l'inutilité en Python de mettre une condition entre parenthèses.

Enfin, pour terminer, il faut noter qu'en PHP on peut itérer dans des tableaux ou dans des objets implémentant une interface particulière. En Python, il en est de même, puisque l'on peut itérer dans n'importe quel objet qui présente une méthode spéciale dédiée (sans entrer plus dans les détails).

Définition d'une fonction

En PHP, définir une fonction se fait ainsi :

function nom_de_la_fonction(param1, param2) {
    block
}

En Python, outre les différences déjà vues (nature d'un bloc), il n'y a que le mot clé qui change :

def nom_de_la_fonction(param1, param2):
    block

L'appel d'une fonction parfaitement identique entre les deux langages.

Une différence est qu'en Python, une fonction est un objet comme un autre, au même titre qu'une instance d'une classe quelconque, d'un entier ou d'une chaîne de caractères. Elle peut donc être utilisée ainsi et donc éventuellement passée en paramètres. Ceci ouvre des voies vers la programmation fonctionnelle, mais dans les premiers temps, ne pas le savoir ne pose pas de problèmes. Il faut juste ne pas être surpris si on lit un code qui utilise ce genre de pratique.

La programmation fonctionnelle n'est pas le seul apport de Python sur l'écriture et l'utilisation de fonctions. Python permet en effet d'avoir des signatures de fonction complexes, peut utiliser des paramètres nommés et autorise même à définir une fonction de telle manière à ce qu'on oblige à nommer un paramètre lors de l'appel.

La maîtrise de ces concepts n'est pas un pré-requis pour utiliser Python, mais elle peut ouvrir des pratiques de développement résolument innovantes

Modèle objet

Définition d'une classe

Globalement, Python offre un choix plus large concernant les possibilités du modèle objet. Utilisé simplement, il ne pose pas de problèmes particulier, par contre il permet d'aller très loin et en ce cas, nécessite d'avoir de solides connaissances théoriques et de s'accrocher un peu. Sans entrer dans des détails qui peuvent être complexe, il va être montré ici comment faire la même chose en Python qu'en PHP. Pour cela, voici un exemple PHP assez complet :

class A
{
    const CONSTANTE = 'constante';

    public $attr_pub = 1;
    private $_attr_priv = 2;

    static $attr_static = 'Statique';

    public function __construct($a, $b) {
        $this->attr_pub = $a;
        $this->_attr_priv = $b;
    }

    public function func_pub() {
        echo 'fonction publique';
    }

    private function _func_priv() {
        echo 'fonction privée';
    }

    public function getConstante() {
        return static::CONSTANTE;
    }

    public static function getConstante() {
        return static::CONSTANTE;
    }

    public static function getStatique() {
        return static::$attr_static;
    }
}

Vous noterez que le code livré est du PHP 5.3 minimum et que l'utilisation du mot clé static pour faire de l'objet propre en PHP est indispensable (je ne parlerais pas des traits, bien qu'ils me semblent une bonne méthodes pour faire ce que le multi-héritage permet de faire). Voici la même classe en Python :

class A:
    CONSTANTE = 'constante'

    attr_pub = 1
    _attr_priv = 2

    attr_static = 'Statique'

    def __init__(self, a, b):
        self.attr_pub = a
        self._attr_priv = b

    def func_pub(self):
        print('fonction publique')

    def _func_priv(self):
        print('fonction privée')

    def getConstante(self):
        return self.CONSTANTE

    @classmethod     def getStatique(cls):
        return cls.attr_static

Listons les différences :

  • il n'y a pas de notion de public / privé ni pour les attributs ni pour les méthodes ; le développeur sait si une méthode est publique ou privée au regard des règles de nommage de la méthode (identiques à celles de PHP sur ce point) : si la méthode commence par le caractère soulignée, elle est privée ou protégée ; une alternative existe en Python pour réaliser ceci à l'aide des property, si l'on veut aller plus loin sur le sujet ;
  • une constante est traitée en Python comme une variable, à l'exception de la règle de nommage ; il est également possible d'utiliser les property pour retrouver un comportement similaire à celui de PHP ;
  • une méthode porte self comme premier argument ; il a le même rôle que $this, mais il ne relève pas d'un quelconque code magique, il provient du fait que l'appel de méthode lie le premier argument à l'instance ; par usage, on utilise self, mais on pourrait vouloir appeler cette variable comme bon nous semble ;
  • le fait qu'une méthode soit statique ne dépend pas d'un mot clé, mais de la manière dont la méthode est écrire à l'aide du décorateur classmethod ; en Python, il s'agit de méthode de classe et non pas de méthode statique ; une méthode statique, pour Python, est une méthode qui n'interfère absolument pas avec la classe, un peu comme s'il s'agissait d'une fonction indépendante rajoutée à la classe ;
  • alors que la méthode d'instance (méthode classique) a pour permier argument l'instance de la méthode, une méthode de classe a pour premier argument la classe de la méthode (usuellement nommé cls)alors que la méthode statique n'a pas de premier argument attribué ;
  • le constructeur,en PHP, est __construct alors qu'il se nomme __init__ en Python ; au passage, les méthodes magiques en PHP commencent par deux caractères soulignés alors qu'en Python, elles commencent ET terminent par ces mêmes caractères.

Ceci nécessite un petit temps d'adaptation, mais n'est pas non plus une révolution tant que l'on écrit des classes simples. L'utilisation des décorateurs est également une nouveauté et quelque chose qui peut déstabiliser dans un premier temps. En réalité, ceci :

@decorateur
def ma_fonction():
    block

est équivalent à ceci :

def ma_fonction():
    block

ma_fonction = decorateur(ma_fonction)

Il s'agit donc d'une fonction qui prend en paramètre une autre fonction et la renvoie transformée. Ce concept est étonnant au premier abord, mais lorsqu'on le maîtrise bien, il permet d'être extrêmement efficace.

Enfin, pour terminer, voici un héritage :

class B extends A
{
}

Et voici l'équivalent en Python :

class B(A):
    pass

La syntaxe est minimaliste, mais efficace. Ce qui me permet de glisser le fait que le mot-clé pass est celui que l'on utilise pour marquer un bloc (ce qui est toujours obligatoire) alors même que ce bloc ne fait rien.

Création d'une instance

En PHP, pour créer une instance, il suffit de faire ceci :

$instance = new A();

On utilise alors le mot clé new qui va réaliser la construction de l'instance avant de passer la main au constructeur de l'instance pour une phase que l'on peut appeler l'initialisation (le mot constructeur est donc mal choisi, quelque soient les langages). Il y a donc une construction en deux étapes, la première étant totalement gérée par le coeur de PHP.

En Python, il n'y a pas de mot-clé. Le fait d'accoler des parenthèses à une variable représentant une classe crée une instance. Là aussi, il y a deux étapes qui sont la construction de l'instance et son initialisation. En Python, la construction passe par l'appel de la méthode __new__ pour la construction (sur laquelle on a donc la main) puis par l'appel de la méthode __init__ pour l'initialisation. La première phase ne sert que très rarement, lorsque la structure de la classe a besoin d'être modifiée (méta classes ou singleton, par exemple), mais elle a le mérite d'exister et de résoudre simplement bien de problèmes d'architecture hautement complexes.

Voici donc, en Python, la création d'une instance :

instance = A()

Pour une utilisation basique de l'objet, Python reste simple et largement abordable. Cependant, l'absence du mot-clé new peut perturber. Il faut garder à l'esprit qu'en Python, c'est le type d'un objet qui compte, puisque la grammaire du langage ne choisit rien du comportement, elle se contente de renvoyer vers des méthodes des objets et ainsi de définir pour chacun ce que signifie tel opérateur ou l'utilisation de parenthèses. C'est le même principe qui permet de surcharger les opérateurs (redéfinir leur comportement) ou de créer des classes qui sauront les utiliser.

Ce petit apperçu du modèle objet de Python permet donc de voir qu'il reste abordable lorsque l'on connaît déjà bien PHP, de soulever les principales différences qui peuvent, au premier abord, surprendre et enfin d'ouvrir vers les possibilités que Python apporte.

Organisation du code

Ce dernier chapitre a pour but de revenir au concret, après avoir détaillé le technique.

En effet, PHP n'est pas fait pour être utilisé en console, il est fait avant tout pout le web. Ainsi, PHP est un langage, mais il est aussi un outil qui permet d'avoir à sa disposition une requête (avec les données dans le GET et dans le POST, la session, ...) afin de pouvoir créer une réponse (HTML, codes HTTP, fichier généré, ...).

Python n'est qu'un langage de programmation. Cependant, il permet de faire du web, parmi beaucoup d'autres utilisations possible (embarqué, système, interface graphiques, ...). J'en veux pour preuve que beaucoup d'articles de GLMF traitent d'embarqué et qu'une bonne partie des applications graphiques sous Linux sont écrites en Python. Pour pouvoir faire du Web, il faut donc utiliser un framework.

Il existe des frameworks web aussi développés que ce que propose Zend Framework, Symfony ou Cake PHP et aussi structurant pour le code, mais il existe également de tout petits frameworks spécialisés, comme bottle.py

Ainsi, ce sont eux qui permettront l'écriture d'applications, qui mettont à disposition du développeur les objets requêtes, session, etc.. et qui permettront la construction d'une réponse.

Python permet d'écrire du code qui sera le serveur Web. Le même code pourra être utilisé directement par Apache (ou autre) via WSGI. De la même manière, PHP est fait pour tourner sur Apache (ou autre) et PHP 5.4 introduit un serveur indépendant à des fins de développement et non de production.

Pour aller plus loin avec Python avec la réalisation d'une application web, je vous invite donc à tester au choix bottle.py, Pyramid, Turbogears ou Grok. Il faut cependant avoir à l'esprit qu'il faut une bonne maîtrise de Python pour certains d'entre eux

Mots-clés associés : ,
Spinner