Il mio rapporto con il linguaggio Python è un matrimonio d’interesse. Lo uso perché nella mia fattispecie lavorativa credo sia la scelta più furba (più facile trovare programmatori Python che programmatori Ruby). Non lo amo, ma lo rispetto profondamente.

Tuttavia, avendo un (arrugginito) background Ruby di un certo spessore, ci sono cose che, tutte le volte che le incontro, mi fanno storcere la bocca e tappare il naso. In breve, Python mi sembra rozzo e molto più a “basso livello” di quello che si vorrebbe far credere.

Faccio un elenco brevissimo di quelle cosette che mi disturbano, per poi alla fine fare un concreto esempio. Premetto che so bene che questi non sono difetti, ma particolarità di un linguaggio che in onore della coerenza ha fatto delle scelte che, beh l’ho già detto, non mi piacciono.

  • I builtin. Mi spiace, ma non riesco a pensare al Python come un linguaggio puramente a oggetti
  • Il self come parametro esplicito
  • __init__ che è un metodo come tutti gli altri, ma anche no
  • Il fatto che esistano le classi “new style”, che inficia tra le altre cose il comportamento di super()
  • Il super(), concetto piuttosto importantino nella OO, il cui comportamento non è mica scontatissimo
  • L’ereditarietà, con effetti collaterali poco intuitivi. Vi pare elegante, poi, una cosa di questo tipo? super(AppdateHTTPRetriever, self).__init__()
  • Il modo esplicito per fare setters e getters dinamici (che dovrebbero invece essere impliciti), ovvero le property
  • Certe curiose caratteristiche dello scoping globale delle variabili
  • Il pass, che mi fa abbastanza ridere (Matz take on that)
  • la nausea da __ __ __
  • hasattr e has_key, che, oltre alla non consistenza del nome, uno è un builtin e uno è un metodo (sì, uno è per gli oggetti e uno è per i dizionari, ma allora vedi punto 1)

Ed ora un esempio.

Problema: data una directory dove risiedono dei “bot”, creare uno script che li esegua tutti uno ad uno. Ogni bot non è altro che una classe, che va dinamincamente istanziata ed eseguito il metodo “run” sulla stessa (la classe ha lo stesso nome del file Bot).

Fornisco due soluzioni, una in Python e una in Ruby. Quale vi sembra più leggibile?

Python:

# Richiede __init__.py nella directory dei bot
import glob, os
for filename in glob.glob("bots/Bot_*.py"):
  classname = modulename = os.path.splitext(os.path.split(filename)[-1])[0]
  package = filename.replace("/", ".")[:-3]
  mod = __import__(package)
  bot = mod.__dict__[modulename].__dict__[classname]()
  if hasattr(bot, "run"):
    bot.run()

Ruby:

Dir.glob('bots/Bot_*.rb').each() do | file |
  require file
  classname = file.split('/')[1].gsub('.rb','')
  bot = Object.const_get(classname).new()
  if (bot.methods.include?('run'))
    bot.run()
  end
end