Python advice: Portability of introspective function call

14

In Python, you can use the dir function on any object to get a list of the names of its instance functions:

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

I'm wondering if this could be a useful golfing technique in a program than calls several lengthily named functions. In such a case, I could create a function selection function F:

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

Now suppose I have a string s and I want store the result of capitalizing its first letter in the variable c. Then instead of c=s.capitalize(), I could note that capitalize is at position 33 in the above list and do the following:

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

which assigns 'Abc' to c.

My question is whether this is likely to work most of the time. In particular,

  • Can I always count on the list being lexicographically sorted by ASCII values?
  • Are there many changes to list of available between minor versions?
  • Do differences exist between implementations?

Also, has anyone used this before on PPCG?

feersum

Posted 2014-11-02T06:10:40.850

Reputation: 29 566

I've seen similar things done with JavaScript and C#. – Peter Taylor – 2014-11-02T07:33:22.183

2You can also do this with builtins: dir(__builtins__). And here's an alternative function: F=lambda o,i:getattr(o,dir(o)[i]). – grc – 2014-11-02T12:45:53.547

Also note that depending on which functions you plan on using, you could add the () to the end of F like so: F=lambda o,i:eval('o.'+dir(o)[i])() Then c=F('abc',33) will assign 'Abc' to c. – FryAmTheEggman – 2014-11-02T17:38:22.650

Answers

6

From the documentation:

The resulting list is sorted alphabetically

As for the differences, I think you will have to check (and specifying in your answer is probably a good idea). There are clear differences between python 2 and 3, for example, __nonzero__ was renamed to __bool__.

I have never heard of any differences between implementations, but I can't find any references on this.

I don't think this has been used before in part because it will rarely save you any characters over doing something like:

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

You would need to use several different functions from dir() in order for this to be worth it.

FryAmTheEggman

Posted 2014-11-02T06:10:40.850

Reputation: 16 206