Hallo allerseits!
BlackJack hat geschrieben:Michael Schneider hat geschrieben:Wenn man nicht unbedingt eine Liste erwartet, kann man sich das auch offen halten, indem man das Naming für allgemeine Objekte verwendet (Cap-Case).
Du meinst kleinbuchstaben_mit_unterstrichen.
Nein, ich meine CamelCase, Entschuldigung.
BlackJack hat geschrieben:Trotzdem kann man den Typ eines ganz speziellen Objekts festlegen und den Namen in seinem Code entsprechend gestalten.
Du legst damit keinen Typ fest. Man kann trotzdem weiterhin alle möglichen Typen an den Namen binden. Fehler findet man nur wenn man den Code testet.
Du legst den Typ fest im Sinne einer Definition. Wenn Du die weitere Funktionalität nur gewährleisten willst, wenn eine Liste gegeben ist, dann kannst Du das so implizit machen oder/und es explizit im Docstring angeben.
BlackJack hat geschrieben:BlackJack hat geschrieben:zu 2) Damit hast Du ein komplett anderes Objekt und damit auch die Bedeutung verändert. Das sollte sich natürlich auch im Namen wiederspiegeln.
Richtig. Und was meinst Du dann mit:
wenn man den Typ mal ändern sollte und nicht die Namen anpasst.
Wenn ich in meiner Funktionsdefinition durch das l-Präfix angebe, dass ich ein Objekt erwarte, welches die Listen-Schnittstelle unterstützt, dann kann das entsprechend "Duck Typing" auch jedes Objekt sein, das das gewährleistet.
Es kann in 99,9% der Fälle aber auch ein Objekt sein, dass das *nicht* gewährleistet.
99,9% finde ich etwas übertrieben. Was meinst Du mit "kann sein"? Letztlich muss jeder selber wissen, was er für ein Objekt übergibt. Ich habe definiert, dass ich eine Liste erwarte und gehe nachfolgend davon aus, dass ich die damit verbundene Funktionalität zur Verfügung habe.
BlackJack hat geschrieben:In den allermeisten Fällen reicht Indexzugriff oder auch nur "iterierbar sein" völlig aus. Mit dem 'l'-Präfix wird viel zu viel gefordert und damit läuft es dem Duck-Typing zuwieder. Wenn ich das 'l' sehe weiss ich nicht was *wirklich* erwartet wird.
Wenn ich keine Liste erwarte, sondern ein iterierbares Objekt, dann schreibe ich auch kein l davor. Denn dann ist es mir egal, solange ich über die Elemente in einer for-Schleife iterieren kann.
BlackJack hat geschrieben:Wie gesagt, wenn man sich nicht sicher ist, ob ein Wert vom Typ float oder int ist, muss man das Präfix nicht davorsetzen. Das ist für die Variablen bestimmt, die einen festgelegten Typ haben sollen.
Das sollen Variablen aber im allgemeinen nicht, sondern "nur" ein entsprechendes Verhalten.
Es ist ein Hinweis zugunsten der besseren Lesbarkeit. Ob die gewünschte Eigenschaft eines Integer Objekts nun vom Objekt hinter Referenz "iCounter" oder "Counter" nicht erfüllt wird, ist doch nebensächlich.
Von mir aus kann hinter iCounter jedes Objekt stehen, das die angedeutete Funktionalität erfüllt.
BlackJack hat geschrieben:BlackJack hat geschrieben:zu 3) Das eine nicht vorhandene Methode aufgerufen wird, kann man nur zur Laufzeit feststellen, egal wie der Name aussieht. Das findet man durch Tests, die man sowieso machen muss, weil kein Name garantiert das bei `lNamen` *wirklich* eine Liste an den Namen gebunden ist.
Das sieht man dann aber schon bei der Zuweisung, z.B.
Ich seh' das nicht. Das kann funktionierender Quelltext sein, der einfach nur die "falschen" Namen hat.
Und wenn man sich auf die Info im Namen verlassen will, muss man genau da stutzig werden. Natürlich ist diese Zuweisung möglich, aber sie ist formal falsch, weil die Methode Split eben definitiv eine Liste zurückgibt und durch den Namen "sNamen" eine Fehlinterpretation auftreten kann.
Wenn man sich auf die Funktionalitätsandeutung durch Präfix einlässt, dann darf man diese Liste nicht dem Namen sNamen zuweisen.
Das ist genau dasselbe, als wenn ich sie dem Namen "Zufallszahl" zuordne, der ebenfalls eine Fehlinterpretation provoziert.
BlackJack hat geschrieben:Nochmal: es geht darum, einen neuen Code zu überfliegen und dort systematisch auf erste Fehler aufmerksam zu werden. Z.B. bei Anfragen hier im Forum, wo man nicht immer die Möglichkeit hat, gleich zu testen.
Gerade bei solchem Quelltext würde ich nicht darauf vertrauen das die Namensgebung stimmt, oder vielleicht nicht noch von früheren Tests mit anderen Objekten die "falschen" Namen da stehen. Wenn man nicht testet, kann man nur raten.
Gerade diese Präfixe helfen dabei, systematisch vorgehen und alle Zuweisungen und Erwartungen auf Richtigkeit zu prüfen, da man sie getrennt bewerten kann.
BlackJack hat geschrieben:Aber das später in jedem Fall die volle `list()`-API vorhanden soll, weisst Du immer? Einfach ein 'l' davor zu pappen ist auch eine Möglichkeit sich ums Gedanken machen zu drücken.
Es ist eine Definition um einen Ausgangspunkt zu schaffen.
BlackJack hat geschrieben:Auf die Gefahr hin, dass ich mich wiederhole: wenn man sich nicht festlegen will, braucht man das nicht zu tun!
Wenn Deine Fehlersuchmethode auch nur halbwegs funktionieren soll, muss man das überall tun wo's nur geht.
Eben, wo es geht. Und das ist da, wo ich weiß, dass bei einer Zuweisung eine Liste, ein Tupel oder sonst was zurückgegeben wird!
Die Methode ist nicht vorrangig zum Suchen von Fehlern gedacht, sondern zum besseren Verständnis, wenn man sich nur einen kleineren Teil des Codes betrachtet.
Und wenn Du einen Namen "lNamen" hast und sollst das 5. Element angeben, dann ist es doch zweifellos intuitiver, als wenn Du nicht weißt, dass Du Listenfunktionen anwenden kannst.
BlackJack hat geschrieben:BlackJack hat geschrieben:Was Du da so ein bisschen über Namenskonvention einführen willst, ist statische Typinformation.
Für mich ist das dasselbe, nur in grün. Von mir aus nennen wir es Typinformation.
Du willst statische Typinformation und wunderst Dich das Gegenwind von "Pythonistas" kommt!?
Was ich möchte, ist, den Code besser lesbar zu machen, WO ES GEHT.
BlackJack hat geschrieben:Wenn Du so in Typen denkst, dann willst Du nicht in Python programmieren. Python ist dadurch Python dass es nicht um den Typ von Objekten, sondern um das Verhalten von Objekten geht. Das ist "duck typing" und IMHO ein wesentlicher Bestandteil von Python.
Ganz meiner Meinung. Ich habe das Gefühl, dass ihr mich irgendwie falsch versteht und meine Regel typabhängiger seht, als sie ist. Was ich beabsichtige ... steht da oben.
EyDu hat geschrieben:Außerdem ist die Wartung des Codes durch solche zusätzlichen, teilweise kryptischen, Zusätze sehr aufwändig. Falls sich am Typ doch etwas ändern sollte ist man erst man am Refactoring.
Stimmt, es könnte sich ein Mehraufwand ergeben. Trotzdem zahlt sich die Typandeutung gerade beim Bugfixing und bei der Wartung aus, weil das häufig andere Programmierer sind, die vielleicht dankbar dafür sind, dass sie Dictionaries, Tupel und Listen auf den ersten Blick erkennen können. Im Prinzip könnte ich die Namen auch mit Dict..., Tuple... oder List... anfangen lassen, was aber wesentlich länger wäre.
EyDu hat geschrieben:Mir stellt sich ebenfalls die Frage, wie du die Notation bei eigenen Namen durchführst. Führst du Variablen welche eine Instanz von "Person" sind dann mit "pers" an, oder wie markierst du diese? Letztendlich muss man sich auch hierzu die Abkürzungen merken, was viel schwiriger ist als der Typ einer Variablen, vorallem da die Präfixe ja nicht standardisiert sind.
Bei mir sind sie standardisiert und ändern sich auch nicht. Mit l, d, t, i, ... sind sie sogar intuitiv. Namen für sonstige Objekte (auch eigene) sind nach PEP 8 CamelCase.
Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...