Consejo de Python: portabilidad de llamada de función introspectiva

14

En Python, puede usar la dirfunción en cualquier objeto para obtener una lista de los nombres de sus funciones de instancia:

>>> 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']

Me pregunto si esta podría ser una técnica de golf útil en un programa que requiera varias funciones con nombres largos. En tal caso, podría crear una función de selección de función F:

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

Ahora suponga que tengo una cadena sy quiero almacenar el resultado de poner en mayúscula su primera letra en la variable c. Entonces, en lugar de c=s.capitalize(),, podría notar que capitalizeestá en la posición 33 en la lista anterior y hacer lo siguiente:

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

que asigna 'Abc'a c.

Mi pregunta es si es probable que esto funcione la mayor parte del tiempo. En particular,

  • ¿Puedo contar siempre con que la lista se clasifique lexicográficamente por valores ASCII?
  • ¿Hay muchos cambios en la lista de disponibles entre versiones menores?
  • ¿Existen diferencias entre implementaciones?

Además, ¿alguien ha usado esto antes en PPCG?

Feersum
fuente
He visto cosas similares hechas con JavaScript y C #.
Peter Taylor
2
También puede hacer esto con órdenes internas: dir(__builtins__). Y aquí está una función alternativa: F=lambda o,i:getattr(o,dir(o)[i]).
grc
También tenga en cuenta que, dependiendo de las funciones que planee usar, puede agregarlas ()al final de la Fmisma manera: F=lambda o,i:eval('o.'+dir(o)[i])()luego c=F('abc',33)asignará 'Abc' a c.
FryAmTheEggman

Respuestas:

6

De la documentación :

La lista resultante se ordena alfabéticamente.

En cuanto a las diferencias, creo que tendrá que verificar (y especificar su respuesta probablemente sea una buena idea). Hay claras diferencias entre python 2 y 3, por ejemplo, __nonzero__se le cambió el nombre __bool__.

Nunca he oído hablar de diferencias entre las implementaciones, pero no puedo encontrar ninguna referencia al respecto.

No creo que esto se haya usado antes en parte porque rara vez te ahorrará algún personaje por hacer algo como:

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

Tendría que usar varias funciones diferentes dir()para que esto valga la pena.

FryAmTheEggman
fuente