Accueil > Code > Le Python, c’est bien. Mangez-en.

Le Python, c’est bien. Mangez-en.

Ce week-end, j’ai fait mes premiers pas en utilisant Python. J’avais évidemment entendu parler de nombreuses fois de ce langages au cours de diverses discussions et dans le domaine professionnel (notamment parce que je bosse avec Trac), mais je n’avais jamais mis les mains dans le cambouis pour voir quel tronche ça avait.

En lisant The Pragmatic Programmer, je suis tombé sur une recommendation du style « étudiez au moins un langage par an », et ça m’a motivé. Du coup, voilà. Et ben putain, j’aurais du faire ça plus tôt. C’est carrément ultime. Syntaxe simple, légère, peu capricieuse mais forçant la lisibilité, documentation bien foutue, tutos poussés vraiment intéressants, vitesse d’execution excellente, grande quantité de bibliothèques, …

Je me réjouis vraiment d’utiliser ça dans un contexte un peu plus serieux que dans ma petite sandbox. Allez, je suis sûr qu’il va bien falloir deux ou trois moulinettes à coder dans la semaine qui arrive… Histoire de me mettre dans le bain et de passer en revue le langage rapidement, j’ai réimplémenté un algo que l’on utilise sur Dofus pour la génération des noms de personnages, et qui est accessoirement ultra-connu: les chaînes de Markov.

Z’allez voir, c’est que du bonheur.

Et voilà :

from random import randint
 
class MarkovDictionary:
	"""Stores possible suffixes for a given prefix."""
 
	def __init__(self):
		"""Initialize an empty Markov dictionary."""
		self.dic = {}
 
	def getItem(self, key):
		"""Get the possible suffixes list for a given prefix."""
		return self.dic[key]
 
	def addItem(self, prefix, suffix):
		"""Add a possible suffix to a given prefix."""
		try:
			self.dic[prefix].append(suffix)
		except KeyError:
			self.dic[prefix] = [suffix]
 
	def getSuffix(self, prefix):
		"""Get a random suffix for a given prefix."""
		list = self.dic[prefix]
		return list[randint(0, len(list) - 1)]
 
class MarkovGenerator:
	"""Generate random words from a given words-list seed."""
 
	def __init__(self, initList, chunkSize = 3):
		"""Initialize the generator with a initial words list.
 
		The chunk size attribute define the size of a single
		chunk from a word inside the initial words list. Chunks
		are combined to create new words.
 
		In short, the larger the chunk size, the closer the
		generated words are to the initial list "spirit", but
		also tends to be sometime too close to it.
 
		"""
		self.initList = initList
		self.chunkSize = chunkSize
		self.dictionnary = MarkovDictionary()
 
		self.generateDictionary()
 
	def getRandomWords(self, maxTries = 100):
		"""Get a list of random words generated using the initial
		words list and the Markov algorithm.
 
		The list size isn't fixed, but is always smaller than
		the specified maxTries attributes.
 
		"""
		result = []
		counter = 0
 
		while len(result) < len(self.initList) and counter < maxTries:
			counter += 1
			prefix = " " * self.chunkSize
			name = ""
 
			while True:
				suffix = self.dictionnary.getSuffix(prefix)
				if suffix == "\n":
					break
				else:
					name += suffix
					prefix = prefix[1:] + suffix
 
			if not name in result and not name in self.initList:
				result.append(name)
 
		return result
 
	def generateDictionary(self):
		"""Generate a dictionary from the initial words list."""
		for nameIndex in range(len(self.initList)):
			name = self.initList[nameIndex]
			chunk = " " * self.chunkSize
			chunk += name
 
			for charIndex in range(len(name)):
				prefix = chunk[charIndex : charIndex + self.chunkSize]
				suffix = chunk[charIndex + self.chunkSize : charIndex + self.chunkSize + 1]
				self.dictionnary.addItem(prefix, suffix)
 
			self.dictionnary.addItem(chunk[len(name) : len(name) + self.chunkSize], "\n")

Et pour l’utiliser, c’est tout con :

from markov import MarkovGenerator
 
# Reading the initial dictionary
f = open('../assets/names.txt', 'r')
initialList = []
for line in f:
    initialList.append(line.strip())
f.close()
 
generator = MarkovGenerator(initialList)
print generator.getRandomNames(100)

En guise de liste de noms, j’ai utilisé la liste des noms des cyclones tropicaux de l’Atlantique Nord, ce qui m’a donné des trucs rigolos: Hanny, Palomas, Gertha, Doria, Humbertha, Bert, … Cet algo est vraiment chouette. Si vous avez une liste de machins, essayez le dessus, c’est toujours drôle. Allez, salut.

