Porada Python: Przenośność introspektywnego wywołania funkcji

14

W Pythonie możesz użyć dirfunkcji na dowolnym obiekcie, aby uzyskać listę nazw funkcji jego instancji:

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

Zastanawiam się, czy może to być przydatna technika gry w golfa, niż wywoływanie kilku funkcji o długich nazwach. W takim przypadku mógłbym utworzyć funkcję wyboru funkcji F:

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

Załóżmy teraz, że mam ciąg znaków si chcę zapisać wynik dużej litery w zmiennej c. Następnie zamiast c=s.capitalize(),zauważyć, że capitalizejest na pozycji 33 na powyższej liście i wykonaj następujące czynności:

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

który przypisuje 'Abc'do c.

Moje pytanie brzmi, czy prawdopodobnie będzie to działać przez większość czasu. W szczególności,

  • Czy zawsze mogę liczyć na sortowanie listy leksykograficznej według wartości ASCII?
  • Czy istnieje wiele zmian na liście dostępnych między mniejszymi wersjami?
  • Czy istnieją różnice między implementacjami?

Ponadto, czy ktoś używał tego wcześniej w PPCG?

feersum
źródło
Widziałem podobne rzeczy zrobione z JavaScript i C #.
Peter Taylor
2
Można również zrobić to z builtins: dir(__builtins__). A oto alternatywa funkcja: F=lambda o,i:getattr(o,dir(o)[i]).
grc
Zauważ też, że w zależności od funkcji, których zamierzasz używać, możesz dodać ()koniec na Fprzykład tak: F=lambda o,i:eval('o.'+dir(o)[i])()Następnie c=F('abc',33)przypisze „Abc” do c.
FryAmTheEggman

Odpowiedzi:

6

Z dokumentacji :

Powstała lista jest posortowana alfabetycznie

Jeśli chodzi o różnice, myślę, że będziesz musiał sprawdzić (a podanie w swojej odpowiedzi jest prawdopodobnie dobrym pomysłem). Istnieją wyraźne różnice między Pythonem 2 i 3, na przykład __nonzero__zmieniono nazwę na__bool__ .

Nigdy nie słyszałem o różnicach między implementacjami, ale nie mogę znaleźć żadnych odniesień na ten temat.

Nie sądzę, aby było to wcześniej używane częściowo, ponieważ rzadko pozwoli ci to uratować postacie przed zrobieniem czegoś takiego:

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

dir()Aby to było tego warte, musisz użyć kilku różnych funkcji .

FryAmTheEggman
źródło