Diverse Syntax Problemchen..

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ulipy: Das wäre `__new__()` und die Methode wird aufgerufen wenn man die Klasse aufruft. Und das alleine reicht schon. Eine Zuweisung ist zwar oft sinnvoll, aber nicht notwendig. Also bei ``instance = Class()`` kann man die Zuweisung auch weglassen — ``Class()`` ist der Teil der das neue Objekt erstellt. Mit dem sollte man dann irgend etwas machen. Oft einem Namen zuweisen, direkt oder indirekt. Also indirekt beispielsweise bei einem Aufruf übergeben, Beispiel ``print(Class())`` — da bindet man das ja nicht für sich selbst an einen Namen, aber innerhalb von `print()` wird das Objekt auch irgendwann an einen Namen gebunden werden müssen. Oder man bindet das Objekt selbst nicht an einen Namen, sondern es ist Teil einer literalen Datenstruktur, die dann vielleicht an einen Namen gebunden wird. Beispiel ``instances = [Class(), Class(), Class()]``. Und manchmal erstellt man Objekte auch nur als Teil eines Ausdrucks wo sie dann direkt ”verrechnet” werden, wobei das letztlich nur ein Sonderfall von Übergabe an eine Methode ist, denn letztendlich führen fast alle Operatoren zu Methoden. Beispiel: ``point = origin + Point(23, 42)`` was letztlich auf ``point = origin.__add__(Point(23, 42))`` hinaus läuft.

Hast Du eigentlich schon Programmiererfahrung? Falls ja in welcher Sprache oder Sprachen?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@ulipy,

ich würde mir mal dies durchlesen:
https://docs.python.org/3.9/reference/d ... ject.__new__

Mann kann den Prozess der Instanzerzeugung sichtbar machen indem man die beteiligten Methoden, die normalerweise im Hintergrund ablaufen, überschreibt und damit experimentiert:
Man sieht immer wieder Code-Beispiele in denen die __init__ Methode überschrieben wurde. Man kann die __new__, die vorher aufgerufen wird, aber auch überschreiben.
Dabei muss man aber auf den richtigen Rückgabewert achten, sonst stört man den Ablauf.

Code: Alles auswählen

class Example:
    def __new__(cls, *args, **kwargs):
        """ 
        Die __new__ Methode erzeugt eine Instanz der Testklasse
        Durch Übeschreiben kann man die Funktionalität, die norlmalerweise im Hintergrund abläuft,
        manipulieren:
        """

        print(f"Ist 'cls' eine Instanz der Klasse Test?: {isinstance(cls, Example)}")
        print(cls)
        # print(args)
        # print(kwargs)

        # Hier wird die neue Instanz nach dem Bauplan der Klasse erzeugt
        instance = object.__new__(cls)

        # und muss schließlich zurückgegeben werden um von der __init__ Methode verwendet zu werden
        return instance

    def __init__(self, *args,**kwargs):
        """ Initialisiert die neu erzeugte Instanz"""
        print(f"Ist 'self' eine Instanz der Klasse Test?: {isinstance(self, Example)}")
        print(self)
        # print(args)
        # print(kwargs)


e = Example("arg", b="kwarg")

"""
Ist 'cls' eine Instanz der Klasse Test?: False
<class '__main__.Example'>
Ist 'self' eine Instanz der Klasse Test?: True
<__main__.Example object at 0x000001E719676FA0>
"""
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@ulipy: Der Konstruktor steht in __blackjack__s Fußnote – vergiss den bitte ganz schnell wieder; den brauchst du in Python nur selten und als Anfänger nie. Dich verwirrt vermutlich noch die Trennung von Klassendefinition und Instanziierung. Das kann oft eine Hürde beim Verständnis von OOP sein. Hier definierst du eine Klasse:

Code: Alles auswählen

class TheClass:
    # ab hier dann die Methoden

und hier legst du eine Instanz an:

Code: Alles auswählen

the_instance = TheClass()
Wie du siehst ist die Klasse ein callable. Der Rückgabewert ist eine Instanz. Rufst du die Klasse öfter auf, erhältst du mehrere Instanzen.

Nehmen wir an, die Klasse implementiert einen Warenkorb mit zwei Methoden, 'reintun' und 'rausnehmen', sowie ein Instanz-Attribut mit dem Inhalt (z.B. eine Liste). Dann kannst du mehrere Instanzen anlegen. Bei allen kannst du etwas reintun und auch wieder rausnehmen. Aber der Inhalt kann sehr unterschiedlich sein.
ulipy
User
Beiträge: 83
Registriert: Mittwoch 17. November 2021, 21:42
Wohnort: Ba-Wü