Categories: Code Tags: , ,
  1. Totoro
    09/02/2009 à 10:22 | #1

    le Python c’est bon, mangeons en tous… :P

    Je ne conteste pas cette affirmation, bien au contraire. j’ai parcouru mes première lignes de Python via scons et cela a complètement changer ma manière de penser le processus de compilation. Mais dans « the pragmatic programmer », les auteurs ne faisait-il pas plutôt référence à une démarche de l’esprit ? Remettre en cause ces réflexes de programmation, qui sont assujettis au langage utilisé.

    Il me semble qu’il est utile d’expérimenter différents langages de programmation pour « casser » les réflexes de programmations que l’on forge au fil de son expérience. Je ne conteste pas l’expérience du développeur en l’occurrence. je constate simplement que cette même expérience nous enferme souvent dans des schémas de pensé nécessairement « étroits »-selon l’adage populaire, c’est en forgeant que l’on devient con comme un forgerons! :P ou, pour le dire plus élégamment, de toutes les habitudes, les bonnes ne sont-elles pas les pires ? Elles sont en tout cas les plus difficiles à perdre… -.

    Si le modèle de programmation impératif, cher à tous les langages de programmation « grand publique » est le plus intéressant, collectionner la connaissances des innombrables déclinaisons de ce même modèle me semble, in fine, une démarche assez stérile.

    Je distinguerais 5 paradigmes de programmations fondamentalement différents (Si d’aucun en a d’autres a proposer je suis preneur ! ) :

    - La programmation impérative : C’est la plus connue (la seule vraiment utilisée ?), elle est illustrée par les langages classiques : C, C++, C#, Java, C#, perl, Php, Python, Ruby, sont tous des langages impératifs, le plus souvent « orientés objets » mais « orienté objet ne signifie pas « à objet » (à mes yeux en tout cas).

    - La programmation Objet : les paradigmes de la programmation objets viennent de Simula, mais ils ont été magnifiés dans SmallTalk’80. J’ai étais émerveiller de redécouvrir ce qu’est un booléen et un flot de contrôle dans SmallTalk (amusez-vous a fabriquer une classe SomeTimes qui hérite de Boolean, au même titre que les classes True et False. Frissons Garantis!). Bien sur, sur le plan pragmatique, Il faut citer le langage Effeil, qui a extrait la notion de contractualisation de la programmation Objet. Notion prometteuse en terme de génie logiciel. Mes détracteurs pourront y ajouter Java, C++ et autre orienté objets s’ils y tiennent vraiment…

    - La programmation fonctionnelle : La programmation fonctionnelle, c’est un peu le « canal historique » de la programmation. Les langages à découvrir sont Lisp -A Lot of Insanity and Stupidous Parenthesis- Et ces descendants dont CAML et sa déclinaison « Orienté Objet » : OCAML sont les plus intéressants pour un usage pragmatique. le typage fonctionnel d’OCAML reste quelque chose de magique à mes yeux.

    - La programmation logique : Bon, avec la programmation logique on entre sur des terres étranges, dont bon nombre de developpeurs ne sont pas ressortis intacts. ici il faut oublier l’essentiel de ce que l’on crois savoir en bon informaticien « pragmatique ». Le point d’entrée le plus sur est le langage Prolog. Le pense que Prolog est l’un des langages les plus denses -on écrit peu de ligne de code- et le plus étonnant. On est jamais vraiment sur du résultat qu’on va obtenir, ce qui en programmation reste quand-même troublant. C’est surtout vrai avec Prolog 3 -Logique d’ordre supérieure et logique floue-, mais le frisson et garantis des les prémisses de l’apprentissage du langage. Bien que l’intention soit sensiblement différente, je range aussi dans cette famille des langages comme l’atelier B et ses avatars capables de produire un exécutable après raffinage -je n’y inclus donc pas PVS et autre système de preuve automatiques qui n’ont qu’une intention démonstrative-.

    - La programmation machine : Tous les autres langages ne sont-ils pas des ombres parcellaires, issues du langage de notre machine ? Parmi les langages machines les plus intéressant à découvrir il y a ceux des deux grandes familles, les SISCs et les RISCs. Mais je pense qu’il y a beaucoup à apprendre aussi des jeux d’instructions SIMPs -rêve de Cray et de masspar :P -. Ce sont sur ces fondations que la PS2 puis la PS3 reposent. Et pour moi cela explique l’exceptionnelle durée de vie de la PS2. Cela donne aussi la mesure du gouffre (inexploité) entre la PS3 et la XBOX360. Parceque les langages machines donnent la mesure opérationnelle de tout les autres langages, je les classes en tant que famille propre, pour laquelle je juge toujours utile d’expérimenter de nouvelles instances -celui des cartes NVIDA par exemple-.

    J’espère que tu t’amusera bien avec ces pistes de langages à expérimenté et il me tarde de lire un post de Prolog ou Smalltalk ! :-)

  1. Pas encore de trackbacks