Conseil Python: Portabilité de l'appel de fonction introspectif

14

En Python, vous pouvez utiliser la dirfonction sur n'importe quel objet pour obtenir une liste des noms de ses fonctions d'instance:

>>> dir('abc')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__','__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

Je me demande si cela pourrait être une technique de golf utile dans un programme qui appelle plusieurs fonctions longuement nommées. Dans un tel cas, je pourrais créer une fonction de sélection de fonction F:

F=lambda o,i:eval('o.'+dir(o)[i])

Supposons maintenant que j'ai une chaîne set que je souhaite stocker le résultat de la mise en majuscule de sa première lettre dans la variable c. Ensuite, au lieu de, c=s.capitalize(),je pourrais noter que capitalizec'est à la position 33 dans la liste ci-dessus et faire ce qui suit:

s='abc'
c=G(s,33)()

qui attribue 'Abc'à c.

Ma question est de savoir si cela est susceptible de fonctionner la plupart du temps. En particulier,

  • Puis-je toujours compter sur la liste triée lexicographiquement par valeurs ASCII?
  • Y a-t-il de nombreux changements dans la liste des versions mineures disponibles?
  • Existe-t-il des différences entre les implémentations?

De plus, quelqu'un a-t-il déjà utilisé cela sur PPCG?

feersum
la source
J'ai vu des choses similaires faites avec JavaScript et C #.
Peter Taylor
2
Vous pouvez aussi le faire avec builtins: dir(__builtins__). Et voici une autre fonction: F=lambda o,i:getattr(o,dir(o)[i]).
grc
Notez également que selon les fonctions que vous prévoyez d'utiliser, vous pouvez ajouter le ()à la fin de la Fmanière suivante: F=lambda o,i:eval('o.'+dir(o)[i])()Ensuite c=F('abc',33), vous affecterez «Abc» à c.
FryAmTheEggman

Réponses:

6

De la documentation :

La liste résultante est triée par ordre alphabétique

Quant aux différences, je pense que vous devrez vérifier (et préciser dans votre réponse est probablement une bonne idée). Il existe des différences claires entre python 2 et 3, par exemple,__nonzero__ été renommé en __bool__.

Je n'ai jamais entendu parler de différences entre les implémentations, mais je ne trouve aucune référence à ce sujet.

Je ne pense pas que cela ait été utilisé auparavant en partie parce que cela vous évitera rarement de créer des personnages comme:

F=str.capitalize
s='abc'
c=F(s)

Vous auriez besoin d'utiliser plusieurs fonctions différentes dir()pour que cela en vaille la peine.

FryAmTheEggman
la source