@__deets__:
Da war wieder meine (absolut ungeübte) Terminologie "schuld", welche erneut Zweifel schürte.

hatte das aus dem Beispiel von @__blackjack__ schon so verstanden, jedoch nicht sauber wiedergegeben. der "Konstruktor" war als Begriff bislang wenig genutzt worden

Das Ganze hin und her wäre in einem Kaffee oder Bar natürlich nicht so abgelaufen.

@__blackjack__: zur Einordnung:
Hatte für persönlichen Bedarf durchaus funktionale und fehlerfrei ablaufende kleinere Programme bis zu der Zeit erstellt, als die OOP-Technologie an Fahrt aufnahm.

D. h. wie gesagt, "prozedural" war die Welt für meinen persönlichen oder gewerblichen Bedarf durchaus "in Ordnung", konnte damit ausreichend sicher umgehen.

Ungefähr ab dem Zeitpunkt, an dem OOP aufkam, war ich kaum mehr codierend "am Ball der Entwicklung", schnappte jedoch immer wieder Grundsätzliches daraus auf.

@Alle
Und jetzt hatten sich die Klärungen und Beiträge hier immer wieder "verheddert", weil sowohl die Abstraktionsebenen unter diesen Voraussetzungen durcheinander kamen als auch "geübte" codierer - natürlicherweise - selten "Schulungssprache" verwenden - das ist einfach ein anderer Bahnhof, der nach einiger Zeit bis auf die verbleibenden "wichtigen" Ausnahmen o. ä. wieder "abgelegt" wird.

Und dann nehmen wir einfach noch die auch nach langer Zeit nicht verbesserte :roll: Flexibilität im Aufsaugen neuer Konzepte einschl. deren konkreter Umsetzung dazu, dann haben wir die Suppe, die wir hatten..

Danke für die Geduld!
Der boot-Vorgang hat auf jeden Fall stattgefunden
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ulipy: Gerade wegen den Begrifflichkeiten und Sprachkonstrukten hatte ich nach der bzw. den Sprachen gefragt, damit man vielleicht leichter Gemeinsamkeiten und Unterschiede zwischen Python und OOP und der oder den Sprachen in denen Du schon Erfahrungen gesammelt hast, in vertrauteren Begriffen erklären kann.

Wobei OOP an sich ja schon sehr alt ist. Ich glaube irgendwann Mitte bis Ende der 1960er hat Alan Kay den Begriff geprägt. Aber ich vermute Du meinst den Zeitpunkt als das in den Mainstream kam, in den 1990ern. Viele prozedurale Sprachen von damals wurden ja mit OOP-Konstrukten erweitert. Ich selbst hatte den ersten etwas verwirrenden Kontakt in der Schule mit Turbo Pascal 5.5.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
ulipy
User
Beiträge: 83
Registriert: Mittwoch 17. November 2021, 21:42
Wohnort: Ba-Wü

@__blackjack__
möchte jetzt ein wenig weiter kommen - deshalb kurz:

Weshalb schreibst du den Namen DEFAULT_SETTINGS groß? Wäre das der empfohlene Stil?

Code: Alles auswählen

DEFAULT_SETTINGS = {
    # system setting
    .
    .
    "del_orphaned": False,  # if true:  del
    .
    .
}
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Solche Fragen beantwortet PEP8, der Styleguide für Python.
ulipy
User
Beiträge: 83
Registriert: Mittwoch 17. November 2021, 21:42
Wohnort: Ba-Wü

sorry - der Grund der Frage war ja, dass ich von einer Abweichung vom Styleguide ausging - ich schau nun spezifischer nach
ulipy
User
Beiträge: 83
Registriert: Mittwoch 17. November 2021, 21:42
Wohnort: Ba-Wü

konnte für empfohlene durchgehende Großschreibung lediglich "constants" finden.

Die Werte der Keys sind ja nicht "konstant", sondern werden vom user oder vom Progamm selbst verändert.

Was konstant ist sind allerdings die Namen der keys selbst.

