Mit der Argumentation das ein Dateiobjekt ein Handle ist, ist *jedes* Objekt in Python ein Handle, also könnte man an jeden Namen `_handle` oder bei schlechten Abkürzungen `h` hinten anhängen. Wenn man das aber an jeden Namen anhängen kann, dann ist der Informationsgehalt davon gleich Null und man sollte den unnötigen Zusatz weg lassen, und so würde dann aus dem `input_file_handle` nur noch `input_file`. Also das was ein guter, passender Name ist.
Nochmal: `file` bricht keine Abwärtskompatibilität. Das das in Python 2 mal ein Datentyp war, ist in Python 3 Code nicht mehr relevant. Und ja, natürlich ist `file` sehr generisch, aber Du sagst es ja selbst: In dem Fall wird das genau zweimal in aufeinanderfolgenden Zeilen benutzt. Und es ist ein besserer, weil für mehr Leute auf Anhieb verständlicherer Name als das kryptische `ifh`.
Das Python 2 noch irgendwo verwendet wird, ich habe da noch Code der in einem Fall bis Python 2.4 zurück geht, weil auf dem Gerät wo das läuft, nichts aktualisiert werden kann, kann man bedenkenlos `file` verwenden. Der Zweck davon ist das man davon ableiten kann. Wird sehr selten gebraucht, und selbst wenn, dann eher nicht *in* einer Funktion in der man den Bezeichner vorher für ein Dateiobjekt verwendet hat.
Hier im Forum gehe ich von Code aus, der aktuelle CPython-Versionen verwendet. Also zumindest die älteste offiziell unterstützte Version. Und da ist Python 2 raus. Wenn dann jemand Probleme damit hat das auf einem älteren/alternativen Python zum laufen zu bringen, muss er das halt ansagen. Das halte ich auch für ein Strohmann-Argument, weil Du ja selbst sagst, dass Du Features benutzt die nach Python 2 eingeführt wurden. Entweder ganz oder gar nicht. Und dann bitte auch getestet, das es auf Python 2 *und* 3 läuft. Ach ja, und bitte auch all die Einschränkungen berücksichtigen wo PyPy, Jython, IronPython, nuitka, Bython, Shed Skin, und PyJS von CPython abweichen. Das muss natürlich auf allen gleich laufen. Haben wir MicroPython/CircuitPython noch vergessen? Bin auf Dein nächstes Codebeispiel gespannt.
Das was man mit `open()` & Co öffnet ist eine Datei. Und dafür gibt es den (Duck)-Typ `File` der das Konzept ”Datei” mit den Operationen repräsentiert. Und ein passender Name für so ein Exemplar ist `file`. Es ist kein Handle. Es enthält/kapselt eines. Es ist aber mehr als das, mehr als ein Wert den man als Stellvertreter an andere Funktionen übergibt. Das ist was ein Handle ist, ein passiver, opaker Wert ohne weitere Eigenschaften, den man als Stellvertreter für ein Objekt, das in einem anderen Namensraum verwaltet wird, übergeben kann. Also zum Beispiel das was `os.open()` zurück gibt. Wenn `file_handle` ein passender, generischer Name wäre, dann würde man den Datentyp dazu ja `FileHandle` nennen. Der heisst aber `File`, beziehungsweise als es den in Python 2 noch als *einen* konkreten Typ gab, hiess der `file`. Und nicht `file_handle` oder `FileHandle`. Ein `file_handle` wäre ein Attribut, ein Bestandteil von so einem Datentyp, aber eben nicht der Datentyp selbst.
Das ein Objekt ein informelles Protokoll unterstützt, ist doch nichts anderes als Duck-Typing. Wenn es läuft wie ein Dateiobjekt und quakt wie ein Dateiobjekt, dann ist es ein Dateiobjekt, oder eben zumindest ein dateiähnliches Objekt.
Mit `sort()` verstehe ich jetzt wieder nicht was Du damit eigentlich sagen willst, denn ja, das verändert die Liste und gibt deswegen nicht die Liste zurück. Das ist so gewollt und pythonisch. Dein `read_csv()` verändert das Objekt und gibt es zurück, was unpythonisch ist, denn hier sollte wie bei `sort()` nichts/`None` zurückgegeben werden.
Pandas verhält sich ebenfalls konform. Du kannst da gerne anderes behaupten, auch immer wieder, dadurch wird das aber nicht wahr. Zeig doch mal Beispiele. In dem verlinkten Artikel waren beispielsweise keine. Im Gegenteil, steht da sogar, dass man in dem fraglichen Fall dann kein „method chaining“ mehr machen kann, weil dann `None` zurückgegeben wird. Da es an der Stelle im jeweiligen Code trivial gewesen wäre ``return self`` statt ``return None`` zu schreiben, sollte man das als bewusste Entscheidung sehen, da keine unpythonische API anzubieten.