Ist das nun eine Konstante gemäß styleguide - {{Kopfkratz..}} ???
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn sie vom Programm verändert werden, dann ist das der pöhse(tm) globale Zustand. Und sollte nicht sein. Wenn er vom User verändert wird, past das schon. Sinn und Zweck von konstanten ist ja auch, die zentral änderbar zu machen.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Eine Konstante ist das falls der Benutzer das im Quelltext ändert bevor er das Programm laufen lässt. Oder umgekehrt, wenn das während des Programmlaufs nicht geändert wird. Also wenn das Programm nicht mehr funktioniert wenn man das Wörterbuch in ein `types.MappingProxy` verpackt, dann ist es keine Konstante und gehört dementsprechend auch nicht auf Modulebene, unabhängig von der Schreibweise des Namens. Ich habe das ja auch nicht `SETTINGS` genannt, weil ich davon ausging, dass Du da noch Einstellungen aus JSON lädst und in `DEFAULT_SETTINGS` nur die *Voreinstellungen* drin sind, die gegebenenfalls durch Werte aus der JSON-Datei ”überstimmt” werden. Zum Beispiel in dem man beide Wörterbücher in einer `collections.ChainMap` verbindet.

Und wenn ich Vermutungen über die Bedeutung von den Schlüsseln anstelle, sieht einiges davon auch so aus, als wenn es dafür ganz gut Kommandozeilenargumente geben könnte.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
ulipy
User
Beiträge: 83
Registriert: Mittwoch 17. November 2021, 21:42
Wohnort: Ba-Wü

So schaffen wir das niemals, auch nicht mit Hilfe eines redlich bemühten Murphy...

Eine Handvoll Wörter würden genügen - wie kommen wir da wieder raus???

* ein "user" ist derjenige, der das Programm nutzt, nicht derjenige, der das Python script schreibt

* die geplanten settings (alles key-value) enthalten zwei Arten von settings:

- a) einen Zähler
dieser wird verwendet ausschließlich intern, vom Programm selbst. er zählt die Anzahl der durch den user ausgelösten Programmaufrufe hoch (war leider als Konstante = 0 im code kommentiert..)
Den kann man sicher woanders auch unterbringen - dafür gibts aber momentan keine Not.

- b) weitere key-val-Paare, welche den Programmablauf beeinflussen
diese werden beim ALLERERSTEN durch den user ausgelösten Programmaufruf vom Programm selbst in die json geschrieben.
(davor gibt es außer dem script (und einem funktionalen Python3 - :evil: ) noch nix Weiteres auf der Festplatte des users)

Nach diesem Punkt im ersten Aufruf (ob nun im selben oder in einem der folgenden Aufrufe), kann der user davon abweichende Einstellungen (settings) tätigen. Die genaue Abfolge solcher Möglichkeiten gehört nicht hierher.

Und diese settings werden - um sie dauerhaft festhalten zu können - nach jeder Änderung in der json abgespeichert.

Und ja, es wird auch Kommandozeilen-Parameter geben, die settings betreffend - aber das interessiert hier ja nicht.

Selbstverständlich wollen diverse Programmteile / Funktionen dann und wann auf einen oder auf mehrere werte in den settings zugreifen, abhängig vom script halt. Das ist dann eine globale Verwendung, keine Frage.
Und das ist dann nicht die "böse" Art der Verwendung - denke ich.

Also ist meine Frage bleibt nach diesem Exkurs erhalten:
Ist "dieses" settings nun eine Konstante im Sinne von PEP 8 oder ist es dies nicht?

Falls die Antwort "42" ist, braucht sie natürlich nicht extra erwähnt zu werden - lediglich wenn das eine KONSTANTE wäre, hätte ich überraschendes aus Python dazugelernt :cry:
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ulipy: User ist halt nicht immer so klar getrennt von Programmierer wenn es um Programme geht die irgendwelche Systemautomatisierung oder so machen. Da hat man oft Konstanten im Programm die der Benutzer an *sein* System anpassen kann, manchmal sogar muss, bevor das Programm sinnvoll laufen kann.

Welches Settings meinst Du denn jetzt mit ”dieses”? Wenn das Programm alle Einstellungen erstmalig auf Platte schreiben soll, dann müssen die ja im Programm hinterlegt sein. Zum Beispiel als Konstante `DEFAULT_SETTINGS` die nie verändert wird. Das sind dann ja aber andere Einstellungen als die, die man einliest und dann im Programm verwendet.

Und was das zugreifen auf globale Strukturen angeht, einfach so magisch, ohne das da Argumente an Funktionen übergeben werden, ist das vielleicht nicht zwingend absolut abgrundtief Böse™, IMHO aber unschön bis komisch riechend. Ich würde das vielleicht so versuchen festzunageln: Wenn man keine Unittests schreiben kann die gute Abdeckung über alle Zweige in den Funktionen haben *und* paralellel ausgeführt werden können, dann hat man spätestens dann ein Problem, wenn man in solchem Code Fehler suchen muss, weil der ungünstig über nicht leicht durchschaubaren globalen Zustand zusammenhängt.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
ulipy
User
Beiträge: 83
Registriert: Mittwoch 17. November 2021, 21:42
Wohnort: Ba-Wü

@__blackjack__
ich versuchs nochmal, obwohl dies eigentlich der Tod dieses Threads war, da die kommunikation nicht mehr möglich war.

* ok, user ist nun für diesen Fall geklärt

* ja klar, die defaults sind im Programm hinterlegt - woraus entnimmst du, dass dies nicht der Fall wäre? Das war ja nicht das Thema

* die dynamischen Änderungen an den settings wurden auf vielfache Weise geklärt

* auf unittestts wird bis auf Weiteres bei einem geplanten Umfang von lediglich viel. 2000 zeilen code innerhalb einer einzigen skript-Datei verzichtet

* sicherer als das Lesen und Schreiben dieses settings-dictionaries von beliebiger Stelle im Programm über eine Python-Funktion braucht das nicht gemacht sein. jeder halbwegs "mündige" Programmierer findet diese Funktion bei Bedarf [ctrl] + [f] "Begriff" oder so ähnlich

Nirgends wurde behauptet, dass ein Schreibzugriff direkt im dict erfolgen soll, an beliebiger Stelle - eine solche Idee wäre tatsächlich nicht so doll

* das mit der Magie ist ja nun auch geklärt, meine ich

* das mit der Sucherei auch
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Ich war raus, als du gesagt hast, dass ein Zähler für Programmaufrufe Teil der settings ist.
ulipy
User
Beiträge: 83
Registriert: Mittwoch 17. November 2021, 21:42
Wohnort: Ba-Wü

was meinst du weshalb ich sagte, dass dies momentan niemandem weh tut? Sicher gehört es nicht dort rein...
Niemand macht 2000 Zeilen in einem Rutsch komplett innerhalb eines Tages..
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ulipy: Es ging doch um die Frage ob/was eine Konstante ist, und die Default-Settings sind eine. Und mir war jetzt nicht klar ob Du da eine Trennung zwischen dieser Datenstruktur machst und der wo die Settings aus der externen Datei eingelesen werden.

Die dynamische Änderung an den Settings ist mir auch nicht klar. Also eigentlich sollten die ja gar nicht geändert werden IMHO, also nicht im Programm. Deine Texte klingen aber teilweise so als wenn die JSON über das Programm verändert werden soll und nicht extern in einem Texteditor wie das IMHO normal wäre. Aber ein Programmstartzähler hat da ja zum Beispiel auch nichts zu suchen. Hatte ich nur nichts zu gesagt weil Du das ja wohl selbst weisst.

Ob Du Unittests machst oder nicht war nicht der Punkt, sondern ob das so geschrieben ist das man sie machen *könnte*. Und gut testbaren Code sollte man immer schreiben, denn spätestens bei der Fehlersuche macht man ja Tests, selbst wenn man die nicht festschreibt und wiederholbar macht — warum eigentlich nicht? Und was hat die Programmlänge damit zu tun? Wobei jetzt auch keiner weiss, wie umfangreich das wird. Du nicht, weil Du von ”lediglich“ 2000 Zeilen ausgehst, was aber relativ ist, weil zwar 2000 Zeilen Python-Code schon ziemlich viel ist, weil Python sehr ausdrucksstark ist. Andererseits bist Du ja noch Anfänger, also sind es vielleicht in Wirklichkeit nur 400 bis 500 Zeilen wenn man die tatsächlich in Python schreibt.

Ich habe so ein bisschen das Gefühl Du kennst die Antwort(en) auf Deine Frage(n) eigentlich schon und versuchst hier nur irgendwie eine Bestätigung zu bekommen, das es irgendwie doch okay sein müsste globale Variablen zu verwenden. Oder nicht so wichtig Code testbar zu schreiben. Oder wenn da keine Not zu besteht das sauber zu trennen auch einen Programmstartzähler in die Settings zu basteln.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten